ollama_chat 0.0.114 → 0.0.115

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5e93e610536ac396d18e929ef76b3dcecac7d3b9d88a35b8d6ff141e7eba8e4
4
- data.tar.gz: a7792a3b397ebcc0d88552f0fa1417933f44ff00c6e0fad4eb62d567b5c98bfd
3
+ metadata.gz: 18297e3bbf39619c1721b30fdf4f691a2a71b1e15994c2ae28ced14eb7f76c57
4
+ data.tar.gz: 1481131a053ef2d9390456c84e9d58bf0890d1ded23eafb5d15c4b1b70babb99
5
5
  SHA512:
6
- metadata.gz: 95a81969d48e98ff06623f887c33bd0acf94452639fabbf4eca30127ef4d300124f9e12d7bbb97a3d8d86263116d3c772e5d9c403d1e4f4cbdc2df241e1f719f
7
- data.tar.gz: 92201492f3a4a084c845d11f7957b6af6ea8630e7f242158458cb1bad059bababb8699f0dc2f24204ddfde38bcd47e8491812e03d5f38128f179b443f858a9dc
6
+ metadata.gz: 6ec5d58d329bb3b8a25ccdb0ce55cb04be29f5e8b22e2b3f7aa8ce77bfe49cf56d33c6c198c63431b4ccca9e78029887fe221be1effa5306d4aef464fe530fd9
7
+ data.tar.gz: ec410eb4d78a5688cb4b67bec44a3600a8e295578bb9375142957577b92d03c5ae0ada7f0e4f7841b70ed40c9dea8e6f1acc688d76abc6ba4d156c550cbf3324
data/CHANGES.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-09-01 v0.0.115
4
+
5
+ * Added `OllamaChat::Tools::ExecuteShell` in
6
+ `lib/ollama_chat/tools/execute_shell.rb`, which executes shell commands via
7
+ `sh -c` after a mandatory human review flow involving an `edit_text` editor
8
+ review and a `y/n/i` confirm prompt.
9
+ * Implemented a `y/n/i` gate in the `execute_shell` tool where `y` executes,
10
+ `n` cancels, and `i` captures user instructions for the LLM to revise the
11
+ command.
12
+ * Configured `require_confirmation: false` in `default_config.yml` to skip
13
+ the preflight confirm in `follow_chat`, relying on the in-tool `confirm?`
14
+ as the primary safety mechanism.
15
+ * Enabled output display via `use_pager` with bold `stdout:`/`stderr:` labels
16
+ and exit codes, with `monochrome: true` (default) stripping ANSI codes
17
+ before returning results to the LLM.
18
+ * Standardized error handling for `execute_shell` failure paths (blank
19
+ command, editor abandoned/cleared, user declined, instruct) to raise
20
+ `OllamaChat::ToolFunctionArgumentError`, which is rescued to log and return
21
+ structured JSON including the `command`.
22
+ * Added a `summary_template` class method to `execute_shell` for one-liner
23
+ output in `lookup_group` compaction.
24
+ * Registered `execute_shell` in `lib/ollama_chat/tools.rb` and configured it
25
+ in `default_config.yml` with `default: false` and `result_display_timeout:
26
+ 10`.
27
+ * Added 18 spec examples in `spec/ollama_chat/tools/execute_shell_spec.rb`
28
+ covering identity, execution, editor cancel, instruct, monochrome, pager
29
+ display, and `summary_template`.
30
+ * Introduced `OllamaChat::Utils::StripANSI` module in
31
+ `lib/ollama_chat/utils/strip_ansi.rb` with a regex-based `strip_ansi`
32
+ method handling both SGR and OSC escape sequences.
33
+ * Replaced `Term::ANSIColor.uncolor` calls with `strip_ansi` in
34
+ `lib/ollama_chat/tools/execute_shell.rb`, `lib/ollama_chat/commands.rb`
35
+ (`/input` path and default subcommands), and `bin/ollama_chat_send`.
36
+ * Registered `lib/ollama_chat/utils/strip_ansi.rb` in `ollama_chat.gemspec`
37
+ file lists.
38
+ * Fixed `read_file` and `write_file` spec assertions in `read_file_spec.rb`
39
+ and `write_file_spec.rb` to match the token-first output format (`tokens
40
+ (bytes)`) shipped in **v0.0.114**.
41
+
3
42
  ## 2026-09-01 v0.0.114
4
43
 
5
44
  ### Added
data/bin/ollama_chat_send CHANGED
@@ -43,7 +43,7 @@ begin
43
43
  opts[?r] ? :socket_input_with_response : :socket_input
44
44
  end
45
45
  content = STDIN.read
46
- content = Term::ANSIColor.uncolor(content) if opts[?m]
46
+ content = OllamaChat::Utils::StripANSI.strip_ansi(content) if opts[?m]
47
47
  if opts[?e]
48
48
  basename = %w[ text ]
49
49
  basename << opts[?F]&.sub(/\A(?=[^.])/, ?.) || '.md'
