ollama_chat 0.0.127 → 0.0.129

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +146 -0
  3. data/README.md +8 -7
  4. data/Rakefile +1 -1
  5. data/lib/ollama_chat/chat.rb +44 -44
  6. data/lib/ollama_chat/collection_search.rb +2 -0
  7. data/lib/ollama_chat/commands.rb +32 -33
  8. data/lib/ollama_chat/conversation.rb +48 -0
  9. data/lib/ollama_chat/dialog.rb +14 -7
  10. data/lib/ollama_chat/information.rb +3 -0
  11. data/lib/ollama_chat/message_list.rb +7 -5
  12. data/lib/ollama_chat/model_handling.rb +14 -13
  13. data/lib/ollama_chat/oc.rb +10 -3
  14. data/lib/ollama_chat/ollama_chat_config/default_config.yml +4 -9
  15. data/lib/ollama_chat/rag_handling.rb +131 -14
  16. data/lib/ollama_chat/source_fetching.rb +3 -3
  17. data/lib/ollama_chat/tools/concern.rb +33 -18
  18. data/lib/ollama_chat/tools/delete_file.rb +2 -2
  19. data/lib/ollama_chat/tools/execute_grep.rb +3 -5
  20. data/lib/ollama_chat/tools/execute_shell.rb +1 -1
  21. data/lib/ollama_chat/tools/forget.rb +2 -2
  22. data/lib/ollama_chat/tools/generate_image.rb +4 -6
  23. data/lib/ollama_chat/tools/get_current_weather.rb +1 -1
  24. data/lib/ollama_chat/tools/get_cve.rb +2 -2
  25. data/lib/ollama_chat/tools/get_endoflife.rb +2 -2
  26. data/lib/ollama_chat/tools/get_rfc.rb +2 -2
  27. data/lib/ollama_chat/tools/get_url.rb +14 -8
  28. data/lib/ollama_chat/tools/{directory_structure.rb → list_directory.rb} +4 -4
  29. data/lib/ollama_chat/tools/{gem_path_lookup.rb → lookup_gem_path.rb} +2 -2
  30. data/lib/ollama_chat/tools/memorize.rb +1 -1
  31. data/lib/ollama_chat/tools/move_file.rb +3 -3
  32. data/lib/ollama_chat/tools/patch_file.rb +14 -7
  33. data/lib/ollama_chat/tools/read_file.rb +2 -2
  34. data/lib/ollama_chat/tools/roll_dice.rb +1 -1
  35. data/lib/ollama_chat/tools/run_tests.rb +3 -5
  36. data/lib/ollama_chat/tools/search_knowledge.rb +5 -3
  37. data/lib/ollama_chat/tools/search_web.rb +1 -2
  38. data/lib/ollama_chat/tools/write_file.rb +2 -2
  39. data/lib/ollama_chat/tools.rb +2 -3
  40. data/lib/ollama_chat/version.rb +1 -1
  41. data/lib/ollama_chat/web_searching.rb +2 -2
  42. data/ollama_chat.gemspec +6 -6
  43. data/spec/ollama_chat/commands_spec.rb +29 -23
  44. data/spec/ollama_chat/conversation_spec.rb +71 -0
  45. data/spec/ollama_chat/model_handling_spec.rb +9 -9
  46. data/spec/ollama_chat/rag_handling_spec.rb +116 -3
  47. data/spec/ollama_chat/tools/concern_spec.rb +1 -1
  48. data/spec/ollama_chat/tools/get_url_spec.rb +22 -4
  49. data/spec/ollama_chat/tools/{directory_structure_spec.rb → list_directory_spec.rb} +6 -6
  50. data/spec/ollama_chat/tools/{gem_path_lookup_spec.rb → lookup_gem_path_spec.rb} +4 -4
  51. data/spec/ollama_chat/tools/memorize_spec.rb +4 -4
  52. data/spec/ollama_chat/tools/patch_file_spec.rb +12 -4
  53. data/spec/ollama_chat/tools/run_tests_spec.rb +3 -3
  54. data/spec/ollama_chat/web_searching_spec.rb +2 -2
  55. data/spec/spec_helper.rb +4 -0
  56. metadata +15 -13
  57. data/lib/ollama_chat/tools/file_context.rb +0 -91
  58. data/spec/ollama_chat/tools/file_context_spec.rb +0 -59
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a72761f0d0b34c0ba21859589410e914dda692d669a39629e4e6bb8f6e2857ea
4
- data.tar.gz: 374fa95c62c5510e94c6a7624200a6193a15e9ed842a4b49b5364d43eeecac52
3
+ metadata.gz: 9aae892b3b152a70e519a4d5a6268f046611c55d5b8ecfda66e2e4386a4681db
4
+ data.tar.gz: '038e498781b238aef6f3d6ff595ec3beb50d00b7efd722f8636bcb87a273bbb2'
5
5
  SHA512:
