ollama_chat 0.0.128 → 0.0.130

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: a8c69119a9431fed33aea9fe4f2f23594eea70c570fb5f08b39b88daee8bd31a
4
- data.tar.gz: efd37e4ba7c7971369bf4bd3f7ea95dd1a031f21f54f8a1b438a516db5b577c1
3
+ metadata.gz: 01d91ba996f30f84990c3d3eb60d0e65cc46b3eb0c593bd55eab6cc580e935e1
4
+ data.tar.gz: 28563308f748187b5cf15dcad886a775dcb6d2abd3c4466ab66854a10dec63fd
5
5
  SHA512:
6
- metadata.gz: cadf4af1255ea0232708e463b4c48f8b7497a556e4e14766f83c2291da8de7c9f77591da2a1d43678502d41bf414ed2e806ca46ef744d09ca85a33212474891a
7
- data.tar.gz: 3e286668006435fe9fc00fdafbaa21d1d422ac99b00631838a69b2e334de30a50e3421a5172763827021370d3eb20eacdf16f7ca5f01a60a4baa4634d678b448
6
+ metadata.gz: edb330105098a15cb10bb0edaaca0131c1f339568c5639d2bc75b02adfaf1a4e0b94176e663e45784e9fb0d978732c854a680b937d135205bcb88c943c02c8b0
7
+ data.tar.gz: 2dff67556aab12d5ad4a9a72239ffa34982804cfa311970a42bf35af33ad1e848baf94f82d74e9e65f21724019963b016c05823fa7e1ec40e01f7b511c1824fd
data/CHANGES.md CHANGED
@@ -1,5 +1,84 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-10-08 v0.0.130
4
+
5
+ * Replace `ask?` with `confirm?` in `rag_handling.rb` for the `[v]iew` /
6
+ `[c]lear` prompts in `#clear_collection_tags` and
7
+ `#clear_collection_sources` to bypass `Reline` and keep command history
8
+ clean.
9
+ * Add `use_pager(force: true)` in the `#clear_collection_sources` view branch
10
+ to fix display.
11
+ * Rewrite `confirm?` YARD documentation in `dialog.rb` to clarify the
12
+ two-branch return contract (`yes: nil` → raw char, `yes:` matcher → matched
13
+ char or `nil`) and history-pollution rationale.
14
+ * Swap 7 `ask?` → `confirm?` stubs in `rag_handling_spec.rb`.
15
+ * Add `line_numbers: true` to the `read_file` tool block in
16
+ `default_config.yml`.
17
+ * Update `read_file.rb` to fall back to `tool_config.line_numbers?` when the
18
+ model omits the argument and interpolate the live default into the tool
19
+ description.
20
+ * Fix typo in description: `linenumbers` → `line numbers`.
21
+ * Update specs to extract `let :tool`, adjust `nil`-arg expectations for the
22
+ `1: ` prefix, checksum, and `line_count`, and add a new spec asserting raw
23
+ content when `tool_config.line_numbers` is stubbed to `false`.
24
+
25
+ ## 2026-10-08 v0.0.129
26
+
27
+ ### Features
28
+
29
+ * **`get_url`**: Added support for the `file` scheme and updated the tool
30
+ description to display live allowed schemes.
31
+ * **`get_url`**: Implemented extraction of character card metadata from PNG
32
+ images when `sub_type` is `'png'`.
33
+ * **`patch_file`**: Enabled deletion of line ranges by passing `text: null`.
34
+ Omitting the key now raises an error, while an explicit `nil` value deletes
35
+ the range.
36
+ * **`update_collection`**: Prunes stale sources from the vector store when
37
+ collection patterns are shrunk, ensuring pattern edits propagate cleanly.
38
+ * **`/input`**: Clarified help text to distinguish between smart import
39
+ (content-type detection, HTML→MD, audio→ASR) and raw file reading.
40
+ * **`/conversation clean`**: Expanded help text to list cleanable categories
41
+ (`tools`, `images`, `thinking`, `messages`, `history`, `links`).
42
+
43
+ ### Fixes
44
+
45
+ * **`execute_grep`**: Replaced `it` with `_1` in the grep command template to
46
+ fix a Ruby **3.3** deprecation warning regarding the implicit block
47
+ parameter in **3.4**.
48
+ * **`less`/`more` fallback**: Split the combined fallback logic so that
49
+ `less` receives the `-r` flag for raw control characters, while `more`
50
+ remains bare, fixing compatibility with GNU `more` on Debian trixie.
51
+ * **`get_url`**: Fixed `URI.parse` errors for URLs containing spaces by
52
+ encoding them as `%20`.
53
+ * **Web searching prompts**: Corrected swapped prompt references to ensure
54
+ `prompt(:web_summarize)` is used for the 'summarizing' policy and
55
+ `prompt(:web_import)` for the import mode.
56
+ * **`source_fetching`**: Moved the `prompt(:embed)` call earlier to ensure it
57
+ is available for both concurrent and non-concurrent execution paths.
58
+
59
+ ### Refactoring
60
+
61
+ * **Tools**: Renamed `directory_structure` to `list_directory` (class
62
+ `DirectoryStructure` → `ListDirectory`).
63
+ * **Tools**: Renamed `gem_path_lookup` to `lookup_gem_path` (class
64
+ `GemPathLookup` → `LookupGemPath`) for verb-first naming consistency.
65
+ * **Tools**: Removed the `file_context` tool, as bulk file context is now
66
+ handled by `/input context` (ContextSpook).
67
+ * **`get_url`**: Reformatted description text for improved readability.
68
+
69
+ ### Dependencies
70
+
71
+ * Bumped the minimum version of the `tins` dependency to **1.60.1**.
72
+
73
+ ### Testing
74
+
75
+ * Stubbed `Tins::Terminal.columns` and `Tins::Terminal.lines` in
76
+ `spec/spec_helper.rb`.
77
+ * Added specs for PNG character card extraction and updated image spec
78
+ doubles to include `sub_type: 'jpeg'`.
79
+ * Split `patch_file` specs to distinguish between omitted keys (raises) and
80
+ explicit `nil` (deletes).
81
+
3
82
  ## 2026-10-07 v0.0.128
