ollama_chat 0.0.110 → 0.0.112

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: 239476f6dca2ca4fca22dc0290b25bb048572cc89d12ef82c09d54a7ee429068
4
- data.tar.gz: d7c51cf3d519c593666625bcedf487a1d40893099c251f211cd055a4610cb3db
3
+ metadata.gz: 7e680260fa6eb6e0fb4c81629a962bffba24af8824a3fe6851bf4084e5bd3172
4
+ data.tar.gz: 5c615c09ff36858276befde7029956941d8ee275b6da8b5bcffbe00099102d39
5
5
  SHA512:
6
- metadata.gz: 24eadaa6eb35470ff3908fbfd7646ad0b685bded30694b7784839aef35a447b6f6926c9cac6a29f4eed55d723065cdc063f21d7c718f3c15dc4905892f860484
7
- data.tar.gz: 98f4ab4370005f5a9523a7fc54ea62f56e64b411894d8ca40ae85518cae9962f8b9818086d5984f34aec392dde268377b10d33ef103e64ebc9b8abcd17702293
6
+ metadata.gz: 3707cb40694f7dc16cc011e4e57ca73ee282809de7ee4fad0bff69f06749a11444354310f82c9ffc475ff3ace01e054d19dc94b0d71ea849e6db21bfdf56e97b
7
+ data.tar.gz: c878bc0af562cf7519469345bb5c800b7382b5b523fa72d5bba6fe2da2d6bebc25e4657068fc02001222f45a1aaea7163ff0e6e28bbe190c0193b47f7f2ac67d
data/CHANGES.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-08-25 v0.0.112
4
+
5
+ * Added a `diff` subcommand to the `/config` command, including updated
6
+ regexp, completion, and help text.
7
+ * Extracted a `diff_config` method in `OllamaChat::ConfigHandling` that
8
+ resolves `OC::DIFF_TOOL` and launches a diff against
9
+ `@ollama_chat_config.filename` and
10
+ `@ollama_chat_config.default_config_path`.
11
+ * Simplified `fix_config` to delegate the diff invocation to `diff_config`.
12
+ * Added `#diff_config` specs covering both the missing-diff-tool path (STDERR
13
+ + `nil`) and the successful `system` invocation.
14
+
15
+ ## 2026-08-25 v0.0.111
16
+
17
+ ### Added
18
+
19
+ * `OllamaChat::Tools::ExecuteJiraTwg` tool
20
+ (`lib/ollama_chat/tools/execute_jira_twg.rb`) as a `twg` CLI wrapper,
21
+ featuring `Shellwords.shellsplit` argument parsing,
22
+ `OllamaChat::ExecuteError` handling for non-zero exits, and
23
+ `Kramdown::ANSI::Width.truncate` for feedback messages.
24
+ * `OC::OLLAMA::CHAT::TOOLS::JIRA::TWG` configuration constant, defaulting to
25
+ `which 2>/dev/null twg`.
26
+ * `execute_jira_twg` entry in `default_config.yml` with `default: false` and
27
+ `require_confirmation: true`.
28
+ * Two-step tool approval workflow in `FollowChat#handle_tool_calls`,
29
+ replacing single `chat.ask?` with `chat.confirm?` followed by `chat.ask?`
30
+ to allow single-keypress confirmation or free-text instructions.
31
+ * `session_sync` method in `session_management.rb` to persist messages,
32
+ links, history, update `working_directory`, and re-lock the session.
33
+ * `context_usage` method in `lib/ollama_chat/information.rb` to calculate and
34
+ format context usage, including `current_context_length` and
35
+ `context_filled` helpers.
36
+ * Context usage gauge in `info_session` displaying tokens used, total, and
37
+ percentage.
38
+ * `api_ps.json` asset containing a **27.3B** `qwen3.8:27b` model entry with a
39
+ **262144** context length.
40
+ * `spec/ollama_chat/tools/execute_jira_twg_spec.rb` with 8 specs covering
41
+ identity, execution, quoted arguments, nil guards, exception rescue, and
42
+ non-zero exits.
43
+ * `#session_sync` spec verifying ordered calls to
44
+ `store_messages_in_session`, `links.sync`, `save_history`, and
45
+ `session.lock`.
46
+
47
+ ### Changed
48
+
49
+ * `session_close` now delegates to `session_sync` before calling
50
+ `session.unlock`.
51
+ * `change_session` `ensure` block now uses `session_sync` instead of inline
52
+ `session.update(working_directory:)`.
53
+ * `set_new_session` now includes `ensure session.lock` to guarantee locking
54
+ on early return.
55
+ * `context_usage` logic extracted from `dynamic_runtime_information_values`
56
+ for improved maintainability.
57
+ * `session_management.rb` now logs the formatted `context_usage` string
58
+ instead of raw token counts and byte sizes.
59
+ * `self.register_name` in `lib/ollama_chat/tools/gem_path_lookup.rb`
60
+ simplified to use endless method definition syntax.
61
+ * Context ingestion logic now guards against empty file sets, emitting a
62
+ `STDERR` message and canceling if no files match the given patterns.
63
+ * `parsing_spec.rb` and `directory_structure_spec.rb` expected file counts
64
+ updated from **23** to **24**.
65
+
66
+ ### Fixed
67
+
68
+ * `current_context_length` now uses safe navigation operators to guard
69
+ against missing `ollama.ps` or `models`.
70
+ * `context_usage` body wrapped in a guard to return `nil` when context length
71
+ is unavailable.
72
+ * `which` stderr silenced in all OC config defaults using `2>/dev/null`.
73
+
3
74
  ## 2026-08-20 v0.0.110