6
- metadata.gz: ea024b4607101da7037f0234970cb6e655c6d2b1af46fc1eac1b8dc901aebd5ef95a091d079653bfb58e86d381c4bb56173172f9fb0861e9d8a3424667bfdd32
7
- data.tar.gz: dfbbe6cddbb4aac1f047cb39719ed58e8920e22a42775cb9f18a4d3731d0c53cc7c632733241f58f6cd6c132e5979b0a3117bf38e7e0095417310e839fb7421b
6
+ metadata.gz: 740289c0e7fdf453718f120f26fa201f68c1f677777b71e440789df72bb14db52526026114adb06ce15a2ea93b78ce6e39a478bfe77a22c1657692e1a5162445
7
+ data.tar.gz: 1b553c6648636b5088857f199a21cd87b86836c59df746fa50c504569be8609fd0181c3b233dda977a065cefdddfda1cd7ce7640a154a742bef8ab7392513346
data/CHANGES.md CHANGED
@@ -1,5 +1,151 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-10-08 v0.0.129
4
+
5
+ ### Features
6
+
7
+ * **`get_url`**: Added support for the `file` scheme and updated the tool
8
+ description to display live allowed schemes.
9
+ * **`get_url`**: Implemented extraction of character card metadata from PNG
10
+ images when `sub_type` is `'png'`.
11
+ * **`patch_file`**: Enabled deletion of line ranges by passing `text: null`.
12
+ Omitting the key now raises an error, while an explicit `nil` value deletes
13
+ the range.
14
+ * **`update_collection`**: Prunes stale sources from the vector store when
15
+ collection patterns are shrunk, ensuring pattern edits propagate cleanly.
16
+ * **`/input`**: Clarified help text to distinguish between smart import
17
+ (content-type detection, HTML→MD, audio→ASR) and raw file reading.
18
+ * **`/conversation clean`**: Expanded help text to list cleanable categories
19
+ (`tools`, `images`, `thinking`, `messages`, `history`, `links`).
20
+
21
+ ### Fixes
22
+
23
+ * **`execute_grep`**: Replaced `it` with `_1` in the grep command template to
24
+ fix a Ruby **3.3** deprecation warning regarding the implicit block
25
+ parameter in **3.4**.
26
+ * **`less`/`more` fallback**: Split the combined fallback logic so that
27
+ `less` receives the `-r` flag for raw control characters, while `more`
28
+ remains bare, fixing compatibility with GNU `more` on Debian trixie.
29
+ * **`get_url`**: Fixed `URI.parse` errors for URLs containing spaces by
30
+ encoding them as `%20`.
31
+ * **Web searching prompts**: Corrected swapped prompt references to ensure
32
+ `prompt(:web_summarize)` is used for the 'summarizing' policy and
33
+ `prompt(:web_import)` for the import mode.
34
+ * **`source_fetching`**: Moved the `prompt(:embed)` call earlier to ensure it
35
+ is available for both concurrent and non-concurrent execution paths.
36
+
37
+ ### Refactoring
38
+
39
+ * **Tools**: Renamed `directory_structure` to `list_directory` (class
40
+ `DirectoryStructure` → `ListDirectory`).
41
+ * **Tools**: Renamed `gem_path_lookup` to `lookup_gem_path` (class
42
+ `GemPathLookup` → `LookupGemPath`) for verb-first naming consistency.
43
+ * **Tools**: Removed the `file_context` tool, as bulk file context is now
44
+ handled by `/input context` (ContextSpook).
45
+ * **`get_url`**: Reformatted description text for improved readability.
46
+
47
+ ### Dependencies
48
+
49
+ * Bumped the minimum version of the `tins` dependency to **1.60.1**.
50
+
51
+ ### Testing
52
+
53
+ * Stubbed `Tins::Terminal.columns` and `Tins::Terminal.lines` in
54
+ `spec/spec_helper.rb`.
55
+ * Added specs for PNG character card extraction and updated image spec
56
+ doubles to include `sub_type: 'jpeg'`.
57
+ * Split `patch_file` specs to distinguish between omitted keys (raises) and
58
+ explicit `nil` (deletes).
59
+
60
+ ## 2026-10-07 v0.0.128
61
+
62
+ ### Features
63
+
64
+ * Migrate `/clear` to `/conversation clean` chooser:
65
+ * Removed `clean` method from `chat.rb` and the `/clear` command from
66
+ `commands.rb`.
67
+ * Added `conversation_clean` to `conversation.rb` with an accumulating
68
+ `choose_with_state` chooser (options: `tools`, `images`, `thinking`,
69
+ `messages`, `history`, `links`), a `confirm?` gate, and per-field
70
+ dispatch.
71
+ * Added `what:` keyword argument to `clean_messages` and
72
+ `clean_messages!` in `message_list.rb` supporting `:tools`, `:images`,
73
+ and `:thinking` selection.
74
+ * Updated `/conversation clean` command handler to delegate to
75
+ `conversation_clean`.
76
+ * Add `OLLAMA_EMBEDDING_URL` for dedicated embedding host:
77
+ * Add `OC::OLLAMA::EMBEDDING_URL` const_conf setting (optional,
78
+ `sensitive true`, decoded to `URI`, scheme-checked).
79
+ * Add `connect_embedding_ollama` + public `embedding_ollama` accessor in
80
+ `chat.rb`; fallback to primary chat client when unset.
81
+ * Propagate `ollama:` kwarg through `model_present?`,
82
+ `pull_model_from_remote`, `pull_model_unless_present`, `prepare_model`,
83
+ `use_model` in `model_handling.rb`.
84
+ * Refactor `connect_message` to keyword-arg signature (`base_url:`,
85
+ `prefix:`) + new `connect_message_done` in `dialog.rb`; remove old
86
+ positional-arg version.
87
+ * Remove `ensure connect_message` from `choose_model`.
88
+ * `/reconnect` now calls both `connect_ollama` +
89
+ `connect_embedding_ollama`; `info_rag` shows embedding URL.
90
+ * Fix `source_fetching.rb` Semantic splitter to route chunking
91
+ calls to `embedding_ollama` instead of the primary chat client.
92
+ * Add `url` + `model` to log payloads in `collection_search.rb` and
93
+ `search_knowledge.rb`.
94
+ * Update `README.md` with `OLLAMA_EMBEDDING_URL` entry.
95
+ * Add `/memory dump` and `/memory restore` command:
96
+ * Add `/memory` command in `commands.rb` routing `dump` and `restore`
97
+ subcommands with an optional trailing `.jsonl` path.
98
+ * Add `memory_dump` in `rag_handling.rb` with accumulating multi-select
99
+ chooser (`[ALL]`/`[DONE]`) writing JSONL via `JSONJSONLIO`.
100
+ * Add `memory_restore` in `rag_handling.rb` grouping records by
101
+ `collection` field and re-embedding with original tags and
102
+ `source` association.
103
+ * Extend `create_memory_collection` to accept either a bare persona stem
104
+ or a full `memory-*` collection name via `start_with?` guard.
105
+ * Update `create_memory_collection` YARD prose to reflect dual-input
106
+ behavior.
107
+ * Swap `miyu_pairing` → `personal_assistant` in `forget.rb`,
108
+ `memorize.rb`, and `memorize_spec.rb` to decouple docs from active
109
+ persona.
110
+
111
+ ### Refactoring
112
+
113
+ * Refactor all tools to use `tool_config`:
114
+ * Replace 20 `config.tools.functions.<name>` call sites across 14 tool
115
+ files with the `tool_config` accessor from `Tools::Concern`.
116
+ * Remove 12 dead `config = chat.config` locals that existed solely to
117
+ reach the tool's own config.
118
+ * Drop `config` parameter from `eval_template` in `execute_grep.rb`,
119
+ `poll_for_image` in `generate_image.rb`, and `check_path` in
120
+ `run_tests.rb`.
121
+ * Move `tool_config` and `allowed_paths` below `private` in `concern.rb`;
122
+ add YARD documentation to `tool_config`.
123
+
124
+ ### Documentation
125
+
126
+ * Document automatic syntax checking in `patch_file` description:
127
+ * Added a `SYNTAX CHECK` note to the `OllamaChat::Tools::PatchFile`
128
+ description, informing users that the tool automatically runs
129
+ language-appropriate checks (e.g. `ruby -wc` for `.rb` files) and
130
+ reports errors in the result message.
131
+
132
+ ### Tests
133
+
134
+ * Removed `/clear` describe block from `commands_spec.rb`; replaced
135
+ `/conversation clean` specs with delegation test.
136
+ * Added 6 unit examples for `#conversation_clean` in `conversation_spec.rb`
137
+ covering cancel, deny, field-only, messages+fields, links-only, and
138
+ history-only paths.
139
+ * Fix `model_handling_spec.rb` call sites for new `ollama:` kwarg.
140
+ * Stub `connect_message_done` in `spec_helper.rb`.
141
+ * Add 5 routing specs in `commands_spec.rb` for `/memory` (with-path,
142
+ without-path, spaces-in-path).
143
+ * Add 7 specs in `rag_handling_spec.rb` for `create_memory_collection`,
144
+ `memory_dump`, and `memory_restore`.
145
+ * Update 3 `check_path` mocks in `run_tests_spec.rb` to match the new
146
+ single-argument signature; use `.expose` in `concern_spec.rb` for private
147
+ method access.
148
+
3
149
  ## 2026-10-06 v0.0.127