4
83
 
5
84
  ### Features
data/README.md CHANGED
@@ -524,18 +524,18 @@ context, manipulate files, and retrieve external information.
524
524
 
525
525
  | Category | Tools | Description |
526
526
  | :--- | :--- | :--- |
527
- | **Filesystem** | `read_file`, `write_file`, `patch_file`, `delete_file`, `move_file`, `directory_structure`, `execute_grep`, `execute_shell` | Read, write, and search files within allowed directories; run shell commands as a last resort. |
528
- | **Ruby/Dev** | `resolve_tag`, `execute_ri`, `gem_path_lookup`, `run_tests`, `eval_ruby` | Introspect Ruby code, check documentation, and run test suites. |
527
+ | **Filesystem** | `read_file`, `write_file`, `patch_file`, `delete_file`, `move_file`, `list_directory`, `execute_grep`, `execute_shell` | Read, write, and search files within allowed directories; run shell commands as a last resort. |
528
+ | **Ruby/Dev** | `resolve_tag`, `execute_ri`, `lookup_gem_path`, `run_tests`, `eval_ruby` | Introspect Ruby code, check documentation, and run test suites. |
529
529
  | **Web/External** | `search_web`, `get_url`, `browse`, `get_rfc`, `get_cve`, `get_endoflife`, `get_ghr`, `get_jira_issue`, `execute_jira_twg` | Access the internet, fetch specific URLs, and look up technical standards; run Jira CLI queries via `twg`. |
530
530
  | **System/Util** | `get_time`, `get_location`, `get_current_weather`, `generate_password`, `compute_bmi`, `roll_dice` | General utility functions for time, location, and simple calculations. |
531
531
  | **Editor/Clip** | `copy_to_clipboard`, `paste_from_clipboard`, `paste_into_editor`, `open_file_in_editor` | Bridge the gap between the chat and the system clipboard or editor. |
532
- | **Knowledge** | `search_knowledge`, `file_context`, `lookup_group` | Semantic search for specific snippets, broad retrieval of structured project context, or retrieving prior message groups by UUID. |
532
+ | **Knowledge** | `search_knowledge`, `lookup_group` | Semantic search for specific snippets, or retrieving prior message groups by UUID. |
533
533
  | **Multimodal** | `generate_image` | Generate images via a local ComfyUI server. |
534
534
 
535
- ***Note on Knowledge Tools**: Use `search_knowledge` for precise,
536
- low-token semantic discovery and `file_context` for a comprehensive view of
537
- modules or patterns. Be cautious with broad patterns in `file_context`, as
538
- importing too many files can exceed the LLM's context window.*
535
+ ***Note on Knowledge Tools**: Use `search_knowledge` for low-token
536
+ semantic discovery. For comprehensive project context, use the
537
+ `/input context` command instead of loading files into the tool
538
+ call context window.*
539
539
 