@@ -926,14 +926,14 @@ module OllamaChat::Commands
926
926
  read = -> pathname {
927
927
  STDOUT.puts "Reading #{pathname.to_s.inspect}."
928
928
  content = pathname.read
929
- opts[?m] ? Term::ANSIColor.uncolor(content) : content
929
+ opts[?m] ? OllamaChat::Utils::StripANSI.strip_ansi(content) : content
930
930
  }
931
931
  next provide_file_set_content(patterns, all:, &read) || :next
932
932
  elsif arg
933
933
  filename = Pathname.new(arg).expand_path
934
934
  filename.file? or next :next
935
935
  content = filename.read
936
- content = Term::ANSIColor.uncolor(content) if opts[?m]
936
+ content = OllamaChat::Utils::StripANSI.strip_ansi(content) if opts[?m]
937
937
  content = edit_text(content) if opts[?e]
938
938
  content
939
939
  else
@@ -947,12 +947,12 @@ module OllamaChat::Commands
947
947
  patterns = extract_patterns(arg)
948
948
  next provide_file_set_content(patterns, all:, skip_blank: true) do |src|
949
949
  content = import(src)
950
- opts[?m] ? Term::ANSIColor.uncolor(content) : content
950
+ opts[?m] ? OllamaChat::Utils::StripANSI.strip_ansi(content) : content
951
951
  end || :next
952
952
  elsif arg
953
953
  source = arg
954
954
  content = import(source) or next :next
955
- content = Term::ANSIColor.uncolor(content) if opts[?m]
955
+ content = OllamaChat::Utils::StripANSI.strip_ansi(content) if opts[?m]
956
956
  content = edit_text(content) if opts[?e]
957
957
  content
958
958
  else
@@ -494,6 +494,10 @@ tools:
494
494
  result_display_timeout: 3
495
495
  cmd: |
496
496
  grep #{'-i' if ignore_case} -m #{max_results} -r #{before.full? { "-B %u " % it }}#{after.full? { "-A %u " % it }}#{context.full? { "-C %u " % it }}#{pattern} #{path}
497
+ execute_shell:
498
+ default: false
499
+ require_confirmation: false # Preflight confirm is skipped, but in-tool it's mandatory.
500
+ result_display_timeout: 0
497
501
  browse:
498
502
  result_display_timeout: 3
499
503
  default: true