4
75
 
5
76
  ### Added
@@ -62,11 +62,11 @@ module OllamaChat::Commands
62
62
 
63
63
  command(
64
64
  name: :config,
65
- regexp: %r(^/config(?:\s+(edit|reload))?$),
66
- complete: [ 'config', %w[ edit reload ] ],
65
+ regexp: %r(^/config(?:\s+(edit|reload|diff))?$),
66
+ complete: [ 'config', %w[ edit reload diff ] ],
67
67
  optional: true,
68
68
  help: <<~EOT
69
- \u2699\uFE0F View, edit, or reload configuration
69
+ \u2699\uFE0F View, edit, diff, or reload configuration
70
70
  EOT
71
71
  ) do |subcommand|
72
72
  case subcommand
@@ -74,9 +74,12 @@ module OllamaChat::Commands
74
74
  edit_config
75
75
  when 'reload'
76
76
  reload_config
77
+ when 'diff'
78
+ diff_config
77
79
  else
78
80
  display_config
79
81
  end
82
+
80
83
  :next
81
84
  end
82
85
 
@@ -594,14 +597,15 @@ module OllamaChat::Commands
594
597
 
595
598
  command(
596
599
  name: :conversation,
597
- regexp: %r(^/conversation\s+(clean|save|load)(\s+-c)?(?:\s+([^-].*\.jsonl?))?$),
598
- complete: [ 'conversation', %w[ save load clean ] ],
600
+ regexp: %r(^/conversation\s+(clean|compact|save|load)(\s+-c)?(?:\s+([^-].*\.jsonl?))?$),
601
+ complete: [ 'conversation', %w[ save load clean compact ] ],
599
602
  options: '[-c] [FILENAME]',
600
603
  help: <<~EOT
601
604
  💾 Save/Load conversation state
602
605
  (-c to clean before saving)
603
606
  FILENAME ends with .json or .jsonl
604
607
  Or clean inplace (removes tool content, images, and thinking)
608
+ Or compact (summarize old messages, keep recent)
605
609
  EOT
606
610
  ) do |subcommand,opts,path|
607
611
  if %w[ save load ].include?(subcommand) && path.blank?
@@ -622,11 +626,23 @@ module OllamaChat::Commands
622
626
  )
623
627
  then
624
628
  messages.clean_messages!
625
- session_close
629
+ session_sync
626
630
  STDOUT.puts "Conversation cleaned."
627
631
  else
628
632
  STDOUT.puts 'Cancelled.'
629
633
  end
634
+ when 'compact'
635
+ if confirm?(
636
+ prompt: '🔔 Compact conversation? Old messages will be summarized. (y/n) ',
637
+ yes: /\Ay/i
638
+ )
639
+ then
640
+ messages.compact!
641
+ session_sync
642
+ STDOUT.puts "Conversation compacted."
643
+ else
644
+ STDOUT.puts 'Cancelled.'
645
+ end
630
646
  end
631
647
  :next
632
648
  end
@@ -44,6 +44,22 @@ module OllamaChat::ConfigHandling
44
44
  end
45
45
  end
46
46
 
47
+ # Opens a diff tool to compare the current config file with the
48
+ # default config, allowing the user to visually inspect differences.
49
+ #
50
+ # @return [Boolean, nil] the result of +system+ if a diff tool was
51
+ # found, or +nil+ if no diff tool is configured.
52
+ def diff_config
53
+ diff_tool = OC::DIFF_TOOL? or
54
+ return STDERR.puts 'No diff tool configured (OC::DIFF_TOOL).'
55
+ cmd = [
56
+ diff_tool,
57
+ @ollama_chat_config.filename,
58
+ @ollama_chat_config.default_config_path,
59
+ ].map(&:to_s)
60
+ system(*cmd)
61
+ end
62
+
47
63
  # The fix_config method handles configuration file errors by informing the
48
64
  # user about the exception and prompting them to fix it. It then executes a
49
65
  # diff tool to compare the current config file with the default one.
@@ -52,9 +68,9 @@ module OllamaChat::ConfigHandling
52
68
  # @param exception [Exception] the exception that occurred while reading
53
69
  # the config file
54
70
  def fix_config(exception)
55
- STDOUT.puts "When reading the config file, a #{exception.class} "\
71
+ STDOUT.puts "When reading the config file, a #{exception.class} " \
56
72
  "exception was caught: #{exception.message.inspect}"
57
- unless diff_tool = OC::DIFF_TOOL?
73
+ unless OC::DIFF_TOOL?
58
74
  exit 1
59
75
  end
60
76
  if confirm?(
@@ -62,18 +78,14 @@ module OllamaChat::ConfigHandling
62
78
  yes: /\Ay/i
63
79
  )
64
80
  then
65
- cmd = [
66
- diff_tool,
67
- @ollama_chat_config.filename,
68
- @ollama_chat_config.default_config_path,
69
- ].map(&:to_s)
70
- system(*cmd)
81
+ diff_config
71
82
  exit 0
72
83
  else
73
84
  exit 1
74
85
  end
75
86
  end
76
87
 
88
+
77
89
  # Adjusts the command-line argument array to ensure the current session is