540
540
  ## External Dependencies
541
541
 
data/Rakefile CHANGED
@@ -49,7 +49,7 @@ GemHadar do
49
49
  dependency 'reverse_markdown', '~> 3.0'
50
50
  dependency 'kramdown-ansi', '~> 0.5'
51
51
  dependency 'complex_config', '~> 0.22', '>= 0.22.2'
52
- dependency 'tins', '~> 1.60'
52
+ dependency 'tins', '~> 1.60', '>= 1.60.1'
53
53
  dependency 'search_ui', '>= 0.2'
54
54
  dependency 'amatch', '~> 0.4'
55
55
  dependency 'pdf-reader', '~> 2.0'
@@ -380,6 +380,12 @@ module OllamaChat::Commands
380
380
  💾 Manage conversation content:
381
381
  - save/load: Export/import as .json or .jsonl
382
382
  - clean: Interactively clean conversation content
383
+ - tools: tool call content
384
+ - images: added images
385
+ - thinking: reasoning content
386
+ - messages: all messages ⇒ tools, images, thinking
387
+ - history: command history
388
+ - links: remembered URLs
383
389
  - compact: Summarize old messages, keep recent
384
390
  - compact summary: Show last compaction summary
385
391
  - summarize: Per-message narrative (-s sentence)
@@ -867,7 +873,10 @@ module OllamaChat::Commands
867
873
  EOT
868
874
  help: <<~EOT
869
875
  📥 Import content (read, summarize, embed, context)
870
- Subcommands: path, context, embedding, summary
876
+ Subcommands: path, context, embedding, summary
877
+ (no subcommand) → smart import (HTML→MD, audio→ASR,
878
+ image→context, PNG char cards)
879
+ path → raw file read (no parsing)
871
880
  Options: -p (pattern), -w [words], -a (all),
872
881
  -c [collection], -t [tags], -e (edit),
873
882
  -m (monochrome), -i (summary instruction),
@@ -29,21 +29,37 @@ module OllamaChat::Dialog
29
29
  prefill and Reline.pre_input_hook = old_pre_input_hook
30
30
  end
31
31
 
32
- # The confirm? method displays a prompt and reads a single character input
33
- # from the user in raw mode, then returns that character. This is best used
34
- # for confirmation prompts.
32
+ # The confirm? method displays a prompt and reads a **single keypress**
33
+ # from the user in raw mode (no Enter required), returning that character.
34
+ # Unlike {#ask?}, it does not go through Reline, so it never pollutes the
35
+ # command history — making it the right tool for confirmation gates *and*
36
+ # terse single-key selections such as `[v]iew` / `[c]lear` menus.
37
+ #
38
+ # The returned value depends on whether a positive-response matcher (`yes`)
39
+ # is supplied:
40
+ #
41
+ # - `yes: nil` (default) — the raw keypress is returned verbatim so the
42
+ # caller can dispatch on it (e.g. `case key; when /\Av/i; ...`); on
43
+ # timeout the `default` value is returned, and on interrupt (Ctrl-C)
44
+ # `nil` is returned.
45
+ # - `yes: <Regexp/Object>` — the keypress is returned only when it
46
+ # satisfies `yes === keypress` (e.g. `yes: /\Ay/i`); any other keypress,
47
+ # or an interrupt, yields `nil`.
35
48
  #
36
49
  # @param prompt [String] the prompt to display to the user
37
50
  # @param timeout [Integer, nil] optional timeout in seconds; if nil, the
38
- # method blocks until input, if 0 the method immediately returns the default
39
- # value.
51
+ # method blocks until input, if 0 it immediately returns the `default`
52
+ # value without waiting.
40
53
  # @param default [Object, nil] value returned when the timeout expires
41
54
  # (defaults to `nil`)
42
- # @param yes [Object, nil] value that is considered a positive response
55
+ # @param yes [Object, nil] matcher (`#===`) that defines a positive
56
+ # response; when `nil` the raw keypress is returned for the caller to
57
+ # interpret (default: `nil`)
43
58
  # @param output [IO] the IO object to write the prompt and the answer to
44
59
  #