@@ -0,0 +1,158 @@
1
+ require 'open3'
2
+
3
+ # Shell command executor with mandatory human review.
4
+ #
5
+ # The LLM proposes a command; the user reviews it in their configured
6
+ # editor (modify or cancel), then answers a y/n/i confirm prompt that
7
+ # cannot be disabled via configuration. Output is displayed via pager.
8
+ class OllamaChat::Tools::ExecuteShell
9
+ include OllamaChat::Tools::Concern
10
+ include Term::ANSIColor
11
+ include OllamaChat::Utils::StripANSI
12
+
13
+ # @return [String] the registered name for this tool
14
+ def self.register_name = 'execute_shell'
15
+
16
+ # Compaction summary: one-liner for lookup_group output.
17
+ #
18
+ # @param result [String] the raw JSON result string
19
+ # @return [String] a short human-readable summary
20
+ def self.summary_template(result:)
21
+ data = JSON.parse(result)
22
+ if data['error']
23
+ "❌ #{data['message']}"
24
+ else
25
+ "✅ #{data['command']} (exit #{data['exit_code']})"
26
+ end
27
+ end
28
+
29
+ # @return [Ollama::Tool] a tool definition for shell execution
30
+ def tool
31
+ Tool.new(
32
+ type: 'function',
33
+ function: Tool::Function.new(
34
+ name:,
35
+ description: <<~EOT,
36
+ Shell executor – Runs a shell command via `sh -c`. The
37
+ command is opened in your editor for review/modification,
38
+ then a mandatory y/n/i confirm prompt gates execution.
39
+ Last resort: use ONLY when no dedicated tool covers
40
+ the task (e.g. `git commit`, `bundle install`, `make`).
41
+ Prefer `execute_grep`, `directory_structure`, `read_file`,
42
+ `patch_file` over shell equivalents. Only invoke when
43
+ the user explicitly requests it or you have proposed
44
+ the command to the user beforehand. Runs in the current
45
+ working directory.
46
+ EOT
47
+ parameters: Tool::Function::Parameters.new(
48
+ type: 'object',
49
+ properties: {
50
+ command: Tool::Function::Parameters::Property.new(
51
+ type: 'string',
52
+ description: 'The shell command to execute'
53
+ ),
54
+ monochrome: Tool::Function::Parameters::Property.new(
55
+ type: 'boolean',
56
+ description: 'Strip ANSI codes from captured output' \
57
+ ' (default: true)'
58
+ ),
59
+ },
60
+ required: %w[command]
61
+ )
62
+ )
63
+ )
64
+ end
65
+
66
+ # Execute the shell command after editor review and confirmation.
67
+ #
68
+ # @param tool_call [OllamaChat::Tool::Call] the tool call with args
69
+ # @param opts [Hash] additional options
70
+ # @option opts [OllamaChat::Chat] :chat the chat instance
71
+ # @return [String] a JSON result string
72
+ def execute(tool_call, **opts)
73
+ chat = opts[:chat]
74
+ args = tool_call.function.arguments
75
+ command = args.command.to_s.strip
76
+ raise OllamaChat::ToolFunctionArgumentError,
77
+ 'command required' if command.empty?
78
+
79
+ monochrome = args.monochrome.nil? ? true : args.monochrome
80
+
81
+ unless OllamaChat.test_mode?
82
+ reviewed = review(command, chat:)
83
+ raise OllamaChat::ToolFunctionArgumentError,
84
+ "Shell command cancelled by user: #{command}" unless reviewed
85
+ command = reviewed
86
+
87
+ STDOUT.puts "\n$ #{command}\n"
88
+ answer = chat.confirm?(
89
+ prompt: '❓ Allow ✅[y]es / ⛔️[n]o / 📝[i]nstruct? '
90
+ )&.to_s&.downcase
91
+
92
+ case answer
93
+ when 'y'
94
+ # proceed to execution
95
+ when 'n'
96
+ raise OllamaChat::ToolFunctionArgumentError,
97
+ "Shell command cancelled by user: #{command}"
98
+ else
99
+ instr = chat.ask?(prompt: '📝 Instructions: ')&.strip
100
+ resolve = instr.full? || 'You **MUST** ask the user for instructions!'
101
+ raise OllamaChat::ToolFunctionArgumentError,
102
+ "User instruct: #{resolve} (command: #{command})"
103
+ end
104
+ end
105
+
106
+ stdout, stderr, status = Open3.capture3('sh', '-c', command)
107
+ exit_code = status.exitstatus
108
+ if monochrome
109
+ stdout = strip_ansi(stdout)
110
+ stderr = strip_ansi(stderr)
111
+ end
112
+
113
+ chat.log(:info, 'Shell executed', data: {
114
+ tool: name, command:, exit_code:,
115
+ stdout_bytes: stdout.bytesize,
116
+ stderr_bytes: stderr.bytesize,
117
+ })
118
+
119
+ display(chat, stdout, stderr, exit_code)
120
+
121
+ {
122
+ stdout:, stderr:, exit_code:, command:,
123
+ message: "Shell command finished (exit #{exit_code}): #{command}",
124
+ }.to_json
125
+ rescue => e
126
+ cmd = args&.command&.to_s
127
+ chat.log(:error, e, data: { tool: name, command: cmd })
128
+ { error: e.class.name, message: e.message, command: cmd }.to_json
129
+ end
130
+
131
+ private
132
+
133
+ # Open the command in the user's editor for review.
134
+ #
135
+ # @return [String, nil] the (possibly modified) command, or nil
136
+ # if the user abandoned or cleared the editor.
137
+ def review(command, chat:)
138
+ edited = chat.edit_text(command, basename: %w[cmd .sh])
139
+ edited.full?(:chomp)
140
+ end
141
+
142
+ # Display command output through the pager.
143
+ def display(chat, stdout, stderr, exit_code)
144
+ chat.use_pager do |io|
145
+ if stdout.present?
146
+ io.puts bold { "stdout:" }, ""
147
+ io.puts stdout
148
+ end
149
+ if stderr.present?
150
+ io.puts bold { "stderr:" }, ""
151
+ io.puts stderr
152
+ end
153
+ io.puts bold{ "🎌 exit: #{exit_code}" }
154
+ end
155
+ end
156
+
157
+ self
158
+ end.register
@@ -48,6 +48,7 @@ require 'ollama_chat/tools/directory_structure'
48
48
  require 'ollama_chat/tools/eval_ruby'
49
49
  require 'ollama_chat/tools/execute_grep'
50
50
  require 'ollama_chat/tools/execute_ri'
51
+ require 'ollama_chat/tools/execute_shell'
51
52
  require 'ollama_chat/tools/execute_jira_twg'
52
53
  require 'ollama_chat/tools/file_context'
53
54
  require 'ollama_chat/tools/gem_path_lookup'
@@ -0,0 +1,22 @@
1
+ # Strips ANSI escape sequences from a string.
2
+ #
3
+ # Handles both SGR (Select Graphic Rendition) sequences like
4
+ # `\e[38;2;255;128;0m` and OSC (Operating System Command) sequences
5
+ # like `\e]0;title\a` or `\e]8;;url\e\\`.
6
+ #
7
+ # @example
8
+ # OllamaChat::Utils::StripANSI.strip_ansi("\e[31mred\e[0m")
9
+ # # => "red"
10
+ module OllamaChat::Utils::StripANSI
11
+ module_function
12
+
13
+ ANSI_RE = /\e\[[0-9;?]*[A-Za-z]|\e\].*?(\e\\|\a)/m
14
+
15
+ # Removes all ANSI escape sequences from the given string.
16
+ #
17
+ # @param line [String] the string potentially containing ANSI escapes
18
+ # @return [String] the string with all ANSI escape sequences removed
19
+ def strip_ansi(line)
20
+ line.to_s.gsub(ANSI_RE, '')
21
+ end
22
+ end
@@ -20,6 +20,7 @@ require 'ollama_chat/utils/path_completer'
20
20
  require 'ollama_chat/utils/path_validator'