78
90
  # explicitly reloaded by injecting the `-l <session_id>` flag.
79
91
  #
@@ -137,18 +137,25 @@ class OllamaChat::FollowChat
137
137
  end
138
138
  STDOUT.puts
139
139
  confirmed = :implicit
140
- function = JSON.pretty_generate(tool_call.function)
140
+ resolve = nil
141
+ function = JSON.pretty_generate(tool_call.function)
141
142
  chat.log(:info, "Tool call received", data: { tool: name, function: })
142
143
  if chat.tool_function(name).require_confirmation?
143
- prompt = "🔔 I want to execute tool %s\n%s\nConfirm? (y/n) " % [
144
- bold { name },
145
- italic { function },
144
+ STDOUT.puts "🔔 I want to execute tool %s\n%s\n" % [
145
+ bold { name }, italic { function },
146
146
  ]
147
- prompt.gsub!('%', '%%')
148
- if chat.confirm?(prompt:, yes: /\Ay/i)
147
+ prompt = ' Allow ✅[y]es / ⛔️[n]o / 📝[i]nstruct? '
148
+ answer = chat.confirm?(prompt:)&.to_s&.downcase
149
+ resolve = 'You **MUST** ask the user for instructions on how to proceed!!!'
150
+ case answer
151
+ when 'y'
149
152
  confirmed = :explicit
153
+ when 'n'
154
+ confirmed = :denied
150
155
  else
151
156
  confirmed = :denied
157
+ instr = chat.ask?(prompt: '📝 Instructions: ')&.strip
158
+ resolve = instr.full? || resolve
152
159
  end
153
160
  else
154
161
  STDOUT.puts "Executing tool %s\n%s" % [
@@ -160,10 +167,7 @@ class OllamaChat::FollowChat
160
167
  result = nil
161
168
  case confirmed
162
169
  when :denied
163
- result = JSON(
164
- message: 'User denied confirmation!',
165
- resolve: 'You **MUST** ask the user for instructions on how to proceed!!!',
166
- )
170
+ result = JSON(message: 'User denied confirmation!', resolve:)
167
171
  STDOUT.printf(
168
172
  "\n%s Execution of tool %s denied by user.\n\n", ?🚫, bold { name }
169
173
  )
@@ -174,11 +178,7 @@ class OllamaChat::FollowChat
174
178
  "\n%s Execution of tool %s confirmed.\n\n", symbol, bold { name }
175
179
  )
176
180
  result = OllamaChat::Tools.registered[name].execute(tool_call, chat:)
177
- if confirmed == :explicit
178
- chat.log(:info, "Tool execution confirmed", data: { tool: name, confirmed: })
179
- else
180
- chat.log(:info, "Tool execution confirmed", data: { tool: name, confirmed: })
181
- end
181
+ chat.log(:info, "Tool execution confirmed", data: { tool: name, confirmed: })
182
182
  end
183
183
 
184
184
  chat.tool_call_results[name] << result
@@ -132,6 +132,12 @@ module OllamaChat::Information
132
132
  output.puts " No persona selected."
133
133
  end
134
134
  output.puts "🧠 Current chat model is #{bold{@model}}."
135
+ context_usage = '%s of %s (%s)' % [
136
+ session.estimate_tokens.tokens_formatted,
137
+ format_tokens(current_context_length),
138
+ bold { '%.1f%%' % (100 * context_filled)},
139
+ ]
140
+ output.puts " Context Length: #{context_usage}"
135
141
  output.print ' '; think_mode.show(output:)
136
142
  output.print ' '; think_loud.show(output:)
137
143
  output.print ' '; think_strip.show(output:)
@@ -360,6 +366,7 @@ module OllamaChat::Information
360
366
  tools_support: tools_support.on? ? 'enabled' : 'disabled',
361
367
  voice: voice.on? ? 'enabled' : 'disabled',
362
368
  weekday: now.strftime('%A'),
369
+ context_usage: ,
363
370
  }
364
371
  end
365
372
 
@@ -373,4 +380,47 @@ module OllamaChat::Information
373
380
  def dynamic_runtime_information
374
381
  prompt(:dynamic_runtime_info).to_s % dynamic_runtime_information_values
375
382
  end
383
+
384
+ # Resolves the effective context window size for the current model.
385
+ #
386
+ # Prefers the session-level `num_ctx` override (set via `/model_options`
387
+ # or the stored model options profile). Falls back to the model's native
388
+ # `context_length` in the default profile or as reported by the Ollama server
389
+ # if possible.
390
+ #
391
+ # @return [Integer, NilClass] the context length in tokens or nil
392
+ def current_context_length
393
+ get_session_model_options[:num_ctx] ||
394
+ get_stored_model_options(@model)[:num_ctx] ||
395
+ ollama.ps&.models&.find { _1.name == @model }&.context_length
396
+ end
397
+
398
+ # Computes the fraction of the context window currently in use.
399
+ #
400
+ # Divides the estimated token count of the session's messages by the
401
+ # effective context length, clamped to the range 0.0–1.0.
402
+ #
403
+ # @return [Float] the ratio of used context (e.g. `0.73` for 73%)
404
+ def context_filled
405
+ es = session.estimate_tokens
406
+ (es.tokens.to_f / current_context_length).clamp(0..1).to_f
407
+ end
408
+
409
+ # Formats the current context usage as a human-readable string.
410
+ #
411
+ # Returns a string like `"167.7 KT of 262.1 KT (64.0%)"` combining
412
+ # the estimated tokens in use, the effective context length, and
413
+ # the percentage (via +context_filled+).
414
+ #
415
+ # @return [String, nil] the formatted usage string, or +nil+ if
416
+ # the context length cannot be determined.
417
+ def context_usage
418
+ if cl = current_context_length
419
+ '%s of %s (%s)' % [
420
+ session.estimate_tokens.tokens_formatted,
421
+ format_tokens(current_context_length),
422
+ '%.1f%%' % (100 * context_filled),
423
+ ]
424
+ end
425
+ end
376
426
  end