45
- # @return [Object] the character entered by the user, the `default` value
46
- # if a timeout occurs, or `nil` if the read is interrupted (e.g. Ctrl-C)
60
+ # @return [Object, nil] see the dispatch rules above: the keypress (or
61
+ # `default` on timeout / `nil` on interrupt) when `yes:` is nil, otherwise
62
+ # the keypress only if it matches `yes`, else `nil`.
47
63
  def confirm?(prompt:, timeout: nil, default: nil, yes: nil, output: STDOUT)
48
64
  return default if timeout&.zero?
49
65
  if prompt.include?('%s')
@@ -41,10 +41,10 @@ module OC
41
41
  description 'Pager command to use in case terminal lines are exceeded by output'
42
42
 
43
43
  default do
44
- if fallback_pager = `which 2>/dev/null less`.full?(:chomp) ||
45
- `which 2>/dev/null more`.full?(:chomp)
46
- then
44
+ if fallback_pager = `which 2>/dev/null less`.full?(:chomp)
47
45
  fallback_pager << ' -r'
46
+ elsif fallback_pager = `which 2>/dev/null more`.full?(:chomp)
47
+ fallback_pager
48
48
  end
49
49
  end
50
50
  end
@@ -584,13 +584,7 @@ tools:
584
584
  get_location:
585
585
  result_display_timeout: 3
586
586
  default: true
587
- file_context:
588
- default: false
589
- require_confirmation: false
590
- result_display_timeout: 3
591
- allowed:
592
- - './spec'
593
- directory_structure:
587
+ list_directory:
594
588
  default: true
595
589
  require_confirmation: false
596
590
  result_display_timeout: 3
@@ -601,7 +595,7 @@ tools:
601
595
  default: true
602
596
  result_display_timeout: 3
603
597
  cmd: |
604
- 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}
598
+ grep #{'-i' if ignore_case} -m #{max_results} -r #{before.full? { "-B %u " % _1 }}#{after.full? { "-A %u " % _1 }}#{context.full? { "-C %u " % _1 }}#{pattern} #{path}
605
599
  execute_shell:
606
600
  default: false
607
601
  require_confirmation: false # Preflight confirm is skipped, but in-tool it's mandatory.
@@ -629,6 +623,7 @@ tools:
629
623
  default: true
630
624
  require_confirmation: false
631
625
  result_display_timeout: 3
626
+ line_numbers: true
632
627
  allowed:
633
628
  - './tmp'
634
629
  - './lib'
@@ -645,7 +640,8 @@ tools:
645
640
  schemes:
646
641
  - http
647
642
  - https
648
- gem_path_lookup:
643
+ - file
644
+ lookup_gem_path:
649
645
  result_display_timeout: 3
650
646
  default: true
651
647
  lookup_group:
@@ -248,7 +248,7 @@ module OllamaChat::RAGHandling
248
248
  label = source ? "#{source} #{snippet}" : snippet
249
249
  feedback(label, type: :info)
250
250
  view_tag_records(tag, [record])
251
- ask?(prompt: " [c]lear / other to go back: ") =~ /\Ac/i or next
251
+ confirm?(prompt: " [c]lear / other to go back: ") =~ /\Ac/i or next
252
252
  clear_tag_records(tag, source)
253
253
  else
254
254
  group_lines = []
@@ -270,7 +270,7 @@ module OllamaChat::RAGHandling
270
270
  )
271
271
  next if chosen.nil? || chosen == '[back]'
272
272
  src, recs = group_map[chosen]
273
- action = ask?(prompt: " [v]iew / [c]lear / other to go back: ")
273
+ action = confirm?(prompt: " [v]iew / [c]lear / other to go back: ")
274
274
  case action
275
275
  when /\Av/i
276
276
  view_tag_records(tag, recs)
@@ -350,11 +350,11 @@ module OllamaChat::RAGHandling
350
350
  break
351
351
  else
352
352
  source = display_map[chosen]
353
- action = ask?(prompt: " [v]iew / [c]lear / other to go back: ")
353
+ action = confirm?(prompt: " [v]iew / [c]lear / other to go back: ")
354
354
  case action
355
355
  when /\Av/i
356
356
  records = @documents.records(sources: [ source ])
357
- use_pager do |output|
357
+ use_pager(force: true) do |output|
358
358
  output.puts "#{bold{source}} (#{records.size} records)"
359
359
  output.puts
360
360
  records.each do |record|