21
21
  require 'ollama_chat/utils/png_metadata_extractor'
22
22
  require 'ollama_chat/utils/tag_resolver'
23
+ require 'ollama_chat/utils/strip_ansi'
23
24
  require 'ollama_chat/utils/value_formatter'
24
25
  require 'ollama_chat/utils/log_viewer'
25
26
  require 'ollama_chat/utils/log_rotation'
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.114'
3
+ VERSION = '0.0.115'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/ollama_chat.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: ollama_chat 0.0.114 ruby lib
2
+ # stub: ollama_chat 0.0.115 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ollama_chat".freeze
6
- s.version = "0.0.114".freeze
6
+ s.version = "0.0.115".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, "ollama_chat_log".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/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/compaction.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/migrations/008_drop_think_mode_constraint.rb".freeze, "lib/ollama_chat/database/migrations/009_add_app_states_table.rb".freeze, "lib/ollama_chat/database/migrations/010_add_enabled_to_collections.rb".freeze, "lib/ollama_chat/database/models/app_state.rb".freeze, "lib/ollama_chat/database/models/collection.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.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/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.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/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/say.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.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/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_jira_twg.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.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_ghr.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/get_url.rb".freeze, "lib/ollama_chat/tools/lookup_group.rb".freeze, "lib/ollama_chat/tools/move_file.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/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.rb".freeze, "lib/ollama_chat/tools/search_web.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/backup.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/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/log_rotation.rb".freeze, "lib/ollama_chat/utils/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_log".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "config/sherlock.md".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/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/compaction.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/migrations/008_drop_think_mode_constraint.rb".freeze, "lib/ollama_chat/database/migrations/009_add_app_states_table.rb".freeze, "lib/ollama_chat/database/migrations/010_add_enabled_to_collections.rb".freeze, "lib/ollama_chat/database/models/app_state.rb".freeze, "lib/ollama_chat/database/models/collection.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.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/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.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/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/say.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.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/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_jira_twg.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.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_ghr.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/get_url.rb".freeze, "lib/ollama_chat/tools/lookup_group.rb".freeze, "lib/ollama_chat/tools/move_file.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/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.rb".freeze, "lib/ollama_chat/tools/search_web.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/backup.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/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/log_rotation.rb".freeze, "lib/ollama_chat/utils/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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_ps.json".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/conversation.jsonl".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.epub".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/fluffy.png".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/miyu.png".freeze, "spec/assets/pirateweather.json".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/commands_spec.rb".freeze, "spec/ollama_chat/compaction_spec.rb".freeze, "spec/ollama_chat/config_handling_spec.rb".freeze, "spec/ollama_chat/conversation_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/favourites_management_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_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/message_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/prompt_handling_spec.rb".freeze, "spec/ollama_chat/prompt_management_spec.rb".freeze, "spec/ollama_chat/rag_handling_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/session_management_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/system_prompt_management_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/token_estimator_spec.rb".freeze, "spec/ollama_chat/tool_calling_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/concern_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_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/execute_jira_twg_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_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_image_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_ghr_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/get_url_spec.rb".freeze, "spec/ollama_chat/tools/lookup_group_spec.rb".freeze, "spec/ollama_chat/tools/move_file_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/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_knowledge_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/log_rotation_spec.rb".freeze, "spec/ollama_chat/utils/log_viewer_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_metadata_extractor_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/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/compaction.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/migrations/008_drop_think_mode_constraint.rb".freeze, "lib/ollama_chat/database/migrations/009_add_app_states_table.rb".freeze, "lib/ollama_chat/database/migrations/010_add_enabled_to_collections.rb".freeze, "lib/ollama_chat/database/models/app_state.rb".freeze, "lib/ollama_chat/database/models/collection.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.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/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.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/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/say.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.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/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_jira_twg.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/execute_shell.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.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_ghr.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/get_url.rb".freeze, "lib/ollama_chat/tools/lookup_group.rb".freeze, "lib/ollama_chat/tools/move_file.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/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.rb".freeze, "lib/ollama_chat/tools/search_web.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/backup.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/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/log_rotation.rb".freeze, "lib/ollama_chat/utils/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/strip_ansi.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_log".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "config/sherlock.md".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/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/compaction.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/migrations/008_drop_think_mode_constraint.rb".freeze, "lib/ollama_chat/database/migrations/009_add_app_states_table.rb".freeze, "lib/ollama_chat/database/migrations/010_add_enabled_to_collections.rb".freeze, "lib/ollama_chat/database/models/app_state.rb".freeze, "lib/ollama_chat/database/models/collection.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.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/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.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/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/say.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.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/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_jira_twg.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/execute_shell.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.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_ghr.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/get_url.rb".freeze, "lib/ollama_chat/tools/lookup_group.rb".freeze, "lib/ollama_chat/tools/move_file.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/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.rb".freeze, "lib/ollama_chat/tools/search_web.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/backup.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/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/log_rotation.rb".freeze, "lib/ollama_chat/utils/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/strip_ansi.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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_ps.json".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/conversation.jsonl".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.epub".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/fluffy.png".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/miyu.png".freeze, "spec/assets/pirateweather.json".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/commands_spec.rb".freeze, "spec/ollama_chat/compaction_spec.rb".freeze, "spec/ollama_chat/config_handling_spec.rb".freeze, "spec/ollama_chat/conversation_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/favourites_management_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_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/message_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/prompt_handling_spec.rb".freeze, "spec/ollama_chat/prompt_management_spec.rb".freeze, "spec/ollama_chat/rag_handling_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/session_management_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/system_prompt_management_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/token_estimator_spec.rb".freeze, "spec/ollama_chat/tool_calling_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/concern_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_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/execute_jira_twg_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_spec.rb".freeze, "spec/ollama_chat/tools/execute_shell_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_image_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_ghr_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/get_url_spec.rb".freeze, "spec/ollama_chat/tools/lookup_group_spec.rb".freeze, "spec/ollama_chat/tools/move_file_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/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_knowledge_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/log_rotation_spec.rb".freeze, "spec/ollama_chat/utils/log_viewer_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_metadata_extractor_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.17".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/commands_spec.rb".freeze, "spec/ollama_chat/compaction_spec.rb".freeze, "spec/ollama_chat/config_handling_spec.rb".freeze, "spec/ollama_chat/conversation_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/favourites_management_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_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/message_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/prompt_handling_spec.rb".freeze, "spec/ollama_chat/prompt_management_spec.rb".freeze, "spec/ollama_chat/rag_handling_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/session_management_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/system_prompt_management_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/token_estimator_spec.rb".freeze, "spec/ollama_chat/tool_calling_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/concern_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_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/execute_jira_twg_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_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_image_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_ghr_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/get_url_spec.rb".freeze, "spec/ollama_chat/tools/lookup_group_spec.rb".freeze, "spec/ollama_chat/tools/move_file_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/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_knowledge_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/log_rotation_spec.rb".freeze, "spec/ollama_chat/utils/log_viewer_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_metadata_extractor_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/commands_spec.rb".freeze, "spec/ollama_chat/compaction_spec.rb".freeze, "spec/ollama_chat/config_handling_spec.rb".freeze, "spec/ollama_chat/conversation_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/favourites_management_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_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/message_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/prompt_handling_spec.rb".freeze, "spec/ollama_chat/prompt_management_spec.rb".freeze, "spec/ollama_chat/rag_handling_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/session_management_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/system_prompt_management_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/token_estimator_spec.rb".freeze, "spec/ollama_chat/tool_calling_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/concern_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_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/execute_jira_twg_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_spec.rb".freeze, "spec/ollama_chat/tools/execute_shell_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_image_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_ghr_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/get_url_spec.rb".freeze, "spec/ollama_chat/tools/lookup_group_spec.rb".freeze, "spec/ollama_chat/tools/move_file_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/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_knowledge_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/log_rotation_spec.rb".freeze, "spec/ollama_chat/utils/log_viewer_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_metadata_extractor_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
 