@@ -95,14 +95,22 @@ module OllamaChat::InputContent
95
95
  format = @context_format.selected
96
96
  myself = self
97
97
  if patterns
98
- ContextSpook::generate_context(verbose: true, format:) do |context|
98
+ count = 0
99
+ ctx = ContextSpook::generate_context(verbose: true, format:) do |context|
99
100
  context do
100
101
  myself.file_set_each(patterns, all:) do |filename|
101
102
  filename.file? or next
102
103
  file filename.to_path
104
+ count += 1
103
105
  end
104
106
  end
105
- end.send("to_#{format.downcase}")
107
+ end
108
+ if count > 0
109
+ ctx.send("to_#{format.downcase}")
110
+ STDOUT.puts "✅ Ingesting context now."
111
+ else
112
+ STDERR.puts "❌ No files in context. ⇨ Cancelled."
113
+ end
106
114
  else
107
115
  if context_filename = choose_filename('.contexts/*.rb')
108
116
  ContextSpook.generate_context(context_filename, verbose: true, format:).
@@ -39,7 +39,7 @@ module OC
39
39
  description 'Pager command to use in case terminal lines are exceeded by output'
40
40
 
41
41
  default do
42
- if fallback_pager = `which less`.full?(:chomp) || `which more`.full?(:chomp)
42
+ if fallback_pager = `which 2>/dev/null less`.full?(:chomp) || `which 2>/dev/null more`.full?(:chomp)
43
43
  fallback_pager << ' -r'
44
44
  end
45
45
  end
@@ -49,7 +49,7 @@ module OC
49
49
  description 'Editor to use'
50
50
 
51
51
  default do
52
- if editor = %w[ vim vi ].find { `which #{_1}`.full?(:chomp) }
52
+ if editor = %w[ vim vi ].find { `which 2>/dev/null #{_1}`.full?(:chomp) }
53
53
  editor
54
54
  else
55
55
  warn 'Need an editor command configured via env var "EDITOR"'
@@ -61,7 +61,7 @@ module OC
61
61
  description 'Browser to use'
62
62
 
63
63
  default do
64
- %w[ open xdg-open ].find { `which #{_1}` }.full?(:chomp)
64
+ %w[ open xdg-open ].find { `which 2>/dev/null #{_1}` }.full?(:chomp)
65
65
  end
66
66
  end
67
67
 
@@ -77,7 +77,7 @@ module OC
77
77
  description 'Diff tool to apply changes with'
78
78
 
79
79
  default do
80
- if diff = `which vimdiff`.full?(:chomp)
80
+ if diff = `which 2>/dev/null vimdiff`.full?(:chomp)
81
81
  diff
82
82
  else
83
83
  warn 'Need a diff tool configured via env var "DIFF_TOOL"'
@@ -193,7 +193,7 @@ module OC
193
193
 
194
194
  CTAGS_TOOL = set do
195
195
  description 'Tools ctags path'
196
- default { `which ctags`.full?(:chomp) }
196
+ default { `which 2>/dev/null ctags`.full?(:chomp) }
197
197
  check { value.blank? || File.exist?(value) }
198
198
  end
199
199
 
@@ -240,6 +240,11 @@ module OC
240
240
  sensitive true
241
241
  required { OC::OLLAMA::CHAT::TOOLS::JIRA::URL? }
242
242
  end
243
+
244
+ TWG = set do
245
+ description 'Path to the twg CLI binary'
246
+ default { `which 2>/dev/null twg`.full?(:chomp) }
247
+ end
243
248
  end
244
249
 
245
250
  module IMAGE_GENERATOR
@@ -73,6 +73,7 @@ prompts:
73
73
  80%% of this width in your output of responses, especially when using
74
74
  markdown tables.
75
75
  - **Session**: %{session_name}
76
+ - Context usage is %{context_usage}.
76
77
  - Markdown output is %{markdown}. **Never** output markdown as your
77
78
  responses if it is disabled.
78
79
  - Voice output is %{voice}. Speak naturally and short if voice
@@ -507,6 +508,10 @@ tools:
507
508
  result_display_timeout: 3
508
509
  default: false
509
510
  require_confirmation: true
511
+ execute_jira_twg:
512
+ result_display_timeout: 3
513
+ default: false
514
+ require_confirmation: true
510
515
  get_rfc:
511
516
  url: "https://www.rfc-editor.org/rfc/rfc%{rfc_id}.txt"
512
517
  result_display_timeout: 3
@@ -15,10 +15,10 @@ module OllamaChat::SessionManagement
15
15
  session.update(messages: output.string)
16
16
  es = session.estimate_tokens
17
17
  log(:info, "Messages stored in session", data: {
18
- session_id: session.id,
19
- size: es.bytes_formatted,
20
- tokens: es.tokens_formatted,
21
- messages: session.count_messages
18
+ session_id: session.id,
19
+ size: es.bytes_formatted,
20
+ context_usage: ,
21
+ messages: session.count_messages
22
22
  })