@@ -547,22 +547,30 @@ module OllamaChat::RAGHandling
547
547
  feedback("Collection #{collection.inspect} not found in database.", type: :warn)
548
548
  return ''
549
549
  end
550
+
551
+ matched_sources = nil
552
+ if patterns = col.patterns.full?
553
+ matched_sources = all_file_set(patterns).map(&:to_s).to_set
554
+ end
555
+
550
556
  sources = {}
551
557
  seen = {}
552
558
  @documents.each_record do |record|
553
559
  source = @documents.normalize_source(record.source) or next
554
- seen.key?(source) and next
555
- seen[source] = true
556
- unless @documents.source_modified?(source)
557
- infobar.puts "Source #{source.to_s.inspect} is unmodified. => Skipping."
558
- next
560
+ if matched_sources.nil? || matched_sources.member?(source)
561
+ seen.key?(source) and next
562
+ seen[source] = true
563
+ unless @documents.source_modified?(source)
564
+ infobar.puts "Source #{source.to_s.inspect} is unmodified. => Skipping."
565
+ next
566
+ end
567
+ sources[source] = record.tags_set
559
568
  end
560
- sources[source] = record.tags_set
561
569
  @documents.source_remove(source)
562
570
  end
563
571
 
564
572
  if patterns = col.patterns.full?
565
- new_sources = all_file_set(patterns).map(&:to_s).reject { seen.key?(_1) }
573
+ new_sources = all_file_set(patterns).map(&:to_s).reject { seen.key?(_1) }.to_set
566
574
  new_sources.each { seen[_1] = true }
567
575
  new_sources.each { sources[_1] = [] }
568
576
  end
@@ -288,12 +288,12 @@ module OllamaChat::SourceFetching
288
288
  # to the tags array to apply to that source
289
289
  # @return [Array<String>] results from each successful embed call
290
290
  def bulk_embed_sources(sources_tags)
291
- return sources_tags.map { |s, tags| embed(s, tags:) }.compact if
291
+ prompt = prompt(:embed)
292
+ return sources_tags.map { |s, tags| embed(s, prompt:, tags:) }.compact if
292
293
  sources_tags.size <= 1 or config.embedding.concurrency <= 1
293
294
 
294
295
  results = []
295
296
  mutex = Mutex.new
296
- prompt = prompt(:embed)
297
297
  Tins::Limited.new(config.embedding.concurrency, name: 'embed').process do |l|
298
298
  sources_tags.each do |s, tags|
299
299
  l.execute do
@@ -38,7 +38,7 @@ class OllamaChat::Tools::ExecuteShell
38
38
  then a mandatory y/n/i confirm prompt gates execution.
39
39
  Last resort: use ONLY when no dedicated tool covers
40
40
  the task (e.g. `git commit`, `bundle install`, `make`).
41
- Prefer `execute_grep`, `directory_structure`, `read_file`,
41
+ Prefer `execute_grep`, `list_directory`, `read_file`,
42
42
  `patch_file` over shell equivalents. Only invoke when
43
43
  the user explicitly requests it or you have proposed
44
44
  the command to the user beforehand. Runs in the current