@@ -0,0 +1,232 @@
1
+ describe OllamaChat::Tools::ExecuteShell do
2
+ let :chat do
3
+ OllamaChat::Chat.new(argv: chat_default_config)
4
+ end
5
+
6
+ connect_to_ollama_server
7
+
8
+ let :tool do
9
+ described_class.new
10
+ end
11
+
12
+ before do
13
+ allow(OllamaChat).to receive(:test_mode?).and_return(false)
14
+ allow(chat).to receive(:log)
15
+ allow(OC).to receive(:EDITOR?).and_return('vim')
16
+ end
17
+
18
+ def tool_call(command, monochrome: nil)
19
+ double('ToolCall', function: double(
20
+ name: 'execute_shell',
21
+ arguments: double('Args', command:, monochrome:)
22
+ ))
23
+ end
24
+
25
+ def stub_success(stdout: 'ok', stderr: '', exit_code: 0)
26
+ allow(chat).to receive(:edit_text).and_return('ls')
27
+ allow(chat).to receive(:confirm?).and_return('y')
28
+ allow(chat).to receive(:use_pager) { |&blk| blk.call(StringIO.new) }
29
+ allow(Open3).to receive(:capture3)
30
+ .and_return([stdout, stderr, double('s', exitstatus: exit_code)])
31
+ end
32
+
33
+ describe 'identity' do
34
+ it 'has the expected name' do
35
+ expect(tool.name).to eq 'execute_shell'
36
+ end
37
+
38
+ it 'provides a Tool instance' do
39
+ expect(tool.tool).to be_a(Ollama::Tool)
40
+ end
41
+
42
+ it 'can be converted to hash' do
43
+ expect(tool.to_hash).to be_a(Hash)
44
+ end
45
+ end
46
+
47
+ describe '#execute' do
48
+ it 'runs the command after editor review and confirmation' do
49
+ expect(chat).to receive(:edit_text)
50
+ .with('ls -l', hash_including(basename: %w[cmd .sh]))
51
+ .and_return('ls -l')
52
+ expect(chat).to receive(:confirm?).and_return('y')
53
+ allow(chat).to receive(:use_pager) { |&blk| blk.call(StringIO.new) }
54
+ expect(Open3).to receive(:capture3)
55
+ .with('sh', '-c', 'ls -l')
56
+ .and_return(['total 0', '', double('s', exitstatus: 0)])
57
+
58
+ result = tool.execute(tool_call('ls -l'), chat:)
59
+ json = json_object(result)
60
+
61
+ expect(json.error).to be_nil
62
+ expect(json.exit_code).to eq 0
63
+ expect(json.stdout).to eq 'total 0'
64
+ expect(json.stderr).to eq ''
65
+ expect(json.command).to eq 'ls -l'
66
+ expect(described_class.summary_template(result:)).to include('ls -l')
67
+ end
68
+
69
+ it 'executes the command as edited in the editor' do
70
+ allow(chat).to receive(:use_pager) { |&blk| blk.call(StringIO.new) }
71
+ expect(chat).to receive(:edit_text)
72
+ .with('ls', anything)
73
+ .and_return('ls -la /tmp')
74
+ allow(chat).to receive(:confirm?).and_return('y')
75
+ expect(Open3).to receive(:capture3)
76
+ .with('sh', '-c', 'ls -la /tmp')
77
+ .and_return(['x', '', double('s', exitstatus: 0)])
78
+
79
+ result = tool.execute(tool_call('ls'), chat:)
80
+
81
+ expect(json_object(result).command).to eq 'ls -la /tmp'
82
+ end
83
+
84
+ it 'returns cancelled when the user answers n' do
85
+ allow(chat).to receive(:edit_text).and_return('rm -rf .')
86
+ expect(chat).to receive(:confirm?).and_return('n')
87
+ expect(Open3).not_to receive(:capture3)
88
+
89
+ result = tool.execute(tool_call('rm -rf .'), chat:)
90
+ json = json_object(result)
91
+
92
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
93
+ expect(json.message).to include('cancelled')
94
+ expect(json.command).to eq 'rm -rf .'
95
+ end
96
+
97
+ it 'returns instruct when the user answers i' do
98
+ allow(chat).to receive(:edit_text).and_return('rm -rf .')
99
+ allow(chat).to receive(:confirm?).and_return('i')
100
+ expect(chat).to receive(:ask?)
101
+ .and_return('Actually use the build dir, not root')
102
+ expect(Open3).not_to receive(:capture3)
103
+
104
+ result = tool.execute(tool_call('rm -rf .'), chat:)
105
+ json = json_object(result)
106
+
107
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
108
+ expect(json.command).to eq 'rm -rf .'
109
+ expect(json.message).to include('build dir')
110
+ end
111
+
112
+ it 'returns cancelled when the editor is abandoned (nil)' do
113
+ expect(chat).to receive(:edit_text).and_return(nil)
114
+ expect(chat).not_to receive(:confirm?)
115
+ expect(Open3).not_to receive(:capture3)
116
+
117
+ result = tool.execute(tool_call('ls'), chat:)
118
+ json = json_object(result)
119
+
120
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
121
+ expect(json.message).to include('cancelled')
122
+ expect(json.command).to eq 'ls'
123
+ end
124
+
125
+ it 'returns cancelled when the editor is cleared to empty' do
126
+ expect(chat).to receive(:edit_text).and_return('')
127
+ expect(chat).not_to receive(:confirm?)
128
+ expect(Open3).not_to receive(:capture3)
129
+
130
+ result = tool.execute(tool_call('ls'), chat:)
131
+ json = json_object(result)
132
+
133
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
134
+ end
135
+
136
+ it 'skips editor and confirm in test mode' do
137
+ expect(OllamaChat).to receive(:test_mode?).and_return(true)
138
+ expect(chat).not_to receive(:edit_text)
139
+ expect(chat).not_to receive(:confirm?)
140
+ expect(Open3).to receive(:capture3)
141
+ .with('sh', '-c', 'ls')
142
+ .and_return(['ok', '', double('s', exitstatus: 0)])
143
+
144
+ result = tool.execute(tool_call('ls'), chat:)
145
+
146
+ expect(json_object(result).exit_code).to eq 0
147
+ end
148
+
149
+ it 'displays output via use_pager after execution' do
150
+ stub_success(stdout: "file1\nfile2", stderr: '')
151
+ pager_output = nil
152
+ expect(chat).to receive(:use_pager) do |&blk|
153
+ io = StringIO.new
154
+ blk.call(io)
155
+ pager_output = io.string
156
+ end
157
+
158
+ tool.execute(tool_call('ls'), chat:)
159
+
160
+ expect(pager_output).to include('file1')
161
+ expect(pager_output).to include('file2')
162
+ expect(pager_output).to include('exit: 0')
163
+ end
164
+
165
+ it 'strips ANSI from stdout when monochrome is true' do
166
+ stub_success(stdout: "\e[32mgreen\e[0m", stderr: '')
167
+
168
+ result = tool.execute(tool_call('ls', monochrome: true), chat:)
169
+
170
+ expect(json_object(result).stdout).to eq 'green'
171
+ end
172
+
173
+ it 'keeps ANSI when monochrome is false' do
174
+ stub_success(stdout: "\e[32mgreen\e[0m", stderr: '')
175
+
176
+ result = tool.execute(tool_call('ls', monochrome: false), chat:)
177
+
178
+ expect(json_object(result).stdout).to eq "\e[32mgreen\e[0m"
179
+ end
180
+
181
+ it 'treats a nil monochrome as true (default)' do
182
+ stub_success(stdout: "\e[31mred\e[0m", stderr: '')
183
+
184
+ result = tool.execute(tool_call('ls', monochrome: nil), chat:)
185
+
186
+ expect(json_object(result).stdout).to eq 'red'
187
+ end
188
+
189
+ it 'reports the exit code and stderr on failure' do
190
+ stub_success(stdout: '', stderr: 'nope', exit_code: 2)
191
+
192
+ result = tool.execute(tool_call('false'), chat:)
193
+ json = json_object(result)
194
+
195
+ expect(json.exit_code).to eq 2
196
+ expect(json.stderr).to eq 'nope'
197
+ end
198
+
199
+ it 'rejects a blank command' do
200
+ allow(chat).to receive(:edit_text)
201
+
202
+ result = tool.execute(tool_call(nil), chat:)
203
+ json = json_object(result)
204
+
205
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
206
+ end
207
+
208
+ it 'summary_template includes the command and exit code' do
209
+ result = {
210
+ stdout: 'x', stderr: '', exit_code: 0,
211
+ command: 'ls -l', message: 'ok',
212
+ }.to_json
213
+
214
+ summary = described_class.summary_template(result:)
215
+ expect(summary).to include('ls -l')
216
+ expect(summary).to include('exit 0')
217
+ end
218
+
219
+ it 'summary_template includes error message for cancelled' do
220
+ result = {
221
+ error: 'OllamaChat::ToolFunctionArgumentError',
222
+ command: 'rm -rf .',
223
+ message: 'Shell command cancelled by user: rm -rf .',
224
+ }.to_json
225
+
226
+ summary = described_class.summary_template(result:)
227
+ expect(summary).to include('cancelled')
228
+ expect(summary).to include('rm -rf .')
229
+ end
230
+
231
+ end
232
+ end
@@ -40,12 +40,12 @@ describe OllamaChat::Tools::ReadFile do
40
40
  expect(json.content).to eq <<~EOT
