ollama_chat 0.0.55 → 0.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +60 -0
- data/README.md +1 -0
- data/Rakefile +1 -1
- data/lib/ollama_chat/chat.rb +45 -22
- data/lib/ollama_chat/dialog.rb +2 -41
- data/lib/ollama_chat/env_config.rb +9 -0
- data/lib/ollama_chat/information.rb +5 -6
- data/lib/ollama_chat/input_content.rb +27 -21
- data/lib/ollama_chat/ollama_chat_config/default_config.yml +5 -2
- data/lib/ollama_chat/parsing.rb +1 -3
- data/lib/ollama_chat/state_selectors.rb +146 -0
- data/lib/ollama_chat/switches.rb +1 -1
- data/lib/ollama_chat/think_control.rb +11 -39
- data/lib/ollama_chat/version.rb +1 -1
- data/lib/ollama_chat.rb +1 -0
- data/ollama_chat.gemspec +8 -8
- data/spec/ollama_chat/chat_spec.rb +10 -9
- data/spec/ollama_chat/clipboard_spec.rb +1 -1
- data/spec/ollama_chat/information_spec.rb +1 -1
- data/spec/ollama_chat/input_content_spec.rb +15 -6
- data/spec/ollama_chat/message_editing_spec.rb +1 -1
- data/spec/ollama_chat/message_output_spec.rb +1 -1
- data/spec/ollama_chat/model_handling_spec.rb +1 -1
- data/spec/ollama_chat/parsing_spec.rb +7 -24
- data/spec/ollama_chat/source_fetching_spec.rb +1 -3
- data/spec/ollama_chat/state_selectors_spec.rb +193 -0
- data/spec/ollama_chat/think_control_spec.rb +41 -101
- data/spec/ollama_chat/web_searching_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -0
- metadata +10 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0812722ef6dcc9b968a058ad3e4d96a8944ba61aaf347e39b064881e67704c3c'
|
|
4
|
+
data.tar.gz: 03ceba63e04403a982eac23c0a1d5bbf9ff50512f83a721a2def8c5ed8ebec46
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 14949a812f2040b5f4ec0fb767abcb8e41e8ff2f64af2502cc9278d8245f9794e1d7f9bcab0b1b99214c80aa135b1c9b68551a5d208356fa521f3fb36bb8e7f3
|
|
7
|
+
data.tar.gz: 44a2dfcccaa933286b5c0a0a93d6916e4bfd8e2af516d16d3524b4c26ffb76a59fd50557aef8262416fd00e7cb88e12d73fab653a6fda3c470f23f9be937d767
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-01-21 v0.0.57
|
|
4
|
+
|
|
5
|
+
- Introduce `OllamaChat::StateSelectors` module with `StateSelector` class for
|
|
6
|
+
managing configurable states
|
|
7
|
+
- Replace simple string-based document policy and think mode with
|
|
8
|
+
`StateSelector` objects
|
|
9
|
+
- Add `allow_empty` parameter to `StateSelector#initialize` method to allow
|
|
10
|
+
empty states in voice output
|
|
11
|
+
- Update `StateSelector#selected=` to conditionally validate states based on
|
|
12
|
+
`allow_empty?`
|
|
13
|
+
- Refactor voice handling to use `StateSelector` by replacing `@current_voice`
|
|
14
|
+
with `@voices` `StateSelector`
|
|
15
|
+
- Update `FollowChat` to use `@voices.selected` instead of `@current_voice` for
|
|
16
|
+
voice selection
|
|
17
|
+
- Simplify `change_voice` method in `dialog.rb` to delegate to `@voices.choose`
|
|
18
|
+
- Update voice display in `information.rb` to use `@voices.show` instead of raw
|
|
19
|
+
voice name
|
|
20
|
+
- Update configuration format to support nested `think` settings with `mode`
|
|
21
|
+
and `loud` sub-properties
|
|
22
|
+
- Modify command handlers to use `document_policy.choose` and
|
|
23
|
+
`think_mode.choose` instead of legacy methods
|
|
24
|
+
- Update `OllamaChat::Chat` initialization to use `setup_state_selectors`
|
|
25
|
+
method
|
|
26
|
+
- Refactor `OllamaChat::ThinkControl` to use new state selector system
|
|
27
|
+
- Update `OllamaChat::Parsing` to reference `@document_policy.selected` instead
|
|
28
|
+
of `@document_policy`
|
|
29
|
+
- Update default configuration file to use format with nested think settings
|
|
30
|
+
- Add proper `attr_reader` for `document_policy` and `think_mode` state
|
|
31
|
+
selectors
|
|
32
|
+
- Update help text to reference new state selector system
|
|
33
|
+
- Update `OllamaChat::Switches` to handle nested think configuration
|
|
34
|
+
- Add `OllamaChat::StateSelectors` to required files in `lib/ollama_chat.rb`
|
|
35
|
+
|
|
36
|
+
## 2026-01-17 v0.0.56
|
|
37
|
+
|
|
38
|
+
- Updated `context_spook` dependency from version **1.4** to **1.5**
|
|
39
|
+
- Expanded context file inclusion to support YAML files
|
|
40
|
+
- Updated `context_spook` method to pass `format` parameter to
|
|
41
|
+
`ContextSpook::generate_context` calls
|
|
42
|
+
- Added `context` section to default configuration with `format: JSON` setting
|
|
43
|
+
- Added `/reconnect` command to reset Ollama connection
|
|
44
|
+
- Introduced `connect_ollama` method to create new Ollama client instances with
|
|
45
|
+
current configuration
|
|
46
|
+
- Added `base_url` method to resolve connection URL from command-line or
|
|
47
|
+
environment config
|
|
48
|
+
- Updated `handle_input` to process `/reconnect` command and trigger
|
|
49
|
+
reconnection
|
|
50
|
+
- Enhanced `OllamaChat::InputContent#input` method to select and read multiple
|
|
51
|
+
files matching a glob pattern
|
|
52
|
+
- Updated `OllamaChat::InputContent#choose_filename` to accept a `chosen`
|
|
53
|
+
parameter for tracking selections
|
|
54
|
+
- Modified test cases in `spec/ollama_chat/input_content_spec.rb` to verify
|
|
55
|
+
multiple file selection behavior
|
|
56
|
+
- Files are now concatenated with filename headers in the output
|
|
57
|
+
- Maintains backward compatibility with single file selection
|
|
58
|
+
- Uses `Set` for efficient duplicate prevention during selection
|
|
59
|
+
- Removed specialized CSV parsing functionality from `OllamaChat::Parsing`
|
|
60
|
+
module
|
|
61
|
+
- Handle nil from `STDIN.gets` to prevent `NoMethodError`
|
|
62
|
+
|
|
3
63
|
## 2026-01-08 v0.0.55
|
|
4
64
|
|
|
5
65
|
- Added `OllamaChat::Vim` class for inserting text into Vim buffers using the
|
data/README.md
CHANGED
|
@@ -151,6 +151,7 @@ subject - the young, blue-eyed cat.
|
|
|
151
151
|
The following commands can be given inside the chat, if prefixed by a `/`:
|
|
152
152
|
|
|
153
153
|
```
|
|
154
|
+
/reconnect reconnect to current ollama server
|
|
154
155
|
/copy to copy last response to clipboard
|
|
155
156
|
/paste to paste content
|
|
156
157
|
/markdown toggle markdown output
|
data/Rakefile
CHANGED
|
@@ -58,7 +58,7 @@ GemHadar do
|
|
|
58
58
|
dependency 'bigdecimal', '~> 3.1'
|
|
59
59
|
dependency 'csv', '~> 3.0'
|
|
60
60
|
dependency 'const_conf', '~> 0.3'
|
|
61
|
-
dependency 'context_spook', '~> 1.
|
|
61
|
+
dependency 'context_spook', '~> 1.5'
|
|
62
62
|
development_dependency 'all_images', '~> 0.6'
|
|
63
63
|
development_dependency 'rspec', '~> 3.2'
|
|
64
64
|
development_dependency 'kramdown', '~> 2.0'
|
data/lib/ollama_chat/chat.rb
CHANGED
|
@@ -36,6 +36,7 @@ class OllamaChat::Chat
|
|
|
36
36
|
include Term::ANSIColor
|
|
37
37
|
include OllamaChat::DocumentCache
|
|
38
38
|
include OllamaChat::Switches
|
|
39
|
+
include OllamaChat::StateSelectors
|
|
39
40
|
include OllamaChat::ModelHandling
|
|
40
41
|
include OllamaChat::Parsing
|
|
41
42
|
include OllamaChat::SourceFetching
|
|
@@ -88,22 +89,13 @@ class OllamaChat::Chat
|
|
|
88
89
|
@ollama_chat_config = OllamaChat::OllamaChatConfig.new(@opts[?f])
|
|
89
90
|
self.config = @ollama_chat_config.config
|
|
90
91
|
setup_switches(config)
|
|
91
|
-
|
|
92
|
-
@ollama
|
|
93
|
-
connect_timeout: config.timeouts.connect_timeout?,
|
|
94
|
-
read_timeout: config.timeouts.read_timeout?,
|
|
95
|
-
write_timeout: config.timeouts.write_timeout?,
|
|
96
|
-
base_url: base_url,
|
|
97
|
-
debug: ,
|
|
98
|
-
user_agent:
|
|
99
|
-
)
|
|
92
|
+
setup_state_selectors(config)
|
|
93
|
+
@ollama = connect_ollama
|
|
100
94
|
if server_version.version < '0.9.0'.version
|
|
101
95
|
raise ArgumentError, 'require ollama API version 0.9.0 or higher'
|
|
102
96
|
end
|
|
103
|
-
@document_policy = config.document_policy
|
|
104
97
|
@model = choose_model(@opts[?m], config.model.name)
|
|
105
98
|
@model_options = Ollama::Options[config.model.options]
|
|
106
|
-
@think = config.think
|
|
107
99
|
model_system = pull_model_unless_present(@model, @model_options)
|
|
108
100
|
embedding_enabled.set(config.embedding.enabled && !@opts[?E])
|
|
109
101
|
if @opts[?c]
|
|
@@ -119,7 +111,6 @@ class OllamaChat::Chat
|
|
|
119
111
|
end
|
|
120
112
|
@documents = setup_documents
|
|
121
113
|
@cache = setup_cache
|
|
122
|
-
@current_voice = config.voice.default
|
|
123
114
|
@images = []
|
|
124
115
|
@kramdown_ansi_styles = configure_kramdown_ansi_styles
|
|
125
116
|
init_chat_history
|
|
@@ -128,6 +119,18 @@ class OllamaChat::Chat
|
|
|
128
119
|
fix_config(e)
|
|
129
120
|
end
|
|
130
121
|
|
|
122
|
+
# The document_policy reader returns the document policy selector for the chat session.
|
|
123
|
+
#
|
|
124
|
+
# @return [ OllamaChat::StateSelector ] the document policy selector object
|
|
125
|
+
# that manages the policy for handling document references in user text
|
|
126
|
+
attr_reader :document_policy
|
|
127
|
+
|
|
128
|
+
# The think_mode reader returns the think mode selector for the chat session.
|
|
129
|
+
#
|
|
130
|
+
# @return [ OllamaChat::StateSelector ] the think mode selector object
|
|
131
|
+
# that manages the thinking mode setting for the Ollama model interactions
|
|
132
|
+
attr_reader :think_mode
|
|
133
|
+
|
|
131
134
|
# The debug method accesses the debug configuration setting.
|
|
132
135
|
#
|
|
133
136
|
# @return [TrueClass, FalseClass] the current debug mode status
|
|
@@ -213,6 +216,11 @@ class OllamaChat::Chat
|
|
|
213
216
|
# the content to be processed, or nil for no action needed
|
|
214
217
|
def handle_input(content)
|
|
215
218
|
case content
|
|
219
|
+
when %r(^/reconnect)
|
|
220
|
+
STDERR.print green { "Reconnecting to ollama #{base_url.to_s.inspect}…" }
|
|
221
|
+
@ollama = connect_ollama
|
|
222
|
+
STDERR.puts green { " Done." }
|
|
223
|
+
:next
|
|
216
224
|
when %r(^/copy$)
|
|
217
225
|
copy_to_clipboard
|
|
218
226
|
:next
|
|
@@ -307,10 +315,10 @@ class OllamaChat::Chat
|
|
|
307
315
|
info
|
|
308
316
|
:next
|
|
309
317
|
when %r(^/document_policy$)
|
|
310
|
-
|
|
318
|
+
document_policy.choose
|
|
311
319
|
:next
|
|
312
320
|
when %r(^/think$)
|
|
313
|
-
|
|
321
|
+
think_mode.choose
|
|
314
322
|
:next
|
|
315
323
|
when %r(^/think_loud$)
|
|
316
324
|
think_loud.toggle
|
|
@@ -388,9 +396,9 @@ class OllamaChat::Chat
|
|
|
388
396
|
# the specified number of URLs. The processing approach varies based on the current
|
|
389
397
|
# document policy and embedding status:
|
|
390
398
|
#
|
|
391
|
-
# - **Embedding mode**: When
|
|
399
|
+
# - **Embedding mode**: When `document_policy.selected == 'embedding'` AND `@embedding.on?` is true,
|
|
392
400
|
# each result is embedded and the query is interpolated into the `web_embed` prompt.
|
|
393
|
-
# - **Summarizing mode**: When
|
|
401
|
+
# - **Summarizing mode**: When `document_policy.selected == 'summarizing'`,
|
|
394
402
|
# each result is summarized and both query and results are interpolated into the
|
|
395
403
|
# `web_summarize` prompt.
|
|
396
404
|
# - **Importing mode**: For all other cases, each result is imported and both query and
|
|
@@ -406,11 +414,11 @@ class OllamaChat::Chat
|
|
|
406
414
|
# web('3', 'ruby programming tutorials')
|
|
407
415
|
#
|
|
408
416
|
# @example Web search with embedding policy
|
|
409
|
-
# # With
|
|
417
|
+
# # With document_policy.selected == 'embedding' and @embedding.on?
|
|
410
418
|
# # Processes results through embedding pipeline
|
|
411
419
|
#
|
|
412
420
|
# @example Web search with summarizing policy
|
|
413
|
-
# # With
|
|
421
|
+
# # With document_policy.selected == 'summarizing'
|
|
414
422
|
# # Processes results through summarization pipeline
|
|
415
423
|
#
|
|
416
424
|
# @see #search_web
|
|
@@ -420,13 +428,13 @@ class OllamaChat::Chat
|
|
|
420
428
|
# @see #summarize
|
|
421
429
|
def web(count, query)
|
|
422
430
|
urls = search_web(query, count.to_i) or return :next
|
|
423
|
-
if
|
|
431
|
+
if document_policy.selected == 'embedding' && @embedding.on?
|
|
424
432
|
prompt = config.prompts.web_embed
|
|
425
433
|
urls.each do |url|
|
|
426
434
|
fetch_source(url) { |url_io| embed_source(url_io, url) }
|
|
427
435
|
end
|
|
428
436
|
prompt.named_placeholders_interpolate({query:})
|
|
429
|
-
elsif
|
|
437
|
+
elsif document_policy.selected == 'summarizing'
|
|
430
438
|
prompt = config.prompts.web_import
|
|
431
439
|
results = urls.each_with_object('') do |url, content|
|
|
432
440
|
summarize(url).full? do |c|
|
|
@@ -620,7 +628,7 @@ class OllamaChat::Chat
|
|
|
620
628
|
handler = OllamaChat::FollowChat.new(
|
|
621
629
|
chat: self,
|
|
622
630
|
messages:,
|
|
623
|
-
voice: (@
|
|
631
|
+
voice: (@voices.selected if voice.on?)
|
|
624
632
|
)
|
|
625
633
|
begin
|
|
626
634
|
retried = false
|
|
@@ -636,7 +644,7 @@ class OllamaChat::Chat
|
|
|
636
644
|
if think? && !retried
|
|
637
645
|
STDOUT.puts "#{bold('Error')}: in think mode, switch thinking off and retry."
|
|
638
646
|
sleep 1
|
|
639
|
-
|
|
647
|
+
think_mode.selected = 'disabled'
|
|
640
648
|
retried = true
|
|
641
649
|
retry
|
|
642
650
|
else
|
|
@@ -680,6 +688,21 @@ class OllamaChat::Chat
|
|
|
680
688
|
|
|
681
689
|
private
|
|
682
690
|
|
|
691
|
+
def base_url
|
|
692
|
+
@opts[?u] || OllamaChat::EnvConfig::OLLAMA::URL
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
def connect_ollama
|
|
696
|
+
Ollama::Client.new(
|
|
697
|
+
connect_timeout: config.timeouts.connect_timeout?,
|
|
698
|
+
read_timeout: config.timeouts.read_timeout?,
|
|
699
|
+
write_timeout: config.timeouts.write_timeout?,
|
|
700
|
+
base_url: base_url,
|
|
701
|
+
debug: ,
|
|
702
|
+
user_agent:
|
|
703
|
+
)
|
|
704
|
+
end
|
|
705
|
+
|
|
683
706
|
# The setup_documents method initializes the document processing pipeline by
|
|
684
707
|
# configuring the embedding model and database connection.
|
|
685
708
|
# It then loads specified documents into the system and returns the
|
data/lib/ollama_chat/dialog.rb
CHANGED
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
#
|
|
13
13
|
# @example Changing the system prompt
|
|
14
14
|
# chat.change_system_prompt('default_prompt', system: '?sherlock')
|
|
15
|
-
#
|
|
16
|
-
# @example Choosing a document policy
|
|
17
|
-
# chat.choose_document_policy
|
|
18
15
|
module OllamaChat::Dialog
|
|
19
16
|
# The model_with_size method formats a model's size for display
|
|
20
17
|
# by creating a formatted string that includes the model name and its size
|
|
@@ -76,7 +73,7 @@ module OllamaChat::Dialog
|
|
|
76
73
|
# @return [ String ] the user's response with trailing newline removed
|
|
77
74
|
def ask?(prompt:)
|
|
78
75
|
print prompt
|
|
79
|
-
STDIN.gets.chomp
|
|
76
|
+
STDIN.gets.to_s.chomp
|
|
80
77
|
end
|
|
81
78
|
|
|
82
79
|
# The choose_collection method presents a menu to select or create a document
|
|
@@ -104,41 +101,6 @@ module OllamaChat::Dialog
|
|
|
104
101
|
info
|
|
105
102
|
end
|
|
106
103
|
|
|
107
|
-
# The document_policy method sets the policy for handling document imports.
|
|
108
|
-
#
|
|
109
|
-
# @param value [ String ] the document policy to be set
|
|
110
|
-
attr_writer :document_policy
|
|
111
|
-
|
|
112
|
-
# The choose_document_policy method presents a menu to select a document policy.
|
|
113
|
-
# It allows the user to choose from importing, embedding, summarizing, or
|
|
114
|
-
# ignoring documents.
|
|
115
|
-
# The method displays available policies and sets the selected policy as the
|
|
116
|
-
# current document policy.
|
|
117
|
-
# If no valid policy is found, it defaults to the first option.
|
|
118
|
-
# After selection, it outputs the chosen policy and displays the current
|
|
119
|
-
# configuration information.
|
|
120
|
-
def choose_document_policy
|
|
121
|
-
policies = %w[ importing embedding summarizing ignoring ].sort
|
|
122
|
-
current = if policies.index(@document_policy)
|
|
123
|
-
@document_policy
|
|
124
|
-
elsif policies.index(config.document_policy)
|
|
125
|
-
config.document_policy
|
|
126
|
-
else
|
|
127
|
-
policies.first
|
|
128
|
-
end
|
|
129
|
-
policies.unshift('[EXIT]')
|
|
130
|
-
policy = OllamaChat::Utils::Chooser.choose(policies)
|
|
131
|
-
case policy
|
|
132
|
-
when nil, '[EXIT]'
|
|
133
|
-
STDOUT.puts "Exiting chooser."
|
|
134
|
-
policy = current
|
|
135
|
-
end
|
|
136
|
-
self.document_policy = policy
|
|
137
|
-
ensure
|
|
138
|
-
STDOUT.puts "Using document policy #{bold{@document_policy}}."
|
|
139
|
-
info
|
|
140
|
-
end
|
|
141
|
-
|
|
142
104
|
# The change_system_prompt method allows the user to select or enter a new
|
|
143
105
|
# system prompt for the chat session.
|
|
144
106
|
# It provides an interactive chooser when multiple prompts match the given
|
|
@@ -204,8 +166,7 @@ module OllamaChat::Dialog
|
|
|
204
166
|
#
|
|
205
167
|
# @return [ String ] the full name of the chosen voice
|
|
206
168
|
def change_voice
|
|
207
|
-
|
|
208
|
-
@current_voice = chosen.full? || config.voice.default
|
|
169
|
+
@voices.choose
|
|
209
170
|
end
|
|
210
171
|
|
|
211
172
|
# The message_list method creates and returns a new MessageList instance
|
|
@@ -2,6 +2,15 @@ require 'const_conf'
|
|
|
2
2
|
require 'pathname'
|
|
3
3
|
|
|
4
4
|
module OllamaChat
|
|
5
|
+
# Environment configuration module for OllamaChat
|
|
6
|
+
#
|
|
7
|
+
# This module provides a structured way to manage environment variables and
|
|
8
|
+
# configuration settings for the OllamaChat application. It uses the
|
|
9
|
+
# ConstConf library to define and manage configuration parameters with
|
|
10
|
+
# default values, descriptions, and decoding logic.
|
|
11
|
+
#
|
|
12
|
+
# The module organizes configuration into logical sections including general
|
|
13
|
+
# settings, Ollama-specific configurations, and chat-specific options.
|
|
5
14
|
module EnvConfig
|
|
6
15
|
include ConstConf
|
|
7
16
|
|
|
@@ -99,15 +99,13 @@ module OllamaChat::Information
|
|
|
99
99
|
end
|
|
100
100
|
markdown.show
|
|
101
101
|
stream.show
|
|
102
|
-
|
|
102
|
+
think_mode.show
|
|
103
103
|
think_loud.show
|
|
104
104
|
location.show
|
|
105
105
|
voice.show
|
|
106
|
-
|
|
107
|
-
STDOUT.puts " Using voice #{bold{@current_voice}} to speak."
|
|
108
|
-
end
|
|
106
|
+
@voice.on? and @voices.show
|
|
109
107
|
STDOUT.puts "Documents database cache is #{@documents.nil? ? 'n/a' : bold{@documents.cache.class}}"
|
|
110
|
-
STDOUT.puts "Document policy for references in user text: #{bold{
|
|
108
|
+
STDOUT.puts "Document policy for references in user text: #{bold{document_policy}}"
|
|
111
109
|
STDOUT.puts "Currently selected search engine is #{bold(search_engine)}."
|
|
112
110
|
STDOUT.puts "Conversation length: #{bold(@messages.size.to_s)} message(s)."
|
|
113
111
|
nil
|
|
@@ -118,6 +116,7 @@ module OllamaChat::Information
|
|
|
118
116
|
# interface.
|
|
119
117
|
private def display_chat_help_message
|
|
120
118
|
<<~EOT
|
|
119
|
+
/reconnect reconnect to current ollama server
|
|
121
120
|
/copy to copy last response to clipboard
|
|
122
121
|
/paste to paste content
|
|
123
122
|
/markdown toggle markdown output
|
|
@@ -143,7 +142,7 @@ module OllamaChat::Information
|
|
|
143
142
|
/summarize [n] source summarize the source's content in n words
|
|
144
143
|
/embedding toggle embedding paused or not
|
|
145
144
|
/embed source embed the source's content
|
|
146
|
-
/web [n] query query web & for n(=1) results (policy:
|
|
145
|
+
/web [n] query query web & for n(=1) results (policy: #{document_policy})
|
|
147
146
|
/links [clear] display (or clear) links used in the chat
|
|
148
147
|
/save filename store conversation messages
|
|
149
148
|
/load filename load conversation messages
|
|
@@ -8,35 +8,40 @@ require 'tempfile'
|
|
|
8
8
|
# interactive file selection and context collection for enhancing chat
|
|
9
9
|
# interactions with local or remote content.
|
|
10
10
|
module OllamaChat::InputContent
|
|
11
|
-
# The input method
|
|
11
|
+
# The input method selects and reads content from files matching a pattern.
|
|
12
12
|
#
|
|
13
|
-
# This method
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# method returns nil.
|
|
13
|
+
# This method prompts the user to select files matching the given glob
|
|
14
|
+
# pattern, reads their content, and returns a concatenated string with each
|
|
15
|
+
# file's content preceded by its filename.
|
|
17
16
|
#
|
|
18
|
-
# @param pattern [
|
|
17
|
+
# @param pattern [String] the glob pattern to search for files (defaults to '**/*')
|
|
19
18
|
#
|
|
20
|
-
# @return [
|
|
21
|
-
# was chosen
|
|
19
|
+
# @return [String] a concatenated string of file contents with filenames as headers
|
|
22
20
|
def input(pattern)
|
|
23
21
|
pattern ||= '**/*'
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
files = Set[]
|
|
23
|
+
while filename = choose_filename(pattern, chosen: files)
|
|
24
|
+
files << filename
|
|
26
25
|
end
|
|
26
|
+
result = ''
|
|
27
|
+
files.each do |filename|
|
|
28
|
+
result << ("%s:\n\n%s\n\n" % [ filename, File.read(filename) ])
|
|
29
|
+
end
|
|
30
|
+
result.full?
|
|
27
31
|
end
|
|
28
32
|
|
|
29
|
-
# The choose_filename method selects a file from a list of matching files.
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
# them in an interactive chooser menu, and returns the selected filename. If
|
|
33
|
-
# the user chooses to exit or no file is selected, the method returns nil.
|
|
33
|
+
# The choose_filename method selects a file from a list of matching files. It
|
|
34
|
+
# searches for files matching the given pattern, excludes already chosen
|
|
35
|
+
# files, and presents them in an interactive chooser menu.
|
|
34
36
|
#
|
|
35
|
-
# @param pattern [ String ] the glob pattern to search for files
|
|
37
|
+
# @param pattern [ String ] the glob pattern to search for files
|
|
38
|
+
# @param chosen [ Set ] a set of already chosen filenames to exclude from
|
|
39
|
+
# selection
|
|
36
40
|
#
|
|
37
|
-
# @return [ String, nil ] the
|
|
38
|
-
def choose_filename(pattern)
|
|
39
|
-
files = Dir.glob(pattern).
|
|
41
|
+
# @return [ String, nil ] the selected filename or nil if no file was chosen or user exited
|
|
42
|
+
def choose_filename(pattern, chosen: nil)
|
|
43
|
+
files = Dir.glob(pattern).reject { chosen&.member?(_1) }.
|
|
44
|
+
select { File.file?(_1) }
|
|
40
45
|
files.unshift('[EXIT]')
|
|
41
46
|
case chosen = OllamaChat::Utils::Chooser.choose(files)
|
|
42
47
|
when '[EXIT]', nil
|
|
@@ -75,8 +80,9 @@ module OllamaChat::InputContent
|
|
|
75
80
|
# @example Load default context
|
|
76
81
|
# context_spook(nil)
|
|
77
82
|
def context_spook(patterns)
|
|
83
|
+
format = config.context.format
|
|
78
84
|
if patterns
|
|
79
|
-
ContextSpook::generate_context(verbose: true) do |context|
|
|
85
|
+
ContextSpook::generate_context(verbose: true, format:) do |context|
|
|
80
86
|
context do
|
|
81
87
|
Dir.glob(patterns).each do |filename|
|
|
82
88
|
File.file?(filename) or next
|
|
@@ -86,7 +92,7 @@ module OllamaChat::InputContent
|
|
|
86
92
|
end.to_json
|
|
87
93
|
else
|
|
88
94
|
if context_filename = choose_filename('.contexts/*.rb')
|
|
89
|
-
ContextSpook.generate_context(context_filename, verbose: true).to_json
|
|
95
|
+
ContextSpook.generate_context(context_filename, verbose: true, format:).to_json
|
|
90
96
|
end
|
|
91
97
|
end
|
|
92
98
|
end
|
data/lib/ollama_chat/parsing.rb
CHANGED
|
@@ -30,8 +30,6 @@ module OllamaChat::Parsing
|
|
|
30
30
|
end
|
|
31
31
|
source_io.rewind
|
|
32
32
|
source_io.read
|
|
33
|
-
when 'text/csv'
|
|
34
|
-
parse_csv(source_io)
|
|
35
33
|
when 'application/rss+xml'
|
|
36
34
|
parse_rss(source_io)
|
|
37
35
|
when 'application/atom+xml'
|
|
@@ -247,7 +245,7 @@ module OllamaChat::Parsing
|
|
|
247
245
|
when 'image'
|
|
248
246
|
add_image(images, source_io, source)
|
|
249
247
|
when 'text', 'application', nil
|
|
250
|
-
case
|
|
248
|
+
case document_policy.selected
|
|
251
249
|
when 'ignoring'
|
|
252
250
|
nil
|
|
253
251
|
when 'importing'
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# A module that provides state selection functionality for OllamaChat.
|
|
2
|
+
#
|
|
3
|
+
# The StateSelectors module encapsulates the StateSelector class, which manages
|
|
4
|
+
# configurable states with selection and display capabilities. It is used to
|
|
5
|
+
# handle various settings in the chat application such as document policies and
|
|
6
|
+
# think modes, allowing users to dynamically configure
|
|
7
|
+
# different aspects of the chat session behavior.
|
|
8
|
+
module OllamaChat::StateSelectors
|
|
9
|
+
# A state selector that manages configurable states with selection and
|
|
10
|
+
# display capabilities.
|
|
11
|
+
class StateSelector
|
|
12
|
+
include Term::ANSIColor
|
|
13
|
+
|
|
14
|
+
# Initializes a new StateSelector with the given configuration.
|
|
15
|
+
#
|
|
16
|
+
# @param name [String] The name of the state selector for display purposes
|
|
17
|
+
# @param states [Array<String>] The list of valid states this selector can have
|
|
18
|
+
# @param default [String, nil] The default state to select (must be one of +states+)
|
|
19
|
+
# @param off [Array<String>, nil] The list of states that should be considered "off"
|
|
20
|
+
# @raise [ArgumentError] If +states+ is empty or +default+ is not in +states+
|
|
21
|
+
def initialize(name:, states:, default: nil, off: nil, allow_empty: false)
|
|
22
|
+
@name = name.to_s
|
|
23
|
+
@states = Set.new(states.map(&:to_s))
|
|
24
|
+
@allow_empty = allow_empty
|
|
25
|
+
unless allow_empty
|
|
26
|
+
@states.empty? and raise ArgumentError, 'states cannot be empty'
|
|
27
|
+
end
|
|
28
|
+
if default
|
|
29
|
+
@default = default.to_s
|
|
30
|
+
unless allow_empty?
|
|
31
|
+
@states.member?(@default) or raise ArgumentError,
|
|
32
|
+
"default has to be one of #{@states.to_a * ', '}."
|
|
33
|
+
end
|
|
34
|
+
@selected = @default
|
|
35
|
+
else
|
|
36
|
+
@selected = @states.first
|
|
37
|
+
end
|
|
38
|
+
@off = Array(off)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# The selected reader returns the currently selected state of the switch.
|
|
42
|
+
#
|
|
43
|
+
# @return [Object] the currently selected state value
|
|
44
|
+
attr_reader :selected
|
|
45
|
+
|
|
46
|
+
# The selected= method sets the selected state of the switch.
|
|
47
|
+
#
|
|
48
|
+
# @param value [Object] the value to be converted to a string and set as
|
|
49
|
+
# the selected state
|
|
50
|
+
#
|
|
51
|
+
# @raise [ArgumentError] if the provided value is not one of the valid states
|
|
52
|
+
def selected=(value)
|
|
53
|
+
value = value.to_s
|
|
54
|
+
unless allow_empty?
|
|
55
|
+
@states.member?(value) or raise ArgumentError,
|
|
56
|
+
"value has to be one of #{@states.to_a * ', '}."
|
|
57
|
+
end
|
|
58
|
+
@selected = value
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The allow_empty? method checks if the switch is allowed to be empty.
|
|
62
|
+
#
|
|
63
|
+
# @return [ TrueClass, FalseClass ] true if the switch is allowed to be
|
|
64
|
+
# empty, false otherwise
|
|
65
|
+
def allow_empty?
|
|
66
|
+
!!@allow_empty
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The off? method checks if the current state is in the off set.
|
|
70
|
+
#
|
|
71
|
+
# @return [ TrueClass, FalseClass ] true if the selected state is in the
|
|
72
|
+
# off set, false otherwise
|
|
73
|
+
def off?
|
|
74
|
+
@off.member?(@selected)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The on? method checks if the switch is in the on state, returning true if
|
|
78
|
+
# it is enabled and false if it is disabled.
|
|
79
|
+
#
|
|
80
|
+
# @return [ TrueClass, FalseClass ] true if the switch is on, false if it
|
|
81
|
+
# is off
|
|
82
|
+
def on?
|
|
83
|
+
!off?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# The choose method presents a menu to select from available states.
|
|
87
|
+
#
|
|
88
|
+
# This method displays the available states to the user and allows them to
|
|
89
|
+
# select one. It handles the user's choice by updating the selected state
|
|
90
|
+
# or exiting the chooser if the user selects '[EXIT]' or cancels the selection.
|
|
91
|
+
#
|
|
92
|
+
# @return [ nil ] This method does not return a value; it updates the instance
|
|
93
|
+
# variable @selected based on user input.
|
|
94
|
+
def choose
|
|
95
|
+
states = @states + [ '[EXIT]' ]
|
|
96
|
+
case chosen = OllamaChat::Utils::Chooser.choose(states)
|
|
97
|
+
when '[EXIT]', nil
|
|
98
|
+
STDOUT.puts "Exiting chooser."
|
|
99
|
+
when
|
|
100
|
+
@selected = chosen
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# The show method outputs the current value of the state selector.
|
|
105
|
+
#
|
|
106
|
+
# This method displays the name of the state selector along with its
|
|
107
|
+
# currently selected state in a formatted message to standard output.
|
|
108
|
+
def show
|
|
109
|
+
STDOUT.puts "#{@name} is #{bold(to_s)}."
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# The to_s method returns the string representation of the selected state.
|
|
113
|
+
#
|
|
114
|
+
# @return [ String ] the string representation of the currently selected
|
|
115
|
+
# state
|
|
116
|
+
def to_s
|
|
117
|
+
@selected.to_s
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Sets up state selectors for document policy and think mode based on the
|
|
122
|
+
# provided configuration.
|
|
123
|
+
#
|
|
124
|
+
# @param config [ComplexConfig::Settings] the configuration object containing
|
|
125
|
+
# settings for document policy and think mode
|
|
126
|
+
def setup_state_selectors(config)
|
|
127
|
+
@document_policy = StateSelector.new(
|
|
128
|
+
name: 'Document policy',
|
|
129
|
+
default: config.document_policy,
|
|
130
|
+
states: %w[ embedding ignoring importing summarizing ],
|
|
131
|
+
off: %w[ ignoring ],
|
|
132
|
+
)
|
|
133
|
+
@think_mode = StateSelector.new(
|
|
134
|
+
name: 'Think mode',
|
|
135
|
+
default: config.think.mode,
|
|
136
|
+
states: %w[ enabled disabled low medium high ],
|
|
137
|
+
off: %w[ disabled ],
|
|
138
|
+
)
|
|
139
|
+
@voices = StateSelector.new(
|
|
140
|
+
name: 'Voice',
|
|
141
|
+
default: config.voice.default,
|
|
142
|
+
states: config.voice.list,
|
|
143
|
+
allow_empty: true
|
|
144
|
+
)
|
|
145
|
+
end
|
|
146
|
+
end
|
data/lib/ollama_chat/switches.rb
CHANGED
|
@@ -192,7 +192,7 @@ module OllamaChat::Switches
|
|
|
192
192
|
)
|
|
193
193
|
|
|
194
194
|
@think_loud = Switch.new(
|
|
195
|
-
value: config.
|
|
195
|
+
value: config.think.loud,
|
|
196
196
|
msg: {
|
|
197
197
|
true => "Thinking out loud, show thinking annotations.",
|
|
198
198
|
false => "Thinking silently, don't show thinking annotations.",
|