@@ -22,9 +22,10 @@ class OllamaChat::Tools::GetURL
22
22
  function: Tool::Function.new(
23
23
  name:,
24
24
  description: <<~EOT,
25
- Web fetcher – Downloads any web resource (HTML, Markdown, plain text, or images)
26
- at url and makes its contents available to the model. Good for pulling
27
- documentation snippets or viewing generated images.
25
+ Web fetcher – Downloads any web resource (HTML, Markdown, plain text,
26
+ or images) at url and makes its contents available to the model. Good
27
+ for pulling documentation snippets or viewing generated images.
28
+ Allowed schemes: #{Array(tool_config.schemes?).map(&:to_s).join(', ')}
28
29
  EOT
29
30
  parameters: Tool::Function::Parameters.new(
30
31
  type: 'object',
@@ -46,8 +47,10 @@ class OllamaChat::Tools::GetURL
46
47
  typically transform the source content into a text-based
47
48
  representation
48
49
  (e.g., HTML to Markdown, PDF to text) before processing.
49
- - 'ignoring': Returns the raw content without any transformation (best for raw text, logs, or code).
50
- - 'importing': Processes content (e.g., HTML to Markdown) and adds it to the chat context.
50
+ - 'ignoring': Returns the raw content without any
51
+ transformation (best for raw text, logs, or code).
52
+ - 'importing': Processes content (e.g., HTML to Markdown) and
53
+ adds it to the chat context.
51
54
  - 'embedding': Processes the content for vector storage.
52
55
  - 'summarizing': Returns a condensed summary of the content.
53
56
  EOT
@@ -104,7 +107,7 @@ class OllamaChat::Tools::GetURL
104
107
 
105
108
  allowed_schemes = Array(tool_config.schemes?).map(&:to_s)
106
109
 
107
- url = URI.parse(args.url.to_s)
110
+ url = URI.parse(args.url.to_s.gsub(' ', '%20'))
108
111
  unless allowed_schemes.include?(url.scheme)
109
112
  raise OllamaChat::ToolFunctionArgumentError,
110
113
  "scheme #{url.scheme.inspect} not allowed "\
@@ -120,6 +123,10 @@ class OllamaChat::Tools::GetURL
120
123
  case source_io&.content_type&.media_type
121
124
  when 'image'
122
125
  chat.add_image(chat.images, source_io, source)
126
+ if source_io&.content_type&.sub_type == 'png'
127
+ source_io.rewind
128
+ content = chat.parse_png(source_io).full?(:join, ?\n)
129
+ end
123
130
  when 'text', 'application', nil
124
131
  case document_policy
125
132
  when 'ignoring'
@@ -6,12 +6,12 @@
6
6
  #
7
7
  # The tool supports traversing directories and returns a structured
8
8
  # representation of the file system hierarchy.
9
- class OllamaChat::Tools::DirectoryStructure
9
+ class OllamaChat::Tools::ListDirectory
10
10
  include OllamaChat::Tools::Concern
11
11
  include OllamaChat::Utils::AnalyzeDirectory
12
12
 
13
13
  # @return [String] the registered name for this tool
14
- def self.register_name = 'directory_structure'
14
+ def self.register_name = 'list_directory'
15
15
 
16
16
  # Creates and returns a tool definition for retrieving directory structure.
17
17
  #
@@ -3,11 +3,11 @@
3
3
  # This tool allows the chat client to find the installation paths of gems
4
4
  # on the system. It integrates with the Ollama tool calling system to
5
5
  # provide gem path information to the language model.
6
- class OllamaChat::Tools::GemPathLookup
6
+ class OllamaChat::Tools::LookupGemPath
7
7
  include OllamaChat::Tools::Concern
8
8
 
9
9
  # @return [String] the registered name for this tool
10
- def self.register_name = 'gem_path_lookup'
10
+ def self.register_name = 'lookup_gem_path'
11
11
 
12
12
  # Creates and returns a tool definition for gem path lookup.
13
13
  #
@@ -71,7 +71,8 @@ class OllamaChat::Tools::PatchFile
71
71
  type: 'array',
72
72
  description: <<~EOT,
73
73
  A list of edits. Each edit must contain start_line, end_line,
74
- and text.
74
+ and text. Set `text` to null to delete the line range
75
+ without replacement.
75
76
  EOT
76
77
  items: Tool::Function::Parameters::Property.new(
77
78
  type: 'object',
@@ -86,7 +87,8 @@ class OllamaChat::Tools::PatchFile
86
87
  type: 'integer', description: '1-indexed end line'
87
88
  ),
88
89
  text: Tool::Function::Parameters::Property.new(
89
- type: 'string', description: 'The replacement text'
90
+ type: 'string',
91
+ description: 'The replacement text. Set to null to delete the range.'
90
92
  ),
91
93
  },
92
94
  )
@@ -234,7 +236,7 @@ class OllamaChat::Tools::PatchFile
234
236
  s_idx = edit[:start_line] - 1
235
237
  e_idx = edit[:end_line] - 1
236
238
 
237
- lines[s_idx..e_idx] = [edit[:text]]
239
+ lines[s_idx..e_idx] = edit[:text].nil? ? [] : [edit[:text]]
238
240
  end
239
241
 
240
242
  lines * ?\n
@@ -251,8 +253,8 @@ class OllamaChat::Tools::PatchFile
251
253
  e[:start_line] or raise OllamaChat::ToolFunctionArgumentError,
252
254
  "Edit ##{i + 1} is missing a start_line"
253
255
  e[:end_line] ||= e[:start_line]