41
41
  puts "Hello World!"
42
42
  EOT
43
- expect(json.message).to include('Read 20.0 B (6.0 T) from')
43
+ expect(json.message).to include('Read 6.0 T (20.0 B) from')
44
44
  expect(json.mtime).to match(/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
45
45
  expect(json.line_count).to be_nil
46
46
  expect(json.checksum).not_to be_present
47
47
  expect(described_class.summary_template(result:))\
48
- .to include('Read 20.0 B (6.0 T) from')
48
+ .to include('Read 6.0 T (20.0 B) from')
49
49
  end
50
50
 
51
51
  it 'can extract range when start_line is provided and end_line is nil' do
@@ -64,7 +64,7 @@ describe OllamaChat::Tools::ReadFile do
64
64
  result = described_class.new.execute(tool_call, chat:)
65
65
  json = json_object(result)
66
66
  expect(json.content).to eq "puts \"Hello World!\"\n"
67
- expect(json.message).to include('Read 20.0 B (6.0 T) from')
67
+ expect(json.message).to include('Read 6.0 T (20.0 B) from')
68
68
  expect(json.mtime).to match(/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
69
69
  expect(json.line_count).to be_nil
70
70
  expect(json.checksum).not_to be_present
@@ -86,7 +86,7 @@ describe OllamaChat::Tools::ReadFile do
86
86
  result = described_class.new.execute(tool_call, chat:)
87
87
  json = json_object(result)
88
88
  expect(json.content).to eq "puts \"Hello World!\"\n"
89
- expect(json.message).to include('Read 20.0 B (6.0 T) from')
89
+ expect(json.message).to include('Read 6.0 T (20.0 B) from')
90
90
  expect(json.mtime).to match(/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
91
91
  expect(json.line_count).to be_nil
92
92
  expect(json.checksum).not_to be_present
@@ -41,9 +41,9 @@ describe OllamaChat::Tools::WriteFile do
41
41
  json = json_object(result)
42
42
  expect(json.success).to eq true
43
43
  expect(json.path).to include(File.basename(test_write_file))
44
- expect(json.message).to include('Wrote 13.0 B (4.0 T) to file')
44
+ expect(json.message).to include('Wrote 4.0 T (13.0 B) to file')
45
45
  expect(described_class.summary_template(result:)).
46
- to include('Wrote 13.0 B (4.0 T) to file')
46
+ to include('Wrote 4.0 T (13.0 B) to file')
47
47
 
48
48
  # Verify file was actually written
49
49
  expect(File.exist?(test_write_file)).to be true
@@ -77,7 +77,7 @@ describe OllamaChat::Tools::WriteFile do
77
77
  expect(json.success).to eq true
78
78
  expect(File.read(test_write_file)).to eq 'New content'
79
79
  expect(described_class.summary_template(result:)).
80
- to include('Wrote 11.0 B (4.0 T) to file')
80
+ to include('Wrote 4.0 T (11.0 B) to file')
81
81
  ensure
82
82
  File.delete(test_write_file) if File.exist?(test_write_file)
83
83
  end
@@ -136,9 +136,9 @@ describe OllamaChat::Tools::WriteFile do
136
136
  json = json_object(result)
137
137
  expect(json.success).to be true
138
138
  expect(json.path).to include(File.basename(test_write_file))
139
- expect(json.message).to include('Wrote 18.0 B (6.0 T) to file')
139
+ expect(json.message).to include('Wrote 6.0 T (18.0 B) to file')
140
140
  expect(described_class.summary_template(result:)).
141
- to include('Wrote 18.0 B (6.0 T) to file')
141
+ to include('Wrote 6.0 T (18.0 B) to file')
142
142
 
143
143
  # Verify file was actually appended
144
144
  expect(File.exist?(test_write_file)).to be true
@@ -171,7 +171,7 @@ describe OllamaChat::Tools::WriteFile do
171
171
  expect(json.success).to eq true
172
172
  expect(File.read(test_write_file)).to eq 'First content\n'
173
173
  expect(described_class.summary_template(result:)).
174
- to include('Wrote 15.0 B (5.0 T) to file')
174
+ to include('Wrote 5.0 T (15.0 B) to file')
175
175
  ensure
176
176
  File.delete(test_write_file) if File.exist?(test_write_file)
177
177
  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.114
4
+ version: 0.0.115
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -557,6 +557,7 @@ extra_rdoc_files:
557
557
  - lib/ollama_chat/tools/execute_grep.rb
558
558
  - lib/ollama_chat/tools/execute_jira_twg.rb
559
559
  - lib/ollama_chat/tools/execute_ri.rb
560
+ - lib/ollama_chat/tools/execute_shell.rb
560
561
  - lib/ollama_chat/tools/file_context.rb
561
562
  - lib/ollama_chat/tools/gem_path_lookup.rb
562
563
  - lib/ollama_chat/tools/generate_image.rb
@@ -595,6 +596,7 @@ extra_rdoc_files:
595
596
  - lib/ollama_chat/utils/path_completer.rb
596
597
  - lib/ollama_chat/utils/path_validator.rb
597
598
  - lib/ollama_chat/utils/png_metadata_extractor.rb
599
+ - lib/ollama_chat/utils/strip_ansi.rb
598
600
  - lib/ollama_chat/utils/tag_resolver.rb
599
601
  - lib/ollama_chat/utils/utf8_converter.rb
600
602
  - lib/ollama_chat/utils/value_formatter.rb
@@ -694,6 +696,7 @@ files:
694
696
  - lib/ollama_chat/tools/execute_grep.rb
695
697
  - lib/ollama_chat/tools/execute_jira_twg.rb
696
698
  - lib/ollama_chat/tools/execute_ri.rb
699
+ - lib/ollama_chat/tools/execute_shell.rb
697
700
  - lib/ollama_chat/tools/file_context.rb
698
701
  - lib/ollama_chat/tools/gem_path_lookup.rb
699
702
  - lib/ollama_chat/tools/generate_image.rb
@@ -732,6 +735,7 @@ files:
732
735
  - lib/ollama_chat/utils/path_completer.rb
733
736
  - lib/ollama_chat/utils/path_validator.rb
734
737
  - lib/ollama_chat/utils/png_metadata_extractor.rb
738
+ - lib/ollama_chat/utils/strip_ansi.rb
735
739
  - lib/ollama_chat/utils/tag_resolver.rb
736
740
  - lib/ollama_chat/utils/utf8_converter.rb
737
741
  - lib/ollama_chat/utils/value_formatter.rb
@@ -809,6 +813,7 @@ files:
809
813
  - spec/ollama_chat/tools/execute_grep_spec.rb
810
814
  - spec/ollama_chat/tools/execute_jira_twg_spec.rb
811
815
  - spec/ollama_chat/tools/execute_ri_spec.rb
816
+ - spec/ollama_chat/tools/execute_shell_spec.rb
812
817
  - spec/ollama_chat/tools/file_context_spec.rb
813
818
  - spec/ollama_chat/tools/gem_path_lookup_spec.rb
814
819
  - spec/ollama_chat/tools/generate_image_spec.rb
@@ -915,6 +920,7 @@ test_files:
915
920
  - spec/ollama_chat/tools/execute_grep_spec.rb
916
921
  - spec/ollama_chat/tools/execute_jira_twg_spec.rb
917
922
  - spec/ollama_chat/tools/execute_ri_spec.rb
923
+ - spec/ollama_chat/tools/execute_shell_spec.rb
918
924
  - spec/ollama_chat/tools/file_context_spec.rb
919
925
  - spec/ollama_chat/tools/gem_path_lookup_spec.rb
920
926
  - spec/ollama_chat/tools/generate_image_spec.rb