23
23
  self
24
24
  end
@@ -197,6 +197,8 @@ module OllamaChat::SessionManagement
197
197
  }
198
198
  log(:info, "New session created", data: { session_id: session.id, name: session.name })
199
199
  nil
200
+ ensure
201
+ session.lock
200
202
  end
201
203
 
202
204
  # Duplicates the current session into a new one.
@@ -410,14 +412,27 @@ module OllamaChat::SessionManagement
410
412
  end
411
413
  end
412
414
 
413
- # Closes the current session by persisting final messages and releasing
414
- # the process lock. This should be called during application shutdown
415
- # or when switching sessions to ensure the session is available for
416
- # future instances.
417
- def session_close
415
+ # Synchronizes the current session state to the database.
416
+ #
417
+ # Persists messages, links, and history, updates the working directory,
418
+ # and re-locks the session. Called before closing or switching sessions
419
+ # to ensure no unsaved state is lost.
420
+ #
421
+ # @return [OllamaChat::Database::Models::Session] the current session
422
+ def session_sync
418
423
  store_messages_in_session
419
424
  links.sync
420
425
  save_history
426
+ session.working_directory = Dir.pwd
427
+ session.lock
428
+ session
429
+ end
430
+
431
+ # Closes the current session synchronizing it first and releasing the process
432
+ # lock. This should be called during application shutdown or when switching
433
+ # sessions to ensure the session is available for future instances.
434
+ def session_close
435
+ session_sync
421
436
  session.unlock
422
437
  end
423
438
 
@@ -470,7 +485,7 @@ module OllamaChat::SessionManagement
470
485
  end
471
486
  ensure
472
487
  set_previous_session_on_change(previous_session_id)
473
- session.update(working_directory: Dir.pwd)
488
+ session_sync
474
489
  end
475
490
 
476
491
  # Records the previous session ID after a session transition.
@@ -0,0 +1,85 @@
1
+ # A tool for executing TWG CLI commands.
2
+ #
3
+ # This tool allows the chat client to run `twg` subcommands for Atlassian
4
+ # Teamwork Graph operations — Jira workitems, Confluence, Rovo search,
5
+ # user lookups, and more. It integrates with the Ollama tool calling
6
+ # system to provide project-management and cross-product capabilities.
7
+ #
8
+ # The command string is parsed with Shellwords.shellsplit to safely
9
+ # handle quoted arguments (e.g. JQL, rich text) before execution.
10
+ class OllamaChat::Tools::ExecuteJIRATWG
11
+ include OllamaChat::Tools::Concern
12
+
13
+ # @return [String] the registered name for this tool
14
+ def self.register_name = 'execute_jira_twg'
15
+
16
+ # Returns the tool definition for use with the Ollama API.
17
+ #
18
+ # @return [OllamaChat::Tool] The tool definition
19
+ def tool
20
+ Tool.new(
21
+ type: 'function',
22
+ function: Tool::Function.new(
23
+ name:,
24
+ description: <<~EOT,
25
+ TWG CLI executor – Runs a `twg` subcommand against the Atlassian
26
+ Teamwork Graph. Command families: `jira workitem` (get, search,
27
+ query, transition, comment, link), `confluence`, `user`, `work`,
28
+ `rovo search`, `org-tree`, `goals`, `projects`, `assets`,
29
+ `pull-requests`, `search-code`, `trello`, `context`.
30
+ Use `help discover-skills "<intent>"` or `help describe
31
+ "skill:<name>/<path>"` to discover syntax.
32
+ Read-only commands are safe; mutations (transition, comment,
33
+ create, update, link) change Jira/Confluence state.
34
+ EOT
35
+ parameters: Tool::Function::Parameters.new(
36
+ type: 'object',
37
+ properties: {
38
+ command: Tool::Function::Parameters::Property.new(
39
+ type: 'string',
40
+ description: 'The twg subcommand and arguments, ' \
41
+ 'e.g. "jira workitem get DEV-29042" or ' \
42
+ 'jira workitem query --jql \"project = DEV\"'
43
+ ),
44
+ },
45
+ required: %w[command]
46
+ )
47
+ )
48
+ )
49
+ end
50
+
51
+ # Executes the twg command with the provided arguments.
52
+ #
53
+ # @param tool_call [OllamaChat::Tool::Call] The tool call with arguments
54
+ # @param opts [Hash] Additional options
55
+ # @option opts [OllamaChat::Chat] :chat the chat instance
56
+ # @return [String] The execution result as JSON string
57
+ def execute(tool_call, **opts)
58
+ chat = opts[:chat]
59
+ command = tool_call.function.arguments.command
60
+ command.full? or raise OllamaChat::ToolFunctionArgumentError,
61
+ 'require a command for twg'
62
+ twg_path = OC::OLLAMA::CHAT::TOOLS::JIRA::TWG? or
63
+ raise OllamaChat::ConfigMissingError,
64
+ 'Require env var %s configuration for TWG CLI' %
65
+ OC::OLLAMA::CHAT::TOOLS::JIRA::TWG!.env_var_name
66
+ args = Shellwords.shellsplit(command)
67
+ cmd = [twg_path] + args
68
+ result = OllamaChat::Utils::Fetcher.execute(cmd, &:read)
69
+ if status = $?.exitstatus.nonzero?
70
+ raise OllamaChat::ExecuteError,
71
+ "twg #{command} exited with code #{status}:\n#{result}"
72
+ end
73
+ chat.log(:info, 'TWG executed', data: { tool: name, command: })
74
+ message = Kramdown::ANSI::Width.truncate(
75
+ result.lines.map(&:strip).reject(&:empty?).first || '(empty)',
76
+ percentage: 90
77
+ )
78
+ { cmd:, result:, message: }.to_json
79
+ rescue => e
80
+ chat.log(:error, e, data: { tool: name, command: })
81
+ { error: e.class, message: e.message }.to_json
82
+ end
83
+
84
+ self
85
+ end.register
@@ -7,9 +7,7 @@ class OllamaChat::Tools::GemPathLookup
7
7
  include OllamaChat::Tools::Concern
