ollama_chat 0.0.70 → 0.0.71
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 +40 -0
- data/README.md +1 -1
- data/lib/ollama_chat/chat.rb +3 -1
- data/lib/ollama_chat/clipboard.rb +72 -29
- data/lib/ollama_chat/conversation.rb +5 -5
- data/lib/ollama_chat/follow_chat.rb +8 -4
- data/lib/ollama_chat/information.rb +1 -1
- data/lib/ollama_chat/message_format.rb +2 -2
- data/lib/ollama_chat/message_list.rb +34 -1
- data/lib/ollama_chat/ollama_chat_config/default_config.yml +27 -12
- data/lib/ollama_chat/tools/copy_to_clipboard.rb +54 -0
- data/lib/ollama_chat/tools/paste_from_clipboard.rb +56 -0
- data/lib/ollama_chat/tools.rb +4 -2
- data/lib/ollama_chat/version.rb +1 -1
- data/ollama_chat.gemspec +5 -5
- data/spec/ollama_chat/chat_spec.rb +6 -1
- data/spec/ollama_chat/clipboard_spec.rb +6 -6
- data/spec/ollama_chat/follow_chat_spec.rb +2 -2
- data/spec/ollama_chat/message_list_spec.rb +35 -12
- data/spec/ollama_chat/tools/copy_to_clipboard_spec.rb +91 -0
- data/spec/ollama_chat/tools/paste_from_clipboard_spec.rb +91 -0
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e83451e14cc4c204b237950b58832b231440487cf490e9434ee127654e849e22
|
|
4
|
+
data.tar.gz: 8fb94fb04d963e05d778edc13af7c0988f3d7f180ea17af90d51a6d5bf07a74c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b2cca9e66e8063fd891ffafeac1c32c7a18467056d4b64c04476cb31154be6f23b6fd13ad3b38299c63e73bdaa73813048cf7e89150d398f4dd21de39a4c3d3a
|
|
7
|
+
data.tar.gz: cd134c0ff8544014765e792e104c76a47c1511d4f219665364eda23e52c7b6dcd382058d935c54658ef93407a0a697227cc2cef88510b8555c4a294ac4102d9e
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-02-26 v0.0.71
|
|
4
|
+
|
|
5
|
+
- Add new clipboard utilities: `tools/copy_to_clipboard.rb` and
|
|
6
|
+
`tools/paste_from_clipboard.rb`.
|
|
7
|
+
- Update gemspec to include the new tools in `s.extra_rdoc_files`, `s.files`,
|
|
8
|
+
and `s.test_files`.
|
|
9
|
+
- Update stub comment in `ollama_chat.gemspec` to reflect the new version.
|
|
10
|
+
- Enable more tools by default
|
|
11
|
+
- Rename `think_loud?` to `think?` in `follow_chat.rb` for storage logic;
|
|
12
|
+
update `last_message_with_user` to conditionally include thinking content;
|
|
13
|
+
remove empty string from `output_eval_stats`; add test for saving
|
|
14
|
+
conversations with thinking content in `message_list_spec.rb`; update spec
|
|
15
|
+
expectations to use `think_loud?: false` for display behavior.
|
|
16
|
+
- Replace `/paste` command to use `paste_from_clipboard`; add
|
|
17
|
+
`perform_paste_from_clipboard` method in `lib/ollama_chat/clipboard.rb`; add
|
|
18
|
+
`paste_from_clipboard` tool in
|
|
19
|
+
`lib/ollama_chat/tools/paste_from_clipboard.rb`; add `paste: pfc`
|
|
20
|
+
configuration option; update tool defaults in configuration; update existing
|
|
21
|
+
tests to use new method names; add new spec file for `paste_from_clipboard`
|
|
22
|
+
tool.
|
|
23
|
+
- Add `OllamaChat::Tools::CopyToClipboard` tool that integrates with chat tool
|
|
24
|
+
system; implement `MessageList#find_last` method with optional `content`
|
|
25
|
+
parameter to filter empty messages; enhance
|
|
26
|
+
`Clipboard#perform_copy_to_clipboard` with better YARD documentation and
|
|
27
|
+
error handling; update `Clipboard#copy_to_clipboard` with comprehensive YARD
|
|
28
|
+
documentation; add comprehensive test coverage for new clipboard tool and
|
|
29
|
+
message finding functionality; integrate clipboard functionality with
|
|
30
|
+
existing configuration system using `config.copy`; update success message
|
|
31
|
+
text from "copied to the system clipboard" to "successfully copied to the
|
|
32
|
+
system clipboard".
|
|
33
|
+
- Add interactive help mode with `/help me` command handler in
|
|
34
|
+
`lib/ollama_chat/chat.rb`; add `help` prompt template to
|
|
35
|
+
`lib/ollama_chat/ollama_chat_config/default_config.yml`; update help text in
|
|
36
|
+
`README.md` and `lib/ollama_chat/information.rb`; add test coverage in
|
|
37
|
+
`spec/ollama_chat/chat_spec.rb`.
|
|
38
|
+
- Make `Pathname` output quoted for string interpolation: replace
|
|
39
|
+
`filename.inspect` with `filename.to_s.inspect` in `save_conversation` and
|
|
40
|
+
`load_conversation` methods; update three locations in
|
|
41
|
+
`lib/ollama_chat/conversation.rb`.
|
|
42
|
+
|
|
3
43
|
## 2026-02-23 v0.0.70
|
|
4
44
|
|
|
5
45
|
- Added `generate_password` tool with secure password generation, supporting
|
data/README.md
CHANGED
|
@@ -190,7 +190,7 @@ The following commands can be given inside the chat, if prefixed by a `/`:
|
|
|
190
190
|
/tools [enable|disable|on|off] list enabled, enable/disable tools, support on/off
|
|
191
191
|
/vim insert the last message into a vim server
|
|
192
192
|
/quit to quit
|
|
193
|
-
/help
|
|
193
|
+
/help [me] to view this help (me = interactive ai help)
|
|
194
194
|
```
|
|
195
195
|
|
|
196
196
|
### Using `ollama_chat_send` to send input to a running `ollama_chat`
|
data/lib/ollama_chat/chat.rb
CHANGED
|
@@ -222,7 +222,7 @@ class OllamaChat::Chat
|
|
|
222
222
|
copy_to_clipboard
|
|
223
223
|
:next
|
|
224
224
|
when %r(^/paste$)
|
|
225
|
-
|
|
225
|
+
paste_from_clipboard
|
|
226
226
|
when %r(^/markdown$)
|
|
227
227
|
markdown.toggle
|
|
228
228
|
:next
|
|
@@ -396,6 +396,8 @@ class OllamaChat::Chat
|
|
|
396
396
|
when %r(^/quit$), nil
|
|
397
397
|
STDOUT.puts "Goodbye."
|
|
398
398
|
:return
|
|
399
|
+
when %r(^/help me$)
|
|
400
|
+
config.prompts.help % { commands: display_chat_help_message }
|
|
399
401
|
when %r(^/)
|
|
400
402
|
display_chat_help
|
|
401
403
|
:next
|
|
@@ -4,50 +4,93 @@
|
|
|
4
4
|
# This module enables users to copy the last assistant message to the system
|
|
5
5
|
# clipboard and paste content from input, facilitating easy transfer of
|
|
6
6
|
# conversation content between different applications and contexts.
|
|
7
|
-
#
|
|
8
|
-
# @example Copying a message to clipboard
|
|
9
|
-
# chat.copy_to_clipboard
|
|
10
|
-
#
|
|
11
|
-
# @example Pasting content from input
|
|
12
|
-
# content = chat.paste_from_input
|
|
13
7
|
module OllamaChat::Clipboard
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Copy the last assistant's message to the system clipboard.
|
|
8
|
+
# Copies the last assistant message to the system clipboard.
|
|
17
9
|
#
|
|
18
|
-
# This method
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# If no assistant response is available or the clipboard command is not
|
|
22
|
-
# found, appropriate error messages are displayed.
|
|
10
|
+
# This method finds the most recent message from the assistant and writes
|
|
11
|
+
# its content to the system clipboard using the command specified in
|
|
12
|
+
# the configuration (config.copy).
|
|
23
13
|
#
|
|
24
|
-
# @
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
# @param content [Boolean] If true, copies the content of the message;
|
|
15
|
+
# if false, copies the entire message object (default: false)
|
|
16
|
+
#
|
|
17
|
+
# @raise [OllamaChat::OllamaChatError] if the clipboard command specified
|
|
18
|
+
# in config.copy is not found in the system's PATH
|
|
19
|
+
# @raise [OllamaChat::OllamaChatError] if no assistant message is available
|
|
20
|
+
# to copy to the clipboard
|
|
21
|
+
def perform_copy_to_clipboard(content: false)
|
|
22
|
+
if message = @messages.find_last(content:) { _1.role == 'assistant' }
|
|
27
23
|
copy = `which #{config.copy}`.chomp
|
|
28
24
|
if copy.present?
|
|
29
25
|
IO.popen(copy, 'w') do |clipboard|
|
|
30
26
|
clipboard.write(message.content)
|
|
31
27
|
end
|
|
32
|
-
STDOUT.puts "The last response has been copied to the system clipboard."
|
|
33
28
|
else
|
|
34
|
-
|
|
29
|
+
raise OllamaChat::OllamaChatError, "#{config.copy.inspect} command not found in system's path!"
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
raise OllamaChat::OllamaChatError, "No response available to copy to the system clipboard."
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Performs the actual clipboard paste operation.
|
|
37
|
+
#
|
|
38
|
+
# This method executes the configured clipboard paste command to retrieve
|
|
39
|
+
# content from the system clipboard. It uses the command specified in the
|
|
40
|
+
# configuration (`config.paste`) to fetch clipboard content.
|
|
41
|
+
#
|
|
42
|
+
# @return [String] The content retrieved from the system clipboard
|
|
43
|
+
# @raise [OllamaChat::OllamaChatError] if the clipboard command is not found
|
|
44
|
+
# or if there is no content available to paste
|
|
45
|
+
#
|
|
46
|
+
# @example
|
|
47
|
+
# # Assuming config.paste is "pfc"
|
|
48
|
+
# content = perform_paste_from_clipboard
|
|
49
|
+
# # => "Some content from clipboard"
|
|
50
|
+
def perform_paste_from_clipboard
|
|
51
|
+
paste = `which #{config.paste}`.chomp
|
|
52
|
+
if paste.present?
|
|
53
|
+
IO.popen(paste, 'r') do |clipboard|
|
|
54
|
+
text = clipboard.read
|
|
55
|
+
if text.empty?
|
|
56
|
+
raise OllamaChat::OllamaChatError,
|
|
57
|
+
"No content available to paste from the system clipboard."
|
|
58
|
+
else
|
|
59
|
+
return text
|
|
60
|
+
end
|
|
35
61
|
end
|
|
36
62
|
else
|
|
37
|
-
|
|
63
|
+
raise OllamaChat::OllamaChatError,
|
|
64
|
+
"#{config.paste.inspect} command not found in system's path!"
|
|
38
65
|
end
|
|
39
|
-
nil
|
|
40
66
|
end
|
|
41
67
|
|
|
42
|
-
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Copies the last assistant message to the system clipboard.
|
|
43
71
|
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
72
|
+
# This method is the interface for copying assistant messages to the
|
|
73
|
+
# clipboard in the chat. It calls perform_copy_to_clipboard internally and
|
|
74
|
+
# handles any OllamaChat::OllamaChatError exceptions by printing the error
|
|
75
|
+
# message to standard error and does not re-raise the exception.
|
|
76
|
+
def copy_to_clipboard
|
|
77
|
+
perform_copy_to_clipboard
|
|
78
|
+
STDOUT.puts "The last response has been successfully copied to the system clipboard."
|
|
79
|
+
rescue OllamaChat::OllamaChatError => e
|
|
80
|
+
STDERR.puts e.message
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Pastes content from the system clipboard into the chat.
|
|
47
84
|
#
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
85
|
+
# This method retrieves content from the system clipboard using the
|
|
86
|
+
# configured paste command and integrates it into the chat session. It
|
|
87
|
+
# handles clipboard errors gracefully by displaying error messages to
|
|
88
|
+
# standard error.
|
|
89
|
+
def paste_from_clipboard
|
|
90
|
+
result = perform_paste_from_clipboard
|
|
91
|
+
STDOUT.puts "The clipboard content has been successfully copied to the chat."
|
|
92
|
+
result
|
|
93
|
+
rescue OllamaChat::OllamaChatError => e
|
|
94
|
+
STDERR.puts e.message
|
|
52
95
|
end
|
|
53
96
|
end
|
|
@@ -27,12 +27,12 @@ module OllamaChat::Conversation
|
|
|
27
27
|
# chat.save_conversation('conversations/2023-10-15_my_session.json')
|
|
28
28
|
def save_conversation(filename)
|
|
29
29
|
File.exist?(filename) &&
|
|
30
|
-
ask?(prompt: "File #{filename.inspect} already exists, overwrite? (y/n) ") !~ /\Ay/i and
|
|
30
|
+
ask?(prompt: "File #{filename.to_s.inspect} already exists, overwrite? (y/n) ") !~ /\Ay/i and
|
|
31
31
|
return
|
|
32
32
|
if messages.save_conversation(filename)
|
|
33
|
-
STDOUT.puts "Saved conversation to #{filename.inspect}."
|
|
33
|
+
STDOUT.puts "Saved conversation to #{filename.to_s.inspect}."
|
|
34
34
|
else
|
|
35
|
-
STDERR.puts "Saving conversation to #{filename.inspect} failed."
|
|
35
|
+
STDERR.puts "Saving conversation to #{filename.to_s.inspect} failed."
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -55,9 +55,9 @@ module OllamaChat::Conversation
|
|
|
55
55
|
messages.list_conversation(2)
|
|
56
56
|
end
|
|
57
57
|
if success
|
|
58
|
-
STDOUT.puts "Loaded conversation from #{filename.inspect}."
|
|
58
|
+
STDOUT.puts "Loaded conversation from #{filename.to_s.inspect}."
|
|
59
59
|
else
|
|
60
|
-
STDERR.puts "Loading conversation from #{filename.inspect} failed."
|
|
60
|
+
STDERR.puts "Loading conversation from #{filename.to_s.inspect} failed."
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
|
@@ -195,7 +195,7 @@ class OllamaChat::FollowChat
|
|
|
195
195
|
# and thinking
|
|
196
196
|
def update_last_message(response)
|
|
197
197
|
@messages.last.content << response.message&.content
|
|
198
|
-
if @chat.
|
|
198
|
+
if @chat.think? and response_thinking = response.message&.thinking.full?
|
|
199
199
|
@messages.last.thinking << response_thinking
|
|
200
200
|
end
|
|
201
201
|
end
|
|
@@ -218,7 +218,7 @@ class OllamaChat::FollowChat
|
|
|
218
218
|
content, thinking = @messages.last.content, @messages.last.thinking
|
|
219
219
|
if @chat.markdown.on?
|
|
220
220
|
content = talk_annotate { truncate_for_terminal @chat.kramdown_ansi_parse(content) }
|
|
221
|
-
if @chat.
|
|
221
|
+
if @chat.think?
|
|
222
222
|
thinking = think_annotate { truncate_for_terminal@chat.kramdown_ansi_parse(thinking) }
|
|
223
223
|
end
|
|
224
224
|
else
|
|
@@ -237,7 +237,11 @@ class OllamaChat::FollowChat
|
|
|
237
237
|
# terminal display
|
|
238
238
|
def last_message_with_user
|
|
239
239
|
content, thinking = prepare_last_message
|
|
240
|
-
|
|
240
|
+
if thinking.present?
|
|
241
|
+
[ @user, ?\n, thinking, ?\n, content ]
|
|
242
|
+
else
|
|
243
|
+
[ @user, ?\n, content ]
|
|
244
|
+
end
|
|
241
245
|
end
|
|
242
246
|
|
|
243
247
|
# The display_formatted_terminal_output method formats and outputs the
|
|
@@ -302,7 +306,7 @@ class OllamaChat::FollowChat
|
|
|
302
306
|
# @param response [ Object ] the response object containing evaluation data
|
|
303
307
|
def output_eval_stats(response)
|
|
304
308
|
response.done or return
|
|
305
|
-
@output.puts "",
|
|
309
|
+
@output.puts "", eval_stats(response)
|
|
306
310
|
end
|
|
307
311
|
|
|
308
312
|
# The debug_output method conditionally outputs the response object using jj
|
|
@@ -156,7 +156,7 @@ module OllamaChat::Information
|
|
|
156
156
|
/tools [enable|disable|on|off] list enabled, enable/disable tools, support on/off
|
|
157
157
|
/vim insert the last message into a vim server
|
|
158
158
|
/quit to quit
|
|
159
|
-
/help
|
|
159
|
+
/help [me] to view this help (me = interactive ai help)
|
|
160
160
|
EOT
|
|
161
161
|
end
|
|
162
162
|
|
|
@@ -34,7 +34,7 @@ module OllamaChat::MessageFormat
|
|
|
34
34
|
def think_annotate(&block)
|
|
35
35
|
string = block.()
|
|
36
36
|
string.to_s.size == 0 and return
|
|
37
|
-
if @chat.
|
|
37
|
+
if @chat.think_loud?
|
|
38
38
|
"💭\n#{string}\n"
|
|
39
39
|
end
|
|
40
40
|
end
|
|
@@ -48,7 +48,7 @@ module OllamaChat::MessageFormat
|
|
|
48
48
|
def talk_annotate(&block)
|
|
49
49
|
string = block.()
|
|
50
50
|
string.to_s.size == 0 and return
|
|
51
|
-
if @chat.
|
|
51
|
+
if @chat.think_loud?
|
|
52
52
|
"💬\n#{string}\n"
|
|
53
53
|
else
|
|
54
54
|
string
|
|
@@ -90,6 +90,39 @@ class OllamaChat::MessageList
|
|
|
90
90
|
@messages.last
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
+
# Find the *last* message that satisfies the supplied block.
|
|
94
|
+
#
|
|
95
|
+
# @param content [Boolean] If `true`, skip messages that have no content
|
|
96
|
+
# (`m.content.present?` is `false`). This is useful when you only care
|
|
97
|
+
# about messages that actually contain a payload (e.g. assistant
|
|
98
|
+
# replies, user queries, etc.).
|
|
99
|
+
#
|
|
100
|
+
# @yield [Message] yields each message in reverse order (from newest to
|
|
101
|
+
# oldest) until the block returns a truthy value.
|
|
102
|
+
#
|
|
103
|
+
# @yieldparam [OllamaChat::Message] message the current message being inspected
|
|
104
|
+
# @yieldreturn [Boolean] whether the message matches the criteria
|
|
105
|
+
#
|
|
106
|
+
# @return [OllamaChat::Message, nil] the first message that matches the
|
|
107
|
+
# block, or `nil` if none match.
|
|
108
|
+
#
|
|
109
|
+
# @example Find the last assistant message that contains content
|
|
110
|
+
# last_assistant = message_list.find_last(content: true) { |m| m.role == 'assistant' }
|
|
111
|
+
#
|
|
112
|
+
# @example Find the last user message regardless of content
|
|
113
|
+
# last_user = message_list.find_last { |m| m.role == 'user' }
|
|
114
|
+
#
|
|
115
|
+
# @note The method iterates in reverse order (`reverse_each`) so that
|
|
116
|
+
# the *most recent* matching message is returned. It also respects
|
|
117
|
+
# the `content` flag to skip empty messages, which is handy when the
|
|
118
|
+
# chat history contains empty messages e. g. when tool calling.
|
|
119
|
+
def find_last(content: false, &block)
|
|
120
|
+
@messages.reverse_each.find { |m|
|
|
121
|
+
content and !m.content.present? and next
|
|
122
|
+
block.(m)
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
|
|
93
126
|
# The second_last method returns the second-to-last message from the
|
|
94
127
|
# conversation if there are more than one non-system messages.
|
|
95
128
|
#
|
|
@@ -340,7 +373,7 @@ class OllamaChat::MessageList
|
|
|
340
373
|
when 'system' then 213
|
|
341
374
|
else 210
|
|
342
375
|
end
|
|
343
|
-
thinking = if @chat.
|
|
376
|
+
thinking = if @chat.think_loud?
|
|
344
377
|
think_annotate do
|
|
345
378
|
message.thinking.full? { @chat.markdown.on? ? @chat.kramdown_ansi_parse(_1) : _1 }
|
|
346
379
|
end
|
|
@@ -31,6 +31,14 @@ prompts:
|
|
|
31
31
|
|
|
32
32
|
%{results}
|
|
33
33
|
location: You are at %{location_name}, %{location_decimal_degrees}, preferring %{units}
|
|
34
|
+
help: |
|
|
35
|
+
Wait for the user to ask questions about the usage of chat commands. Just
|
|
36
|
+
list the command names separated by spaces (no descriptions yet) and
|
|
37
|
+
offer to answer any questions about any of them. Interactively help the
|
|
38
|
+
user by answering questions about the following
|
|
39
|
+
chat commands:
|
|
40
|
+
|
|
41
|
+
%{commands}
|
|
34
42
|
system_prompts:
|
|
35
43
|
default: <%= OC::OLLAMA::CHAT::SYSTEM || 'null' %>
|
|
36
44
|
assistant: You are a helpful assistant.
|
|
@@ -74,6 +82,7 @@ working_dir_dependent_socket: true
|
|
|
74
82
|
request_headers:
|
|
75
83
|
Accept: 'text/*,application/*,image/*'
|
|
76
84
|
ssl_no_verify: []
|
|
85
|
+
paste: pfc # Paste clipboard content to chat app
|
|
77
86
|
copy: ctc # Copy stdin to clipboard app
|
|
78
87
|
web_search:
|
|
79
88
|
use: duckduckgo
|
|
@@ -92,7 +101,7 @@ tools:
|
|
|
92
101
|
default: false
|
|
93
102
|
get_cve:
|
|
94
103
|
url: 'https://cveawg.mitre.org/api/cve/%{cve_id}'
|
|
95
|
-
default:
|
|
104
|
+
default: true
|
|
96
105
|
get_endoflife:
|
|
97
106
|
url: "https://endoflife.date/api/v1/products/%{product}"
|
|
98
107
|
default: false
|
|
@@ -102,12 +111,12 @@ tools:
|
|
|
102
111
|
default: true
|
|
103
112
|
file_context:
|
|
104
113
|
default: false
|
|
105
|
-
require_confirmation:
|
|
114
|
+
require_confirmation: false
|
|
106
115
|
allowed:
|
|
107
|
-
- ./spec
|
|
116
|
+
- './spec'
|
|
108
117
|
directory_structure:
|
|
109
|
-
default:
|
|
110
|
-
require_confirmation:
|
|
118
|
+
default: true
|
|
119
|
+
require_confirmation: false
|
|
111
120
|
exclude:
|
|
112
121
|
- corpus
|
|
113
122
|
- pkg
|
|
@@ -116,21 +125,23 @@ tools:
|
|
|
116
125
|
cmd: |
|
|
117
126
|
grep #{'-i' if ignore_case} -m #{max_results} -r #{pattern} #{path}
|
|
118
127
|
browse:
|
|
119
|
-
default:
|
|
128
|
+
default: true
|
|
120
129
|
write_file:
|
|
121
|
-
default:
|
|
130
|
+
default: true
|
|
122
131
|
require_confirmation: true
|
|
123
132
|
allowed:
|
|
124
|
-
- ./tmp
|
|
133
|
+
- './tmp'
|
|
125
134
|
read_file:
|
|
126
|
-
default:
|
|
135
|
+
default: true
|
|
127
136
|
require_confirmation: false
|
|
128
137
|
allowed:
|
|
129
|
-
- ./tmp
|
|
130
|
-
- ./lib
|
|
131
|
-
- ./spec
|
|
138
|
+
- './tmp'
|
|
139
|
+
- './lib'
|
|
140
|
+
- './spec'
|
|
132
141
|
search_web:
|
|
133
142
|
default: true
|
|
143
|
+
require_confirmation: true
|
|
144
|
+
max_results: 25
|
|
134
145
|
import_url:
|
|
135
146
|
default: true
|
|
136
147
|
require_confirmation: true
|
|
@@ -152,3 +163,7 @@ tools:
|
|
|
152
163
|
default: true
|
|
153
164
|
generate_password:
|
|
154
165
|
default: true
|
|
166
|
+
copy_to_clipboard:
|
|
167
|
+
default: true
|
|
168
|
+
paste_from_clipboard:
|
|
169
|
+
default: true
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# A tool for copying the last assistant response to the clipboard.
|
|
2
|
+
#
|
|
3
|
+
# The executable used for the copy operation is read from the configuration
|
|
4
|
+
# under `copy.executable`. The default configuration ships with
|
|
5
|
+
# `ctc` – a small CLI that copies stdin to the system clipboard.
|
|
6
|
+
#
|
|
7
|
+
# The tool has no parameters; it simply grabs the most recent response
|
|
8
|
+
# from the chat instance and streams it to the executable.
|
|
9
|
+
class OllamaChat::Tools::CopyToClipboard
|
|
10
|
+
include OllamaChat::Tools::Concern
|
|
11
|
+
|
|
12
|
+
# Register the tool name for the OllamaChat runtime.
|
|
13
|
+
def self.register_name = 'copy_to_clipboard'
|
|
14
|
+
|
|
15
|
+
# Build the OpenAI function schema for the tool.
|
|
16
|
+
# No parameters are required.
|
|
17
|
+
def tool
|
|
18
|
+
Tool.new(
|
|
19
|
+
type: 'function',
|
|
20
|
+
function: Tool::Function.new(
|
|
21
|
+
name:,
|
|
22
|
+
description: 'Copy the last assistant response to the system clipboard',
|
|
23
|
+
parameters: Tool::Function::Parameters.new(
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {},
|
|
26
|
+
required: []
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Execute the tool.
|
|
33
|
+
#
|
|
34
|
+
# @param _tool_call [OllamaChat::Tool::Call] the tool call object (unused)
|
|
35
|
+
# @param opts [Hash] additional options
|
|
36
|
+
# @option opts [ComplexConfig::Settings] :config the configuration object
|
|
37
|
+
# @option opts [OllamaChat::Chat] :chat the chat instance
|
|
38
|
+
# @return [String] JSON payload indicating success or failure
|
|
39
|
+
def execute(_tool_call, **opts)
|
|
40
|
+
chat = opts[:chat]
|
|
41
|
+
chat.perform_copy_to_clipboard(content: true)
|
|
42
|
+
{
|
|
43
|
+
success: true,
|
|
44
|
+
message: "The last response has been successfully copied to the system clipboard."
|
|
45
|
+
}.to_json
|
|
46
|
+
rescue => e
|
|
47
|
+
{
|
|
48
|
+
error: e.class,
|
|
49
|
+
message: e.message
|
|
50
|
+
}.to_json
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
self
|
|
54
|
+
end.register
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# A tool for pasting content from the clipboard.
|
|
2
|
+
#
|
|
3
|
+
# This tool allows the chat client to retrieve content from the system
|
|
4
|
+
# clipboard and make it available for use in the chat session.
|
|
5
|
+
# It integrates with the Ollama tool calling system to provide
|
|
6
|
+
# clipboard reading capabilities to the language model.
|
|
7
|
+
class OllamaChat::Tools::PasteFromClipboard
|
|
8
|
+
include OllamaChat::Tools::Concern
|
|
9
|
+
|
|
10
|
+
# Register the tool name for the OllamaChat runtime.
|
|
11
|
+
def self.register_name = 'paste_from_clipboard'
|
|
12
|
+
|
|
13
|
+
# Build the OpenAI function schema for the tool.
|
|
14
|
+
# No parameters are required.
|
|
15
|
+
def tool
|
|
16
|
+
Tool.new(
|
|
17
|
+
type: 'function',
|
|
18
|
+
function: Tool::Function.new(
|
|
19
|
+
name:,
|
|
20
|
+
description: 'Paste content from the system clipboard into the chat session',
|
|
21
|
+
parameters: Tool::Function::Parameters.new(
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {},
|
|
24
|
+
required: []
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Execute the tool.
|
|
31
|
+
#
|
|
32
|
+
# @param _tool_call [OllamaChat::Tool::Call] the tool call object (unused)
|
|
33
|
+
# @param opts [Hash] additional options
|
|
34
|
+
# @option opts [ComplexConfig::Settings] :config the configuration object
|
|
35
|
+
# @option opts [OllamaChat::Chat] :chat the chat instance
|
|
36
|
+
# @return [String] JSON payload indicating success or failure
|
|
37
|
+
def execute(_tool_call, **opts)
|
|
38
|
+
chat = opts[:chat]
|
|
39
|
+
|
|
40
|
+
# Use the chat instance's clipboard paste functionality
|
|
41
|
+
content = chat.perform_paste_from_clipboard
|
|
42
|
+
|
|
43
|
+
{
|
|
44
|
+
success: true,
|
|
45
|
+
message: "Content pasted from clipboard",
|
|
46
|
+
content:
|
|
47
|
+
}.to_json
|
|
48
|
+
rescue => e
|
|
49
|
+
{
|
|
50
|
+
error: e.class,
|
|
51
|
+
message: e.message
|
|
52
|
+
}.to_json
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
self
|
|
56
|
+
end.register
|
data/lib/ollama_chat/tools.rb
CHANGED
|
@@ -41,6 +41,7 @@ module OllamaChat::Tools
|
|
|
41
41
|
end
|
|
42
42
|
require 'ollama_chat/tools/concern'
|
|
43
43
|
require 'ollama_chat/tools/browse'
|
|
44
|
+
require 'ollama_chat/tools/copy_to_clipboard'
|
|
44
45
|
require 'ollama_chat/tools/directory_structure'
|
|
45
46
|
require 'ollama_chat/tools/execute_grep'
|
|
46
47
|
require 'ollama_chat/tools/file_context'
|
|
@@ -51,11 +52,12 @@ require 'ollama_chat/tools/get_cve'
|
|
|
51
52
|
require 'ollama_chat/tools/get_endoflife'
|
|
52
53
|
require 'ollama_chat/tools/get_jira_issue'
|
|
53
54
|
require 'ollama_chat/tools/get_location'
|
|
54
|
-
require 'ollama_chat/tools/get_time'
|
|
55
55
|
require 'ollama_chat/tools/get_rfc'
|
|
56
|
+
require 'ollama_chat/tools/get_time'
|
|
56
57
|
require 'ollama_chat/tools/import_url'
|
|
58
|
+
require 'ollama_chat/tools/open_file_in_editor'
|
|
59
|
+
require 'ollama_chat/tools/paste_from_clipboard'
|
|
57
60
|
require 'ollama_chat/tools/read_file'
|
|
58
61
|
require 'ollama_chat/tools/run_tests'
|
|
59
62
|
require 'ollama_chat/tools/search_web'
|
|
60
|
-
require 'ollama_chat/tools/open_file_in_editor'
|
|
61
63
|
require 'ollama_chat/tools/write_file'
|
data/lib/ollama_chat/version.rb
CHANGED
data/ollama_chat.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: ollama_chat 0.0.
|
|
2
|
+
# stub: ollama_chat 0.0.71 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "ollama_chat".freeze
|
|
6
|
-
s.version = "0.0.
|
|
6
|
+
s.version = "0.0.71".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]
|
|
@@ -12,15 +12,15 @@ Gem::Specification.new do |s|
|
|
|
12
12
|
s.description = "The app provides a command-line interface (CLI) to an Ollama AI model,\nallowing users to engage in text-based conversations and generate\nhuman-like responses. Users can import data from local files or web pages,\nwhich are then processed through three different modes: fully importing the\ncontent into the conversation context, summarizing the information for\nconcise reference, or storing it in an embedding vector database for later\nretrieval based on the conversation.\n".freeze
|
|
13
13
|
s.email = "flori@ping.de".freeze
|
|
14
14
|
s.executables = ["ollama_chat".freeze, "ollama_chat_send".freeze]
|
|
15
|
-
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/env_config.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/import_url.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/weather/dwd_sensor.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze]
|
|
16
|
-
s.files = [".utilsrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/env_config.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/import_url.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/weather/dwd_sensor.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze, "ollama_chat.gemspec".freeze, "redis/redis.conf".freeze, "spec/assets/api_show.json".freeze, "spec/assets/api_tags.json".freeze, "spec/assets/api_version.json".freeze, "spec/assets/conversation.json".freeze, "spec/assets/deep/deeper/empty.txt".freeze, "spec/assets/deep/deeper/not-empty.txt".freeze, "spec/assets/deep/empty.txt".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/example_with_quote.html".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/import_url_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
|
15
|
+
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/env_config.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/import_url.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/paste_from_clipboard.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/weather/dwd_sensor.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze]
|
|
16
|
+
s.files = [".utilsrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/env_config.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/import_url.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/paste_from_clipboard.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/weather/dwd_sensor.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze, "ollama_chat.gemspec".freeze, "redis/redis.conf".freeze, "spec/assets/api_show.json".freeze, "spec/assets/api_tags.json".freeze, "spec/assets/api_version.json".freeze, "spec/assets/conversation.json".freeze, "spec/assets/deep/deeper/empty.txt".freeze, "spec/assets/deep/deeper/not-empty.txt".freeze, "spec/assets/deep/empty.txt".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/example_with_quote.html".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/import_url_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/paste_from_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
|
17
17
|
s.homepage = "https://github.com/flori/ollama_chat".freeze
|
|
18
18
|
s.licenses = ["MIT".freeze]
|
|
19
19
|
s.rdoc_options = ["--title".freeze, "OllamaChat - A command-line interface (CLI) for interacting with an Ollama AI model.".freeze, "--main".freeze, "README.md".freeze]
|
|
20
20
|
s.required_ruby_version = Gem::Requirement.new(">= 3.2".freeze)
|
|
21
21
|
s.rubygems_version = "4.0.3".freeze
|
|
22
22
|
s.summary = "A command-line interface (CLI) for interacting with an Ollama AI model.".freeze
|
|
23
|
-
s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/import_url_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
|
23
|
+
s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/import_url_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/paste_from_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
|
24
24
|
|
|
25
25
|
s.specification_version = 4
|
|
26
26
|
|
|
@@ -35,7 +35,7 @@ describe OllamaChat::Chat, protect_env: true do
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
it 'returns :next when input is "/paste"' do
|
|
38
|
-
expect(chat).to receive(:
|
|
38
|
+
expect(chat).to receive(:paste_from_clipboard).and_return "pasted this"
|
|
39
39
|
expect(chat.handle_input("/paste")).to eq "pasted this"
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -209,6 +209,11 @@ describe OllamaChat::Chat, protect_env: true do
|
|
|
209
209
|
expect(chat.handle_input("/nixda")).to eq :next
|
|
210
210
|
end
|
|
211
211
|
|
|
212
|
+
it 'returns :next when input is "/help me"' do
|
|
213
|
+
expect(chat).to receive(:display_chat_help_message).and_return 'the help message'
|
|
214
|
+
expect(chat.handle_input("/help me")).to include 'the help message'
|
|
215
|
+
end
|
|
216
|
+
|
|
212
217
|
it 'returns :next when input is " "' do
|
|
213
218
|
expect(STDOUT).to receive(:puts).with(/to quit/)
|
|
214
219
|
expect(chat.handle_input(" ")).to eq :next
|
|
@@ -8,17 +8,17 @@ describe OllamaChat::Clipboard do
|
|
|
8
8
|
connect_to_ollama_server
|
|
9
9
|
|
|
10
10
|
it 'can copy to clipboard' do
|
|
11
|
-
`which pbcopy`.full? or skip 'pbcopy not in path'
|
|
12
11
|
expect(STDERR).to receive(:puts).with(/No response available to copy to the system clipboard/)
|
|
13
12
|
expect(chat.copy_to_clipboard).to be_nil
|
|
14
13
|
chat.instance_variable_get(:@messages).load_conversation(asset('conversation.json'))
|
|
15
|
-
expect(STDOUT).to receive(:puts).with(/The last response has been copied to the system clipboard/)
|
|
14
|
+
expect(STDOUT).to receive(:puts).with(/The last response has been successfully copied to the system clipboard/)
|
|
15
|
+
expect(chat).to receive(:perform_copy_to_clipboard).and_return nil
|
|
16
16
|
expect(chat.copy_to_clipboard).to be_nil
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
it 'can paste from
|
|
20
|
-
expect(STDOUT).to receive(:puts).with(/
|
|
21
|
-
expect(
|
|
22
|
-
expect(chat.
|
|
19
|
+
it 'can paste from clipboard' do
|
|
20
|
+
expect(STDOUT).to receive(:puts).with(/The clipboard content has been successfully copied to the chat/)
|
|
21
|
+
expect(chat).to receive(:perform_paste_from_clipboard).and_return 'test content'
|
|
22
|
+
expect(chat.paste_from_clipboard).to eq 'test content'
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -8,7 +8,7 @@ describe OllamaChat::FollowChat do
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
let :chat do
|
|
11
|
-
double('Chat', markdown: double(on?: false), think_loud?:
|
|
11
|
+
double('Chat', markdown: double(on?: false), think_loud?: false,
|
|
12
12
|
think?: false, debug: false, stream: double(on?: true))
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -43,7 +43,7 @@ describe OllamaChat::FollowChat do
|
|
|
43
43
|
prompt_eval_count: 7,
|
|
44
44
|
load_duration: 33.45,
|
|
45
45
|
)
|
|
46
|
-
expect(output).to receive(:puts).with("",
|
|
46
|
+
expect(output).to receive(:puts).with("", /eval_duration/)
|
|
47
47
|
follow_chat.call(response)
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -35,7 +35,7 @@ describe OllamaChat::MessageList do
|
|
|
35
35
|
|
|
36
36
|
let :list do
|
|
37
37
|
described_class.new(chat).tap do |list|
|
|
38
|
-
list << Ollama::Message.new(role: 'system', content: 'hello')
|
|
38
|
+
list << Ollama::Message.new(role: 'system', content: 'hello', thinking: 'a while')
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -59,6 +59,20 @@ describe OllamaChat::MessageList do
|
|
|
59
59
|
expect(list.last).to be_a Ollama::Message
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
describe '#find_last' do
|
|
63
|
+
it 'can find last message' do
|
|
64
|
+
expect(list.find_last { true }.content).to eq 'hello'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'can find last message with or w/o content' do
|
|
68
|
+
list << Ollama::Message.new(role: 'assistant', content: 'yep')
|
|
69
|
+
list << Ollama::Message.new(role: 'user', content: 'world')
|
|
70
|
+
list << Ollama::Message.new(role: 'assistant', content: '')
|
|
71
|
+
expect(list.find_last { _1.role == 'assistant' }.content).to be_empty
|
|
72
|
+
expect(list.find_last(content: true) { _1.role == 'assistant' }.content).to eq 'yep'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
62
76
|
it 'can load conversations if existing' do
|
|
63
77
|
expect(list.messages.first.role).to eq 'system'
|
|
64
78
|
expect(list.load_conversation(asset('conversation-nixda.json'))).to be_nil
|
|
@@ -68,10 +82,19 @@ describe OllamaChat::MessageList do
|
|
|
68
82
|
expect(list.messages.map(&:role)).to eq %w[ system user assistant ]
|
|
69
83
|
end
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
describe '.save_conversation' do
|
|
86
|
+
it 'can save conversations' do
|
|
87
|
+
expect(list.save_conversation('tmp/test-conversation.json')).to eq list
|
|
88
|
+
ensure
|
|
89
|
+
FileUtils.rm_f 'tmp/test-conversation.json'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'can save conversations with thinking' do
|
|
93
|
+
expect(list.save_conversation('tmp/test-conversation.json')).to eq list
|
|
94
|
+
expect(JSON.load(File.new('tmp/test-conversation.json'))[0]['thinking']).to eq 'a while'
|
|
95
|
+
ensure
|
|
96
|
+
FileUtils.rm_f 'tmp/test-conversation.json'
|
|
97
|
+
end
|
|
75
98
|
end
|
|
76
99
|
|
|
77
100
|
describe "#last" do
|
|
@@ -107,7 +130,7 @@ describe OllamaChat::MessageList do
|
|
|
107
130
|
|
|
108
131
|
it 'shows nothing when the last message is by the assistant' do
|
|
109
132
|
list = described_class.new(chat)
|
|
110
|
-
allow(chat).to receive(:
|
|
133
|
+
allow(chat).to receive(:think_loud?).and_return(false)
|
|
111
134
|
allow(chat).to receive(:markdown).and_return(double(on?: false))
|
|
112
135
|
list << Ollama::Message.new(role: 'assistant', content: 'hello')
|
|
113
136
|
expect(STDOUT).to receive(:puts).
|
|
@@ -123,7 +146,7 @@ describe OllamaChat::MessageList do
|
|
|
123
146
|
end
|
|
124
147
|
|
|
125
148
|
it "shows last N messages when N is larger than available messages" do
|
|
126
|
-
allow(chat).to receive(:
|
|
149
|
+
allow(chat).to receive(:think_loud?).and_return(false)
|
|
127
150
|
allow(chat).to receive(:markdown).and_return(double(on?: false))
|
|
128
151
|
list = described_class.new(chat)
|
|
129
152
|
list << Ollama::Message.new(role: 'system', content: 'hello')
|
|
@@ -143,7 +166,7 @@ describe OllamaChat::MessageList do
|
|
|
143
166
|
it 'can show last message' do
|
|
144
167
|
expect(chat).to receive(:markdown).
|
|
145
168
|
and_return(double(on?: true)).at_least(:once)
|
|
146
|
-
expect(chat).to receive(:
|
|
169
|
+
expect(chat).to receive(:think_loud?).and_return(false).at_least(:once)
|
|
147
170
|
expect(STDOUT).to receive(:puts).
|
|
148
171
|
with("📨 \e[1m\e[38;5;213msystem\e[0m\e[0m:\nhello\n")
|
|
149
172
|
list.show_last
|
|
@@ -152,7 +175,7 @@ describe OllamaChat::MessageList do
|
|
|
152
175
|
it 'can list conversations without thinking' do
|
|
153
176
|
expect(chat).to receive(:markdown).
|
|
154
177
|
and_return(double(on?: true)).at_least(:once)
|
|
155
|
-
expect(chat).to receive(:
|
|
178
|
+
expect(chat).to receive(:think_loud?).and_return(false).at_least(:once)
|
|
156
179
|
list << Ollama::Message.new(role: 'user', content: 'world')
|
|
157
180
|
expect(STDOUT).to receive(:puts).
|
|
158
181
|
with(
|
|
@@ -165,7 +188,7 @@ describe OllamaChat::MessageList do
|
|
|
165
188
|
it 'can list conversations with thinking' do
|
|
166
189
|
expect(chat).to receive(:markdown).
|
|
167
190
|
and_return(double(on?: true)).at_least(:once)
|
|
168
|
-
expect(chat).to receive(:
|
|
191
|
+
expect(chat).to receive(:think_loud?).and_return(true).at_least(:once)
|
|
169
192
|
expect(STDOUT).to receive(:puts).
|
|
170
193
|
with(
|
|
171
194
|
"📨 \e[1m\e[38;5;213msystem\e[0m\e[0m:\n" \
|
|
@@ -192,7 +215,7 @@ describe OllamaChat::MessageList do
|
|
|
192
215
|
skip 'no tty' unless STDOUT.tty?
|
|
193
216
|
expect(chat).to receive(:markdown).
|
|
194
217
|
and_return(double(on?: true)).at_least(:once)
|
|
195
|
-
expect(chat).to receive(:
|
|
218
|
+
expect(chat).to receive(:think_loud?).and_return(false).at_least(:once)
|
|
196
219
|
list << Ollama::Message.new(role: 'user', content: 'world')
|
|
197
220
|
list.list_conversation
|
|
198
221
|
end
|
|
@@ -264,7 +287,7 @@ describe OllamaChat::MessageList do
|
|
|
264
287
|
expect(chat).to receive(:location).and_return(double(on?: false))
|
|
265
288
|
list << Ollama::Message.new(role: 'user', content: 'world')
|
|
266
289
|
expect(list.to_ary.map(&:as_json)).to eq [
|
|
267
|
-
Ollama::Message.new(role: 'system', content: 'hello').as_json,
|
|
290
|
+
Ollama::Message.new(role: 'system', content: 'hello', thinking: 'a while').as_json,
|
|
268
291
|
Ollama::Message.new(role: 'user', content: 'world').as_json,
|
|
269
292
|
]
|
|
270
293
|
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe OllamaChat::Tools::CopyToClipboard do
|
|
4
|
+
let :chat do
|
|
5
|
+
OllamaChat::Chat.new(argv: chat_default_config)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
let :config do
|
|
9
|
+
chat.config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
connect_to_ollama_server
|
|
13
|
+
|
|
14
|
+
it 'can have name' do
|
|
15
|
+
expect(described_class.new.name).to eq 'copy_to_clipboard'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'can have tool' do
|
|
19
|
+
expect(described_class.new.tool).to be_a Ollama::Tool
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'can be converted to hash' do
|
|
23
|
+
expect(described_class.new.to_hash).to be_a Hash
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'can be executed successfully' do
|
|
27
|
+
tool_call = double(
|
|
28
|
+
'ToolCall',
|
|
29
|
+
function: double(
|
|
30
|
+
name: 'copy_to_clipboard',
|
|
31
|
+
arguments: double()
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Test that perform_copy_to_clipboard is called with content: true
|
|
36
|
+
expect(chat).to receive(:perform_copy_to_clipboard).with(content: true)
|
|
37
|
+
|
|
38
|
+
result = described_class.new.execute(tool_call, chat: chat)
|
|
39
|
+
|
|
40
|
+
# Should return valid JSON
|
|
41
|
+
expect(result).to be_a(String)
|
|
42
|
+
json = json_object(result)
|
|
43
|
+
expect(json.error).to be_nil # No exception was raised
|
|
44
|
+
expect(json.success).to be true
|
|
45
|
+
expect(json.message).to eq 'The last response has been successfully copied to the system clipboard.'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'can handle execution errors gracefully' do
|
|
49
|
+
tool_call = double(
|
|
50
|
+
'ToolCall',
|
|
51
|
+
function: double(
|
|
52
|
+
name: 'copy_to_clipboard',
|
|
53
|
+
arguments: double()
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Test that perform_copy_to_clipboard raises an error
|
|
58
|
+
expect(chat).to receive(:perform_copy_to_clipboard).with(content: true).
|
|
59
|
+
and_raise(OllamaChat::OllamaChatError, 'No response available to copy to the system clipboard.')
|
|
60
|
+
|
|
61
|
+
result = described_class.new.execute(tool_call, chat: chat)
|
|
62
|
+
|
|
63
|
+
# Should return valid JSON even with errors
|
|
64
|
+
expect(result).to be_a(String)
|
|
65
|
+
json = json_object(result)
|
|
66
|
+
expect(json.error).to eq 'OllamaChat::OllamaChatError'
|
|
67
|
+
expect(json.message).to eq 'No response available to copy to the system clipboard.'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'can handle execution exceptions gracefully' do
|
|
71
|
+
tool_call = double(
|
|
72
|
+
'ToolCall',
|
|
73
|
+
function: double(
|
|
74
|
+
name: 'copy_to_clipboard',
|
|
75
|
+
arguments: double()
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Test that perform_copy_to_clipboard raises an exception
|
|
80
|
+
expect(chat).to receive(:perform_copy_to_clipboard).with(content: true).
|
|
81
|
+
and_raise(RuntimeError, 'some kind of exception')
|
|
82
|
+
|
|
83
|
+
result = described_class.new.execute(tool_call, chat: chat)
|
|
84
|
+
|
|
85
|
+
# Should return valid JSON even with exceptions
|
|
86
|
+
expect(result).to be_a(String)
|
|
87
|
+
json = json_object(result)
|
|
88
|
+
expect(json.error).to eq 'RuntimeError'
|
|
89
|
+
expect(json.message).to eq 'some kind of exception'
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe OllamaChat::Tools::PasteFromClipboard do
|
|
4
|
+
let :chat do
|
|
5
|
+
OllamaChat::Chat.new(argv: chat_default_config)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
let :config do
|
|
9
|
+
chat.config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
connect_to_ollama_server
|
|
13
|
+
|
|
14
|
+
it 'can have name' do
|
|
15
|
+
expect(described_class.new.name).to eq 'paste_from_clipboard'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'can have tool' do
|
|
19
|
+
expect(described_class.new.tool).to be_a Ollama::Tool
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'can be converted to hash' do
|
|
23
|
+
expect(described_class.new.to_hash).to be_a Hash
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'can be executed successfully' do
|
|
27
|
+
tool_call = double(
|
|
28
|
+
'ToolCall',
|
|
29
|
+
function: double(
|
|
30
|
+
name: 'paste_from_clipboard',
|
|
31
|
+
arguments: double()
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Test that perform_paste_from_clipboard is called
|
|
36
|
+
expect(chat).to receive(:perform_paste_from_clipboard)
|
|
37
|
+
|
|
38
|
+
result = described_class.new.execute(tool_call, chat: chat)
|
|
39
|
+
|
|
40
|
+
# Should return valid JSON
|
|
41
|
+
expect(result).to be_a(String)
|
|
42
|
+
json = json_object(result)
|
|
43
|
+
expect(json.error).to be_nil # No exception was raised
|
|
44
|
+
expect(json.success).to be true
|
|
45
|
+
expect(json.message).to eq 'Content pasted from clipboard'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'can handle execution errors gracefully' do
|
|
49
|
+
tool_call = double(
|
|
50
|
+
'ToolCall',
|
|
51
|
+
function: double(
|
|
52
|
+
name: 'paste_from_clipboard',
|
|
53
|
+
arguments: double()
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Test that perform_paste_from_clipboard raises an error
|
|
58
|
+
expect(chat).to receive(:perform_paste_from_clipboard).
|
|
59
|
+
and_raise(OllamaChat::OllamaChatError, 'No content available to paste from the system clipboard.')
|
|
60
|
+
|
|
61
|
+
result = described_class.new.execute(tool_call, chat: chat)
|
|
62
|
+
|
|
63
|
+
# Should return valid JSON even with errors
|
|
64
|
+
expect(result).to be_a(String)
|
|
65
|
+
json = json_object(result)
|
|
66
|
+
expect(json.error).to eq 'OllamaChat::OllamaChatError'
|
|
67
|
+
expect(json.message).to eq 'No content available to paste from the system clipboard.'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'can handle execution exceptions gracefully' do
|
|
71
|
+
tool_call = double(
|
|
72
|
+
'ToolCall',
|
|
73
|
+
function: double(
|
|
74
|
+
name: 'paste_from_clipboard',
|
|
75
|
+
arguments: double()
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Test that perform_paste_from_clipboard raises an exception
|
|
80
|
+
expect(chat).to receive(:perform_paste_from_clipboard).
|
|
81
|
+
and_raise(RuntimeError, 'some kind of exception')
|
|
82
|
+
|
|
83
|
+
result = described_class.new.execute(tool_call, chat: chat)
|
|
84
|
+
|
|
85
|
+
# Should return valid JSON even with exceptions
|
|
86
|
+
expect(result).to be_a(String)
|
|
87
|
+
json = json_object(result)
|
|
88
|
+
expect(json.error).to eq 'RuntimeError'
|
|
89
|
+
expect(json.message).to eq 'some kind of exception'
|
|
90
|
+
end
|
|
91
|
+
end
|
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.
|
|
4
|
+
version: 0.0.71
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -481,6 +481,7 @@ extra_rdoc_files:
|
|
|
481
481
|
- lib/ollama_chat/tools.rb
|
|
482
482
|
- lib/ollama_chat/tools/browse.rb
|
|
483
483
|
- lib/ollama_chat/tools/concern.rb
|
|
484
|
+
- lib/ollama_chat/tools/copy_to_clipboard.rb
|
|
484
485
|
- lib/ollama_chat/tools/directory_structure.rb
|
|
485
486
|
- lib/ollama_chat/tools/execute_grep.rb
|
|
486
487
|
- lib/ollama_chat/tools/file_context.rb
|
|
@@ -495,6 +496,7 @@ extra_rdoc_files:
|
|
|
495
496
|
- lib/ollama_chat/tools/get_time.rb
|
|
496
497
|
- lib/ollama_chat/tools/import_url.rb
|
|
497
498
|
- lib/ollama_chat/tools/open_file_in_editor.rb
|
|
499
|
+
- lib/ollama_chat/tools/paste_from_clipboard.rb
|
|
498
500
|
- lib/ollama_chat/tools/read_file.rb
|
|
499
501
|
- lib/ollama_chat/tools/run_tests.rb
|
|
500
502
|
- lib/ollama_chat/tools/search_web.rb
|
|
@@ -552,6 +554,7 @@ files:
|
|
|
552
554
|
- lib/ollama_chat/tools.rb
|
|
553
555
|
- lib/ollama_chat/tools/browse.rb
|
|
554
556
|
- lib/ollama_chat/tools/concern.rb
|
|
557
|
+
- lib/ollama_chat/tools/copy_to_clipboard.rb
|
|
555
558
|
- lib/ollama_chat/tools/directory_structure.rb
|
|
556
559
|
- lib/ollama_chat/tools/execute_grep.rb
|
|
557
560
|
- lib/ollama_chat/tools/file_context.rb
|
|
@@ -566,6 +569,7 @@ files:
|
|
|
566
569
|
- lib/ollama_chat/tools/get_time.rb
|
|
567
570
|
- lib/ollama_chat/tools/import_url.rb
|
|
568
571
|
- lib/ollama_chat/tools/open_file_in_editor.rb
|
|
572
|
+
- lib/ollama_chat/tools/paste_from_clipboard.rb
|
|
569
573
|
- lib/ollama_chat/tools/read_file.rb
|
|
570
574
|
- lib/ollama_chat/tools/run_tests.rb
|
|
571
575
|
- lib/ollama_chat/tools/search_web.rb
|
|
@@ -621,6 +625,7 @@ files:
|
|
|
621
625
|
- spec/ollama_chat/switches_spec.rb
|
|
622
626
|
- spec/ollama_chat/think_control_spec.rb
|
|
623
627
|
- spec/ollama_chat/tools/browse_spec.rb
|
|
628
|
+
- spec/ollama_chat/tools/copy_to_clipboard_spec.rb
|
|
624
629
|
- spec/ollama_chat/tools/directory_structure_spec.rb
|
|
625
630
|
- spec/ollama_chat/tools/execute_grep_spec.rb
|
|
626
631
|
- spec/ollama_chat/tools/file_context_spec.rb
|
|
@@ -635,6 +640,7 @@ files:
|
|
|
635
640
|
- spec/ollama_chat/tools/get_time_spec.rb
|
|
636
641
|
- spec/ollama_chat/tools/import_url_spec.rb
|
|
637
642
|
- spec/ollama_chat/tools/open_file_in_editor_spec.rb
|
|
643
|
+
- spec/ollama_chat/tools/paste_from_clipboard_spec.rb
|
|
638
644
|
- spec/ollama_chat/tools/read_file_spec.rb
|
|
639
645
|
- spec/ollama_chat/tools/run_tests_spec.rb
|
|
640
646
|
- spec/ollama_chat/tools/search_web_spec.rb
|
|
@@ -692,6 +698,7 @@ test_files:
|
|
|
692
698
|
- spec/ollama_chat/switches_spec.rb
|
|
693
699
|
- spec/ollama_chat/think_control_spec.rb
|
|
694
700
|
- spec/ollama_chat/tools/browse_spec.rb
|
|
701
|
+
- spec/ollama_chat/tools/copy_to_clipboard_spec.rb
|
|
695
702
|
- spec/ollama_chat/tools/directory_structure_spec.rb
|
|
696
703
|
- spec/ollama_chat/tools/execute_grep_spec.rb
|
|
697
704
|
- spec/ollama_chat/tools/file_context_spec.rb
|
|
@@ -706,6 +713,7 @@ test_files:
|
|
|
706
713
|
- spec/ollama_chat/tools/get_time_spec.rb
|
|
707
714
|
- spec/ollama_chat/tools/import_url_spec.rb
|
|
708
715
|
- spec/ollama_chat/tools/open_file_in_editor_spec.rb
|
|
716
|
+
- spec/ollama_chat/tools/paste_from_clipboard_spec.rb
|
|
709
717
|
- spec/ollama_chat/tools/read_file_spec.rb
|
|
710
718
|
- spec/ollama_chat/tools/run_tests_spec.rb
|
|
711
719
|
- spec/ollama_chat/tools/search_web_spec.rb
|