4
150
 
5
151
  ## Changes
data/README.md CHANGED
@@ -61,6 +61,7 @@ The following environment variables can be used to configure behavior:
61
61
  #### Ollama Core
62
62
  - `OLLAMA_URL` - Base URL for Ollama server (default: `http://localhost:11434`)
63
63
  - `OLLAMA_HOST` - Base hostname for Ollama server (default: `localhost:11434`)
64
+ - `OLLAMA_EMBEDDING_URL` - Optional base URL for a dedicated Ollama server used exclusively for embedding operations. When set, the embedding model runs on this host while the chat model stays on `OLLAMA_URL`. Falls back to `OLLAMA_URL` when unset.
64
65
  - `OLLAMA_SEARXNG_URL` - SearxNG search endpoint URL
65
66
  - `OLLAMA_CHAT_TTS_URL` - Base URL for the [audio.cpp](https://github.com/0xshug0/audio.cpp) TTS server (default: `http://localhost:8880`)
66
67
 
@@ -523,18 +524,18 @@ context, manipulate files, and retrieve external information.
523
524
 
524
525
  | Category | Tools | Description |
525
526
  | :--- | :--- | :--- |
526
- | **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. |
527
- | **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. |
528
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`. |
529
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. |
530
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. |
531
- | **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. |
532
533
  | **Multimodal** | `generate_image` | Generate images via a local ComfyUI server. |
533
534
 
534
- ***Note on Knowledge Tools**: Use `search_knowledge` for precise,
535
- low-token semantic discovery and `file_context` for a comprehensive view of
536
- modules or patterns. Be cautious with broad patterns in `file_context`, as
537
- 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.*
538
539
 
539
540
  ## External Dependencies
540
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'
@@ -2,6 +2,7 @@ require 'tins'
2
2
  require 'tins/xt/string_version'
3
3
  require 'tins/xt/full'
4
4
  require 'json'
5
+ require 'set'
5
6
  require 'term/ansicolor'
6
7
  require 'reline'
7
8
  require 'reverse_markdown'
@@ -116,6 +117,7 @@ class OllamaChat::Chat
116
117
  setup_session
117
118
  setup_state_selectors(config)
118
119
  connect_ollama
120
+ connect_embedding_ollama
119
121
  @documents = setup_documents
120
122
  models::Collection.sync(self)
121
123
  @cache = setup_cache
@@ -321,6 +323,16 @@ class OllamaChat::Chat
321
323
  voice_handler.new(chat: self, voice: current_voice).speak(text, background:)
322
324
  end
323
325
 
326
+ # Returns the Ollama client to use for embedding operations.
327
+ #
328
+ # Falls back to the primary chat client when no dedicated embedding
329
+ # URL has been configured.
330
+ #
331
+ # @return [Ollama::Client] the embedding or chat Ollama client
332
+ def embedding_ollama
333
+ @embedding_ollama || ollama
334
+ end
335
+
324
336
  # Returns a human-readable string representation of the Chat object,
325
337
  # including the class name and the base URL.
326
338
  #
@@ -427,47 +439,6 @@ class OllamaChat::Chat
427
439
  content
428
440
  end
429
441
 
430
- # The clean method clears various parts of the chat session based on the
431
- # specified parameter.
432
- #
433
- # @param what [ String, nil ] the type of data to clear, defaults to
434
- # 'messages' if nil
435
- def clean(what)
436
- persona_profile = nil
437
- case what
438
- when 'messages', nil
439
- messages.clear
440
- feedback("Cleared messages.", type: :info)
441
- when 'links'
442
- links.clear
443
- feedback("Cleared links.", type: :info)
444
- when 'history'
445
- clear_history
446
- feedback("Cleared history.", type: :info)
447
- when 'tags'
448
- @documents.clear
449
- feedback("Cleared all tags.", type: :info)
450
- when 'images'
451
- messages.clear_images
452
- feedback("Cleared all images.", type: :info)
453
- when 'all'
454
- if confirm?(
455
- prompt: '🔔 Are you sure to clear messages and collection? (y/n) ',
456
- yes: /\Ay/i
457
- )
458
- then
459
- messages.clear
460
- @documents.clear
461
- links.clear
462
- clear_history
463
- feedback("Cleared messages and collection #{bold{collection}}.", type: :info)
464
- else
465
- feedback("Denied.", type: :denied)
466
- end
467
- end
468
- persona_profile
469
- end
470
-
471
442
  # The interact_with_user method manages the interactive loop for user input
472
443
  # and chat processing.
473
444
  # It handles reading user input, processing commands, managing messages, and
@@ -646,12 +617,13 @@ class OllamaChat::Chat
646
617
  # @raise [RuntimeError] if the connected Ollama server API version is less
647
618
  # than 0.9.0
648
619
  def connect_ollama
620
+ connect_message(base_url:)
649
621
  @server_version = nil
650
622
  @ollama = Ollama::Client.new(
651
623
  connect_timeout: config.timeouts.connect_timeout?,
652
624
  read_timeout: config.timeouts.read_timeout?,
653
625
  write_timeout: config.timeouts.write_timeout?,
654
- base_url: base_url,
626
+ base_url: ,
655
627
  debug: ,
656
628
  user_agent:
657
629
  )
@@ -659,6 +631,7 @@ class OllamaChat::Chat
659
631
  raise 'require ollama API version 0.9.0 or higher'
660
632
  end
661
633
  log(:info, "Connection established", data: { base_url: })
634
+ connect_message_done
662
635
  @ollama
663
636
  end
664
637
 
@@ -673,10 +646,10 @@ class OllamaChat::Chat
673
646
  if embedding.on?
674
647
  @embedding_model = config.embedding.model.name
675
648
  @embedding_model_options = Ollama::Options[config.embedding.model.options]
676
- pull_model_unless_present(@embedding_model)
649
+ pull_model_unless_present(@embedding_model, ollama: embedding_ollama)
677
650
  collection = initial_collection
678
651
  @documents = Documentrix::Documents.new(
679
- ollama:,
652
+ ollama: embedding_ollama,
680
653
  model: @embedding_model,
681
654
  model_options: config.embedding.model.options,
682
655
  embedding_length: config.embedding.model.embedding_length,
@@ -691,6 +664,33 @@ class OllamaChat::Chat
691
664
  end
692
665
  end
693
666
 
667
+ # Establishes a dedicated Ollama connection for embedding operations.
668
+ #
669
+ # When OC::OLLAMA::EMBEDDING_URL is configured, creates a separate
670
+ # Ollama::Client targeting that host so the embedding model can run
671
+ # on a different machine (e.g. a GPU box running audio.cpp alongside
672
+ # the embedding model) while the chat model stays on the primary
673
+ # Ollama server.
674
+ #
675
+ # @return [Ollama::Client, nil] the embedding client, or nil when no
676
+ # dedicated embedding URL is configured
677
+ def connect_embedding_ollama
678
+ if base_url = OC::OLLAMA::EMBEDDING_URL?
679
+ connect_message(base_url:, prefix: 'embedding ')
680
+ @embedding_ollama = Ollama::Client.new(
681
+ connect_timeout: config.timeouts.connect_timeout?,
682
+ read_timeout: config.timeouts.read_timeout?,
683
+ write_timeout: config.timeouts.write_timeout?,
684
+ base_url: ,
685
+ debug: ,
686
+ user_agent:
687
+ )
688
+ log(:info, "Embedding connection established", data: { base_url: })
689
+ connect_message_done
690
+ @embedding_ollama
691
+ end
692
+ end
693
+
694
694
  # Adds documents from command line arguments to the document collection.
695
695
  #
696
696
  # Processes a list of document paths or URLs, handling both local files and
@@ -31,6 +31,7 @@ module OllamaChat::CollectionSearch
31
31
  log(
32
32
  :info, 'Embedding search request',
33
33
  data: {
34
+ url: embedding_ollama.base_url,
34
35
  model: config.embedding.model.to_h,
35
36
  collection: collection,
36
37
  query: effective_query,
@@ -48,6 +49,7 @@ module OllamaChat::CollectionSearch
48
49
  log(
49
50
  :info, 'Embedding search response',
50
51
  data: {
52
+ url: embedding_ollama.base_url,
51
53
  collection: collection,
52
54
  query: effective_query,
53
55
  result_count: records.size,
@@ -324,24 +324,6 @@ module OllamaChat::Commands
324
324
  :next
325
325
  end
326
326
 
327
- command(
328
- name: :clear,
329
- regexp: %r(^/clear(?:\s+(messages|images|links|history|tags|all))?$),
330
- complete: [ 'clear', %w[ messages images links history tags all ] ],
331
- optional: true,
332
- help: <<~EOT
333
- 🧹 Clear chat state (messages, images, links,
334
- history, tags, all)
335
- EOT
336
- ) do |subcommand|
337
- if result = clean(subcommand)
338
- disable_content_parsing
339
- result
340
- else
341
- :next
342
- end
343
- end
344
-
345
327
  command(
346
328
  name: :links,
347
329
  regexp: %r(^/links(?:\s+(clear))?$),
@@ -397,7 +379,13 @@ module OllamaChat::Commands
397
379
  help: <<~EOT
398
380
  💾 Manage conversation content:
399
381
  - save/load: Export/import as .json or .jsonl
400
- - clean: Remove tool content, images, thinking
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
401
389
  - compact: Summarize old messages, keep recent
402
390
  - compact summary: Show last compaction summary
403
391
  - summarize: Per-message narrative (-s sentence)
@@ -416,17 +404,7 @@ module OllamaChat::Commands
416
404
  load_conversation(path)
417
405
  repair_group_uuids
418
406
  when 'clean'
419
- if confirm?(
420
- prompt: '🔔 Clean tool content, images, and thinking from conversation? (y/n) ',
421
- yes: /\Ay/i
422
- )
423
- then
424
- messages.clean_messages!
425
- session_sync
426
- feedback("Conversation cleaned.", type: :info)
427
- else
428
- feedback("Denied.", type: :denied)
429
- end
407
+ conversation_clean
430
408
  when 'compact summary'
431
409
  show_compaction_summary
432
410
  when 'compact'
@@ -699,6 +677,25 @@ module OllamaChat::Commands
699
677
  :next
700
678
  end
701
679
 
680
+ command(
681
+ name: :memory,
682
+ regexp: %r{^/memory(?:\s+(dump|restore))(?:\s+([^-].*\.jsonl?))?$},
683
+ complete: [ 'memory', %w[ dump restore ] ],
684
+ options: '[FILENAME]',
685
+ help: <<~EOT
686
+ 💾 Manage persona memory (dump/restore)
687
+ optional path must end in .json or .jsonl
688
+ EOT
689
+ ) do |subcommand, path|
690
+ case subcommand
691
+ when 'dump'
692
+ memory_dump(path)
693
+ when 'restore'
694
+ memory_restore(path)
695
+ end
696
+ :next
697
+ end
698
+
702
699
  category :Persona
703
700
 
704
701
  command(
@@ -876,7 +873,10 @@ module OllamaChat::Commands
876
873
  EOT
877
874
  help: <<~EOT
878
875
  📥 Import content (read, summarize, embed, context)
879
- 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)
880
880
  Options: -p (pattern), -w [words], -a (all),
881
881
  -c [collection], -t [tags], -e (edit),
882
882
  -m (monochrome), -i (summary instruction),
@@ -1042,9 +1042,8 @@ module OllamaChat::Commands
1042
1042
  🔌 Reconnect to Ollama server
1043
1043
  EOT
1044
1044
  ) do
1045
- feedback green { "Reconnecting to ollama #{base_url.to_s.inspect}…" }, type: :info
1046
1045
  connect_ollama
1047
- feedback green { "Done." }, type: :success
1046
+ connect_embedding_ollama
1048
1047
  :next
1049
1048
  end
1050
1049
 
@@ -63,4 +63,52 @@ module OllamaChat::Conversation
63
63
  "#{filename.to_s.inspect} failed.", type: :warn)
64
64
  end
65
65
  end
66
+
67
+ # Selectively cleans parts of the current conversation.
68
+ #
69
+ # Presents an accumulating chooser of cleanable targets:
70
+ # tool content, images, thinking, messages, history, links.
71
+ # The user picks one or more (or [ALL]), confirms, and the
72
+ # selected items are cleared.
73
+ def conversation_clean
74
+ options = %w[ tools images thinking messages history links ]
75
+
76
+ selected = Set.new
77
+ choose_with_state do
78
+ loop do
79
+ remaining = options - selected.to_a
80
+ entries = (remaining.empty? ? [] : ['[ALL]'] + remaining) + ['[DONE]']
81
+ choice = choose_entry(entries, prompt: 'What to clean from conversation? %s')
82
+ case choice
83
+ when nil, '[DONE]'
84
+ break
85
+ when '[ALL]'
86
+ selected.merge(remaining)
87
+ break
88
+ else
89
+ selected.add(choice)
90
+ end
91
+ end
92
+ end
93
+
94
+ return feedback('Cancelled, nothing selected.', type: :cancel) if selected.empty?
95
+
96
+ what = selected.map { |s| bold{s} }.to_a
97
+
98
+ unless confirm?(
99
+ prompt: "🔔 Clean #{what * ', '} from conversation? (y/n) ",
100
+ yes: /\Ay/i
101
+ )
102
+ return feedback('Denied.', type: :denied)
103
+ end
104
+
105
+ field_options = %w[ tools images thinking ].select { selected.include?(_1) }
106
+ messages.clear if selected.include?('messages')
107
+ messages.clean_messages!(what: field_options.map(&:to_sym)) unless field_options.empty?
108
+ clear_history if selected.include?('history')
109
+ links.clear if selected.include?('links')
110
+
111
+ session_sync
112
+ feedback("Cleaned #{what * ', '} from conversation.", type: :info)
113
+ end
66
114
  end
@@ -118,14 +118,21 @@ module OllamaChat::Dialog
118
118
  files
119
119
  end
120
120
 
121
- # The connect_message method displays a connection status message.
121
+ # Displays an info-level feedback message indicating that a connection
122
+ # to an Ollama server is being established.
122
123
  #
123
- # @param model [String] the model name to connect to
124
- # @param base_url [String] the base URL of the connection
125
- def connect_message(model, base_url)
126
- msg = "Connecting to #{model}@#{base_url} now…"
127
- log(:info, msg, data: { model:, base_url: })
128
- feedback green { msg }, type: :info
124
+ # @param base_url [URI, String] the target Ollama server URL
125
+ # @param prefix [String] an optional label prepended to "ollama" to
126
+ # distinguish the connection type, e.g. `"embedding "` for a dedicated
127
+ # embedding host (default: `""`)
128
+ def connect_message(base_url:, prefix: '')
129
+ feedback green { "Connecting to #{prefix}ollama #{base_url.to_s.inspect}…" }, type: :info
130
+ end
131
+
132
+ # Displays a success-level feedback message confirming that a
133
+ # connection was established. Counterpart to {#connect_message}.
134
+ def connect_message_done
135
+ feedback green { "Done." }, type: :success
129
136
  end
130
137
 
131
138
  # The change_voice method allows the user to select a voice from a list of
@@ -191,6 +191,9 @@ module OllamaChat::Information
191
191
  # @param output [IO] the output stream to write the information to, defaults to STDOUT
192
192
  def info_rag(output: STDOUT)
193
193
  if embedding.on?
194
+ if base_url = OC::OLLAMA::EMBEDDING_URL?
195
+ output.puts "🔌 Connected to embedding ollama server on: #{base_url.to_s.inspect}"
196
+ end
194
197
  output.puts "🗄️ Current RAG model is #{bold{@embedding_model}}"
195
198
  if @embedding_model_options.present?
196
199
  output.puts " Options: #{JSON.pretty_generate(@embedding_model_options).gsub(/(?<!\A)^/, ' ')}"
@@ -407,11 +407,13 @@ class OllamaChat::MessageList
407
407
  # @param messages [Array<OllamaChat::Message>] the list of messages to clean
408
408
  # @return [Array<OllamaChat::Message>] a new array containing duplicated
409
409
  # messages with stripped content
410
- def clean_messages(messages: @messages)
410
+ def clean_messages(messages: @messages, what: %i[ tools images ])
411
+ what = Array(what).map(&:to_sym)
411
412
  messages.map do |message|
412
413
  message = message.dup
413
- message.content = '' if message.tool?
414
- message.images = nil
414
+ message.content = '' if what.include?(:tools) && message.tool?
415
+ message.images = nil if what.include?(:images)
416
+ message.thinking = nil if what.include?(:thinking)
415
417
  message
416
418
  end
417
419
  end
@@ -422,8 +424,8 @@ class OllamaChat::MessageList
422
424
  # @param messages [Array<OllamaChat::Message>] the messages to clean.
423
425
  # Defaults to all current messages.
424
426
  # @return [OllamaChat::MessageList] self to allow for method chaining.
425
- def clean_messages!(messages: @messages)
426
- @messages = clean_messages(messages:)
427
+ def clean_messages!(messages: @messages, what: %i[ tools images ])
428
+ @messages = clean_messages(messages:, what:)
427
429
  self
428
430
  end
429
431