8
8
 
9
9
  # @return [String] the registered name for this tool
10
- def self.register_name
11
- 'gem_path_lookup'
12
- end
10
+ def self.register_name = 'gem_path_lookup'
13
11
 
14
12
  # Creates and returns a tool definition for gem path lookup.
15
13
  #
@@ -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_jira_twg'
51
52
  require 'ollama_chat/tools/file_context'
52
53
  require 'ollama_chat/tools/gem_path_lookup'
53
54
  require 'ollama_chat/tools/generate_image'
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.110'
3
+ VERSION = '0.0.112'
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.110 ruby lib
2
+ # stub: ollama_chat 0.0.112 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ollama_chat".freeze
6
- s.version = "0.0.110".freeze
6
+ s.version = "0.0.112".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/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/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_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/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_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/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/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_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/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_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_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/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/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/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_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/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_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/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/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/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_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/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/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/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_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/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/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/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/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_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/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/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/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_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/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_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/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/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/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/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_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,23 @@
1
+ {
2
+ "models": [
3
+ {
4
+ "name": "qwen3.8:27b",
5
+ "model": "qwen3.8:27b",
6
+ "size": 20178387594,
7
+ "digest": "22130167c4c20e20c7b71454612966ca8e8171e9b3cc8ab6ce8aa6cbfec79643",
8
+ "details": {
9
+ "parent_model": "",
10
+ "format": "gguf",
11
+ "family": "qwen35",
12
+ "families": [
13
+ "qwen35"
14
+ ],
15
+ "parameter_size": "27.3B",
16
+ "quantization_level": "Q4_K_M"
17
+ },
18
+ "expires_at": "2026-08-25T01:10:55.582506803Z",
19
+ "size_vram": 16231411218,
20
+ "context_length": 262144
21
+ }
22
+ ]
23
+ }
@@ -532,6 +532,18 @@ describe OllamaChat::Commands, protect_env: true do
532
532
  expect(chat).to receive(:confirm?).and_return false
533
533
  expect(chat.handle_input("/conversation clean")).to eq :next
534
534
  end
535
+
536
+ it 'returns :next when input is "/conversation compact"' do
537
+ expect(chat).to receive(:confirm?).and_return true
538
+ expect(chat.messages).to receive(:compact!)
539
+ expect(chat).to receive(:session_sync)
540
+ expect(chat.handle_input("/conversation compact")).to eq :next
541
+ end
542
+
543
+ it 'returns :next when input is "/conversation compact" and user cancels' do
544
+ expect(chat).to receive(:confirm?).and_return false
545
+ expect(chat.handle_input("/conversation compact")).to eq :next
546
+ end
535
547
  end
536
548
 
537
549
  describe 'tools' do
@@ -110,6 +110,36 @@ describe OllamaChat::ConfigHandling do
110
110
  end
111
111
  end
112
112
 
113
+ describe '#diff_config' do
114
+ context 'without a diff tool' do
115
+ before do
116
+ expect(OC).to receive(:DIFF_TOOL?).and_return(nil)
117
+ end
118
+
119
+ it 'prints an error to STDERR and returns nil' do
120
+ expect(STDERR).to receive(:puts).with(/No diff tool configured/)
121
+ expect(chat.diff_config).to be_nil
122
+ end
123
+ end
124
+
125
+ context 'with a diff tool' do
126
+ before { const_conf_as('OC::DIFF_TOOL' => 'vimdiff') }
127
+
128
+ it 'launches the diff tool with config and default paths' do
129
+ expect(chat.instance_variable_get(:@ollama_chat_config))
130
+ .to receive(:filename).and_return('/cfg.yml')
131
+ .ordered
132
+ expect(chat.instance_variable_get(:@ollama_chat_config))
133
+ .to receive(:default_config_path).and_return('/default.yml')
134
+ .ordered
135
+ expect(chat).to receive(:system)
136
+ .with('vimdiff', '/cfg.yml', '/default.yml')
137
+ .and_return(true)
138
+ expect(chat.diff_config).to be true
139
+ end
140
+ end
141
+ end
142
+
113
143
  describe '#edit_config' do
114
144
  it 'edits the config and restarts on confirmation' do
115
145
  expect(chat).to receive(:edit_file).and_return(true)
@@ -289,7 +289,7 @@ describe OllamaChat::Parsing do
289
289
  json = JSON(json_data)