254
- e[:text] or raise OllamaChat::ToolFunctionArgumentError,
255
- "Edit ##{i + 1} is missing its substiution text"
256
+ e.key?(:text) or raise OllamaChat::ToolFunctionArgumentError,
257
+ "Edit ##{i + 1} is missing the text key; set it to null to delete"
256
258
  if e[:start_line] < 1 || e[:end_line] > 1 && e[:end_line] > file_size || e[:start_line] > e[:end_line]
257
259
  raise OllamaChat::ToolFunctionArgumentError,
258
260
  "Invalid range for edit ##{i + 1}: lines #{e[:start_line]}-#{e[:end_line]} (File size: #{file_size})"
@@ -28,7 +28,7 @@ class OllamaChat::Tools::ReadFile
28
28
  File reader – Returns raw text from path if it’s within allowed
29
29
  directories. No side effects; useful for inspecting config or source
30
30
  files. You can optionally specify a line range to read. You can also
31
- enable prefixing with linenumbers; this is highly recommended (and
31
+ enable prefixing with line numbers; this is highly recommended (and
32
32
  practically mandatory) before calling `open_file_in_editor` to ensure
33
33
  the line range is precise.
34
34
  EOT
@@ -53,8 +53,8 @@ class OllamaChat::Tools::ReadFile
53
53
  line_numbers: Tool::Function::Parameters::Property.new(
54
54
  type: 'boolean',
55
55
  description: <<~EOT
56
- Whether to prefix each line with its line number,
57
- e.g. "666: The line content…
56
+ Whether to prefix each line with its line number, e.g.
57
+ "666: The line content…" (default: #{!!tool_config.line_numbers?})
58
58
  EOT
59
59
  )
60
60
  },
@@ -77,12 +77,12 @@ class OllamaChat::Tools::ReadFile
77
77
  # @return [String] an error message as a JSON string if the operation fails
78
78
  # @raise [JSON::ParserError] if the result cannot be serialized to JSON
79
79
  def execute(tool_call, **opts)
80
-
81
80
  args = tool_call.function.arguments
82
81
 
83
82
  start_line = args.start_line.full?
84
83
  end_line = args.end_line.full?
85
84
  line_numbers = args.line_numbers
85
+ line_numbers.nil? and line_numbers = !!tool_config.line_numbers?
86
86
 
87
87
  path = assert_valid_path(args.path, tool_config.allowed?, check: :file)
88
88
  full_content = path.read
@@ -90,15 +90,14 @@ require 'ollama_chat/tools/browse'
90
90
  require 'ollama_chat/tools/compute_bmi'
91
91
  require 'ollama_chat/tools/copy_to_clipboard'
92
92
  require 'ollama_chat/tools/delete_file'
93
- require 'ollama_chat/tools/directory_structure'
94
93
  require 'ollama_chat/tools/eval_ruby'
95
94
  require 'ollama_chat/tools/execute_grep'
96
95
  require 'ollama_chat/tools/execute_ri'
97
96
  require 'ollama_chat/tools/execute_shell'
98
97
  require 'ollama_chat/tools/execute_jira_twg'
99
- require 'ollama_chat/tools/file_context'
100
98
  require 'ollama_chat/tools/forget'
101
- require 'ollama_chat/tools/gem_path_lookup'
99
+ require 'ollama_chat/tools/list_directory'
100
+ require 'ollama_chat/tools/lookup_gem_path'
102
101
  require 'ollama_chat/tools/generate_image'
103
102
  require 'ollama_chat/tools/generate_password'
104
103
  require 'ollama_chat/tools/get_current_weather'
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.128'
3
+ VERSION = '0.0.130'
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:
@@ -78,7 +78,7 @@ module OllamaChat::WebSearching
78
78
  end
79
79
  prompt.named_placeholders_interpolate({query:})
80
80
  elsif document_policy.selected == 'summarizing'
81
- prompt = prompt(:web_import).to_s
81
+ prompt = prompt(:web_summarize).to_s
82
82
  results = urls.each_with_object('') do |url, content|
83
83
  summarize(url).full? do |c|
84
84
  content << c.ask_and_send_or_self(:read)
@@ -86,7 +86,7 @@ module OllamaChat::WebSearching
86
86
  end
87
87
  prompt.named_placeholders_interpolate({query:, results:})
88
88
  else
89
- prompt = prompt(:web_summarize).to_s
89
+ prompt = prompt(:web_import).to_s
90
90
  results = urls.each_with_object('') do |url, content|
91
91
  import(url).full? do |c|
92
92
  content << c.ask_and_send_or_self(:read)