290
290
  expect(json.map { _1['name'] }.sort).to eq(
291
291
  [
292
- "api_show.json", "api_tags.json", "api_version.json",
292
+ "api_show.json", "api_tags.json", "api_version.json", "api_ps.json",
293
293
  "conversation.json", "conversation.jsonl", "deep", "duckduckgo.html",
294
294
  "example.atom", "example.csv", "example.html", "example.pdf",
295
295
  "example.epub", "example.ps", "example.rb", "example.rss",
@@ -177,15 +177,27 @@ describe OllamaChat::SessionManagement do
177
177
  end
178
178
 
179
179
  describe '#session_close' do
180
- it 'stores messages, syncs links, saves history, and unlocks session' do
181
- expect(chat).to receive(:store_messages_in_session)
182
- expect(chat).to receive(:links).and_return(double(sync: nil))
183
- expect(chat).to receive(:save_history)
180
+ it 'synchronizes and unlocks session' do
181
+ expect(chat).to receive(:session_sync)
184
182
  expect(chat.session).to receive(:unlock)
185
183
  chat.session_close
186
184
  end
187
185
  end
188
186
 
187
+ describe '#session_sync' do
188
+ it 'stores messages, syncs links, saves history, and locks' do
189
+ expect(Dir).to receive(:pwd).and_return('/sync_test')
190
+ expect(chat).to receive(:store_messages_in_session).ordered
191
+ expect(chat.links).to receive(:sync).ordered
192
+ expect(chat).to receive(:save_history).ordered
193
+ expect(chat.session).to receive(:lock).ordered
194
+
195
+ result = chat.session_sync
196
+ expect(result).to eq(chat.session)
197
+ expect(chat.session.working_directory).to eq('/sync_test')
198
+ end
199
+ end
200
+
189
201
  describe '#session_apply' do
190
202
  it 'updates working directory and initializes history' do
191
203
  expect(Dir).to receive(:pwd).and_return('/curr')
@@ -31,7 +31,7 @@ describe OllamaChat::Tools::DirectoryStructure do
31
31
  # Should return valid JSON
32
32
  expect(result).to be_a(String)
33
33
  json = json_object(result)
34
- expect(json.size).to eq 23
34
+ expect(json.size).to eq 24
35
35
  end
36
36
 
37
37
  it 'can be executed successfully with no arguments (defaults)' do
@@ -0,0 +1,140 @@
1
+ describe OllamaChat::Tools::ExecuteJIRATWG do
2
+ let :chat do
3
+ OllamaChat::Chat.new(argv: chat_default_config)
4
+ end
5
+
6
+ connect_to_ollama_server
7
+
8
+ it 'can have name' do
9
+ expect(described_class.new.name).to eq 'execute_jira_twg'
10
+ end
11
+
12
+ it 'can have tool' do
13
+ expect(described_class.new.tool).to be_a Ollama::Tool
14
+ end
15
+
16
+ it 'can be converted to hash' do
17
+ expect(described_class.new.to_hash).to be_a Hash
18
+ end
19
+
20
+ context 'when executed successfully' do
21
+ let(:command) { 'jira workitem get DEV-29042' }
22
+
23
+ before do
24
+ expect(OC::OLLAMA::CHAT::TOOLS::JIRA).to receive(:TWG?).and_return('true')
25
+ system('true') # reset $? to exit 0
26
+ expect(OllamaChat::Utils::Fetcher).to receive(:execute)
27
+ .with(%w[true jira workitem get DEV-29042])
28
+ .and_return('{ "key": "DEV-29042" }')
29
+ end
30
+
31
+ it 'returns JSON containing cmd and result' do
32
+ tool_call = double(
33
+ 'ToolCall',
34
+ function: double(
35
+ name: 'execute_jira_twg',
36
+ arguments: double(command:)
37
+ )
38
+ )
39
+
40
+ result = described_class.new.execute(tool_call, chat:)
41
+
42
+ expect(result).to be_a String
43
+ json = json_object(result)
44
+ expect(json.cmd).to include('true')
45
+ expect(json.cmd).to include('DEV-29042')
46
+ expect(json.result).to eq '{ "key": "DEV-29042" }'
47
+ expect(json.message).to include('DEV-29042')
48
+ end
49
+ end
50
+
51
+ context 'when command contains quoted arguments' do
52
+ let(:command) { 'jira workitem query --jql "project = DEV AND status != Done"' }
53
+
54
+ before do
55
+ expect(OC::OLLAMA::CHAT::TOOLS::JIRA).to receive(:TWG?).and_return('true')
56
+ system('true') # reset $? to exit 0
57
+ expect(OllamaChat::Utils::Fetcher).to receive(:execute)
58
+ .with(['true', 'jira', 'workitem', 'query', '--jql', 'project = DEV AND status != Done'])
59
+ .and_return('{ "issues": [] }')
60
+ end
61
+
62
+ it 'parses shell-quoted arguments correctly' do
63
+ tool_call = double(
64
+ 'ToolCall',
65
+ function: double(
66
+ name: 'execute_jira_twg',
67
+ arguments: double(command:)
68
+ )
69
+ )
70
+
71
+ result = described_class.new.execute(tool_call, chat:)
72
+
73
+ json = json_object(result)
74
+ expect(json.result).to eq '{ "issues": [] }'
75
+ end
76
+ end
77
+
78
+ context 'when command is missing or invalid' do
79
+ it 'returns an error JSON due to ToolFunctionArgumentError' do
80
+ tool_call = double(
81
+ 'ToolCall',
82
+ function: double(
83
+ name: 'execute_jira_twg',
84
+ arguments: double(command: nil)
85
+ )
86
+ )
87
+
88
+ result = described_class.new.execute(tool_call, chat:)
89
+
90
+ json = json_object(result)
91
+ expect(json.error).to eq('OllamaChat::ToolFunctionArgumentError')
92
+ end
93
+ end
94
+
95
+ context 'when fetcher raises an exception' do
96
+ before do
97
+ expect(OC::OLLAMA::CHAT::TOOLS::JIRA).to receive(:TWG?).and_return('true')
98
+ expect(OllamaChat::Utils::Fetcher).to receive(:execute)
99
+ .and_raise('twg: command not found')
100
+ end
101
+
102
+ it 'returns a JSON with the error class and message' do
103
+ tool_call = double(
104
+ 'ToolCall',
105
+ function: double(
106
+ name: 'execute_jira_twg',
107
+ arguments: double(command: 'user get')
108
+ )
109
+ )
110
+
111
+ result = described_class.new.execute(tool_call, chat:)
112
+
113
+ json = json_object(result)
114
+ expect(json.error).to eq('RuntimeError')
115
+ expect(json.message).to include('twg: command not found')
116
+ end
117
+ end
118
+
119
+ context 'when twg exits with non-zero status' do
120
+ before do
121
+ expect(OC::OLLAMA::CHAT::TOOLS::JIRA).to receive(:TWG?).and_return('false')
122
+ end
123
+
124
+ it 'returns a JSON with ExecuteError' do
125
+ tool_call = double(
126
+ 'ToolCall',
127
+ function: double(
128
+ name: 'execute_jira_twg',
129
+ arguments: double(command: 'jira workitem get DEV-29042')
130
+ )
131
+ )
132
+
133
+ result = described_class.new.execute(tool_call, chat:)
134
+
135
+ json = json_object(result)
136
+ expect(json.error).to eq('OllamaChat::ExecuteError')
137
+ expect(json.message).to include('exited with code 1')
138
+ end
139
+ end
140
+ end
data/spec/spec_helper.rb CHANGED
@@ -166,6 +166,8 @@ module StubOllamaServer
166
166
  to_return(status: 200, body: asset_json('api_show.json'))
167
167
  stub_request(:get, %r(/api/version\z)).
168
168
  to_return(status: 200, body: asset_json('api_version.json'))
169
+ stub_request(:get, %r(/api/ps\z)).
170
+ to_return(status: 200, body: asset_json('api_ps.json'))
169
171
  allow_any_instance_of(OllamaChat::Chat).to receive(:connect_message)
170
172
  allow_any_instance_of(OllamaChat::Chat).to receive(:info_session)
171
173
  instantiate and chat
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.110
4
+ version: 0.0.112
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -553,6 +553,7 @@ extra_rdoc_files:
553
553
  - lib/ollama_chat/tools/directory_structure.rb
554
554
  - lib/ollama_chat/tools/eval_ruby.rb
555
555
  - lib/ollama_chat/tools/execute_grep.rb
556
+ - lib/ollama_chat/tools/execute_jira_twg.rb
556
557
  - lib/ollama_chat/tools/execute_ri.rb
557
558
  - lib/ollama_chat/tools/file_context.rb
558
559
  - lib/ollama_chat/tools/gem_path_lookup.rb
@@ -685,6 +686,7 @@ files:
685
686
  - lib/ollama_chat/tools/directory_structure.rb
686
687
  - lib/ollama_chat/tools/eval_ruby.rb
687
688
  - lib/ollama_chat/tools/execute_grep.rb
689
+ - lib/ollama_chat/tools/execute_jira_twg.rb
688
690
  - lib/ollama_chat/tools/execute_ri.rb
689
691
  - lib/ollama_chat/tools/file_context.rb
690
692
  - lib/ollama_chat/tools/gem_path_lookup.rb
@@ -731,6 +733,7 @@ files:
731
733
  - lib/ollama_chat/web_searching.rb
732
734
  - ollama_chat.gemspec
733
735
  - redis/redis.conf
736
+ - spec/assets/api_ps.json
734
737
  - spec/assets/api_show.json
735
738
  - spec/assets/api_tags.json
736
739
  - spec/assets/api_version.json
@@ -793,6 +796,7 @@ files:
793
796
  - spec/ollama_chat/tools/delete_file_spec.rb
794
797
  - spec/ollama_chat/tools/directory_structure_spec.rb
795
798
  - spec/ollama_chat/tools/execute_grep_spec.rb
799
+ - spec/ollama_chat/tools/execute_jira_twg_spec.rb
796
800
  - spec/ollama_chat/tools/execute_ri_spec.rb
797
801
  - spec/ollama_chat/tools/file_context_spec.rb
798
802
  - spec/ollama_chat/tools/gem_path_lookup_spec.rb
@@ -893,6 +897,7 @@ test_files:
893
897
  - spec/ollama_chat/tools/delete_file_spec.rb
894
898
  - spec/ollama_chat/tools/directory_structure_spec.rb
895
899
  - spec/ollama_chat/tools/execute_grep_spec.rb
900
+ - spec/ollama_chat/tools/execute_jira_twg_spec.rb
896
901
  - spec/ollama_chat/tools/execute_ri_spec.rb
897
902
  - spec/ollama_chat/tools/file_context_spec.rb
898
903
  - spec/ollama_chat/tools/gem_path_lookup_spec.rb