ollama_chat 0.0.109 → 0.0.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +54 -0
- data/lib/ollama_chat/commands.rb +8 -4
- data/lib/ollama_chat/database/migrations/009_add_app_states_table.rb +11 -0
- data/lib/ollama_chat/database/models/app_state.rb +122 -0
- data/lib/ollama_chat/oc.rb +9 -0
- data/lib/ollama_chat/ollama_chat_config/default_config.yml +0 -1
- data/lib/ollama_chat/prompt_management.rb +124 -0
- data/lib/ollama_chat/tools/patch_file.rb +1 -1
- data/lib/ollama_chat/version.rb +1 -1
- data/lib/ollama_chat/web_searching.rb +4 -3
- data/lib/ollama_chat.rb +20 -2
- data/ollama_chat.gemspec +4 -4
- data/spec/ollama_chat/prompt_management_spec.rb +110 -0
- data/spec/ollama_chat/web_searching_spec.rb +26 -26
- data/spec/spec_helper.rb +1 -0
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 239476f6dca2ca4fca22dc0290b25bb048572cc89d12ef82c09d54a7ee429068
|
|
4
|
+
data.tar.gz: d7c51cf3d519c593666625bcedf487a1d40893099c251f211cd055a4610cb3db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 24eadaa6eb35470ff3908fbfd7646ad0b685bded30694b7784839aef35a447b6f6926c9cac6a29f4eed55d723065cdc063f21d7c718f3c15dc4905892f860484
|
|
7
|
+
data.tar.gz: 98f4ab4370005f5a9523a7fc54ea62f56e64b411894d8ca40ae85518cae9962f8b9818086d5984f34aec392dde268377b10d33ef103e64ebc9b8abcd17702293
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-08-20 v0.0.110
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
* **App State Support**: Introduced `009_add_app_states_table.rb` migration
|
|
8
|
+
and `app_state.rb` model.
|
|
9
|
+
* **Prompt Synchronization**: Added `/prompt sync` subcommand with unified
|
|
10
|
+
diffs and boot check capabilities.
|
|
11
|
+
* Implemented `AppState` model with `get`/`set` helpers and a `seed` boot
|
|
12
|
+
check using per-prompt `Digest::SHA256` hashes XOR-folded into a
|
|
13
|
+
fingerprint.
|
|
14
|
+
* Boot check prints `~`/`+`/`-` detail report on drift and prompts user
|
|
15
|
+
to acknowledge; declining retains old fingerprint for repeated notice
|
|
16
|
+
on next boot.
|
|
17
|
+
* Added `OC::DIFF_COMMAND` setting (`diff -u --color=always`) to `oc.rb`
|
|
18
|
+
for unified diff display, decoded via `Shellwords.split`.
|
|
19
|
+
* Implemented `prompt_sync` and `show_prompt_diff` methods in
|
|
20
|
+
`prompt_management.rb` to compare DB prompts against shipped defaults,
|
|
21
|
+
show unified diff, offer `OC::DIFF_TOOL` resolution, and clean up
|
|
22
|
+
orphaned default prompts.
|
|
23
|
+
* Wired `/prompt sync` subcommand into `commands.rb` (regexp, completion,
|
|
24
|
+
dispatch).
|
|
25
|
+
* **Test Mode**: Added `OllamaChat.test_mode` flag in `ollama_chat.rb` to
|
|
26
|
+
suppress interactive prompts during specs; set in `spec_helper.rb`.
|
|
27
|
+
* **Documentation**: Added YARD `@!attribute` docs for `test_mode` and
|
|
28
|
+
`test_mode?`.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
* **Web Searching**: Updated `web_searching.rb` to store `search_engine` in
|
|
33
|
+
local `engine` to avoid double method call.
|
|
34
|
+
* **Session Management**: Added call to `session_close` after
|
|
35
|
+
`clean_messages!` succeeds in `lib/ollama_chat/commands.rb`.
|
|
36
|
+
* **Error Messages**: Simplified stale context error message in `PatchFile`
|
|
37
|
+
when a checksum mismatch occurs.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
* **Spec Expectations**: Updated `web_searching_spec.rb` to replace `allow`
|
|
42
|
+
with `expect` for message expectations.
|
|
43
|
+
* Changed `log` expectations to `.at_least(:once)` since `links.add` also
|
|
44
|
+
triggers `log` internally.
|
|
45
|
+
* Removed unused `before { allow(chat).to receive(:log) }` from the
|
|
46
|
+
`#web` describe block.
|
|
47
|
+
* Added `.at_least(:once)` to `document_policy.selected` as it is called
|
|
48
|
+
in both `if` and `elsif` branches.
|
|
49
|
+
* Changed `fetch_source`, `summarize`, and `import` expectations to
|
|
50
|
+
`.twice` since they are called once per URL (2 URLs in test data).
|
|
51
|
+
|
|
52
|
+
### Tests
|
|
53
|
+
|
|
54
|
+
* Added 7 new spec examples for `prompt_sync` and `show_prompt_diff` in
|
|
55
|
+
`prompt_management_spec.rb`.
|
|
56
|
+
|
|
3
57
|
## 2026-08-18 v0.0.109
|
|
4
58
|
|
|
5
59
|
### Added
|
data/lib/ollama_chat/commands.rb
CHANGED
|
@@ -484,14 +484,15 @@ module OllamaChat::Commands
|
|
|
484
484
|
|
|
485
485
|
command(
|
|
486
486
|
name: :prompt,
|
|
487
|
-
regexp: %r(^/prompt(?:\s+(edit|info|add|delete|list|duplicate|import|export|reset|rename|-e))?(\s+(?:-[ef]|-c\s+(?:\w+|\?)))?(?:\s+([^-].*))?$),
|
|
488
|
-
complete: [ 'prompt', %w[ edit info add delete list duplicate import export reset rename ] ],
|
|
487
|
+
regexp: %r(^/prompt(?:\s+(edit|info|add|delete|list|duplicate|import|export|reset|rename|sync|-e))?(\s+(?:-[ef]|-c\s+(?:\w+|\?)))?(?:\s+([^-].*))?$),
|
|
488
|
+
complete: [ 'prompt', %w[ edit info add delete list duplicate import export reset rename sync ] ],
|
|
489
489
|
optional: true,
|
|
490
490
|
options: '[-c CONTEXT|-e|-f]',
|
|
491
491
|
help: <<~EOT,
|
|
492
492
|
📝 Manage prompt templates:
|
|
493
|
-
|
|
494
|
-
|
|
493
|
+
Subcommands: edit, info, add, delete, list,
|
|
494
|
+
duplicate, import, export, reset, rename,
|
|
495
|
+
sync.
|
|
495
496
|
Options: -c [context]
|
|
496
497
|
(? for interactive in /prompt),
|
|
497
498
|
-e (edit next)
|
|
@@ -544,6 +545,8 @@ module OllamaChat::Commands
|
|
|
544
545
|
STDOUT.puts "No default value found for prompt #{bold{prompt.name}}."
|
|
545
546
|
end
|
|
546
547
|
end
|
|
548
|
+
when 'sync'
|
|
549
|
+
prompt_sync(context:)
|
|
547
550
|
when nil, '-e'
|
|
548
551
|
if prompt = choose_prompt(
|
|
549
552
|
prompt: 'Which template shall guide the next response? %s',
|
|
@@ -619,6 +622,7 @@ module OllamaChat::Commands
|
|
|
619
622
|
)
|
|
620
623
|
then
|
|
621
624
|
messages.clean_messages!
|
|
625
|
+
session_close
|
|
622
626
|
STDOUT.puts "Conversation cleaned."
|
|
623
627
|
else
|
|
624
628
|
STDOUT.puts 'Cancelled.'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
change do
|
|
3
|
+
create_table :app_states do
|
|
4
|
+
primary_key :id
|
|
5
|
+
String :key, null: false, unique: true
|
|
6
|
+
Text :value # JSON-encoded payload
|
|
7
|
+
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP, null: false
|
|
8
|
+
DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP, null: false
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'digest'
|
|
2
|
+
|
|
3
|
+
# Represents a key/value pair of persistent application state stored in
|
|
4
|
+
# the database.
|
|
5
|
+
#
|
|
6
|
+
# This model provides a generic, JSON-backed store for small bits of
|
|
7
|
+
# runtime state that need to survive across sessions—such as the
|
|
8
|
+
# XOR-SHA256 fingerprint of the shipped default prompts used for boot
|
|
9
|
+
# drift detection.
|
|
10
|
+
class OllamaChat::Database::Models::AppState < Sequel::Model(OllamaChat::DB)
|
|
11
|
+
plugin :timestamps, update_on_create: true
|
|
12
|
+
plugin :serialization, :json, :value
|
|
13
|
+
plugin :validation_helpers
|
|
14
|
+
|
|
15
|
+
# Validates the application state entry.
|
|
16
|
+
#
|
|
17
|
+
# Ensures that the `key` is present and unique.
|
|
18
|
+
def validate
|
|
19
|
+
super
|
|
20
|
+
validates_presence :key
|
|
21
|
+
validates_unique :key
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Retrieves the JSON payload stored under the given key.
|
|
25
|
+
#
|
|
26
|
+
# @param key [String, Symbol] the state key to look up
|
|
27
|
+
# @return [Hash, nil] the deserialized JSON payload, or nil if no
|
|
28
|
+
# record exists for the key
|
|
29
|
+
def self.get(key)
|
|
30
|
+
where(key: key.to_s).first&.value
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Creates or updates the JSON payload stored under the given key.
|
|
34
|
+
#
|
|
35
|
+
# @param key [String, Symbol] the state key to write
|
|
36
|
+
# @param value [Hash, nil] the JSON-serializable payload to store
|
|
37
|
+
# @return [OllamaChat::Database::Models::AppState] the saved record
|
|
38
|
+
def self.set(key, value)
|
|
39
|
+
if found = where(key: key.to_s).first
|
|
40
|
+
found.update(value:)
|
|
41
|
+
found
|
|
42
|
+
else
|
|
43
|
+
create(key: key.to_s, value:)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Computes per-prompt SHA256 hashes and an XOR fingerprint of all shipped
|
|
48
|
+
# default prompts.
|
|
49
|
+
#
|
|
50
|
+
# At boot, if the stored fingerprint differs from the current one, a detail
|
|
51
|
+
# report (modified / added / removed) is printed to STDERR and the user is
|
|
52
|
+
# prompted to accept the new fingerprint. If declined, the old fingerprint
|
|
53
|
+
# is retained and the notice will reappear on the next boot.
|
|
54
|
+
#
|
|
55
|
+
# This method is invoked automatically by the model seeding loop in
|
|
56
|
+
# `OllamaChat::Database.setup_models`.
|
|
57
|
+
#
|
|
58
|
+
# @param chat [OllamaChat::Chat] the chat instance providing the config
|
|
59
|
+
# and `confirm?`
|
|
60
|
+
def self.seed(chat)
|
|
61
|
+
stored = get(:prompt_defaults_fingerprint)
|
|
62
|
+
|
|
63
|
+
stored_fingerprint = stored&.dig('fingerprint')
|
|
64
|
+
|
|
65
|
+
hashes = {}
|
|
66
|
+
chat.config.prompts.to_h.each do |context, prompts|
|
|
67
|
+
prompts.each do |name, content|
|
|
68
|
+
hashes["#{context}/#{name}"] =
|
|
69
|
+
Digest::SHA256.hexdigest(content.to_s)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
fingerprint = hashes.values.reduce(0) do |sum, hex|
|
|
74
|
+
sum ^ hex.to_i(16)
|
|
75
|
+
end.to_s(16)
|
|
76
|
+
|
|
77
|
+
return true if fingerprint == stored_fingerprint
|
|
78
|
+
|
|
79
|
+
if stored&.dig('hashes')
|
|
80
|
+
old = stored['hashes']
|
|
81
|
+
added = hashes.keys - old.keys
|
|
82
|
+
removed = old.keys - hashes.keys
|
|
83
|
+
changed = hashes.select { |k, v| old[k] && old[k] != v }.keys
|
|
84
|
+
|
|
85
|
+
STDERR.puts "⚠️ Shipped prompts changed since last boot:"
|
|
86
|
+
changed.each { |k| STDERR.puts " ~ #{k} (modified)" }
|
|
87
|
+
added.each { |k| STDERR.puts " + #{k} (new)" }
|
|
88
|
+
removed.each { |k| STDERR.puts " - #{k} (removed)" }
|
|
89
|
+
elsif !OllamaChat.test_mode?
|
|
90
|
+
STDERR.puts '⚠️ First run — storing prompt fingerprints.'
|
|
91
|
+
set(:prompt_defaults_fingerprint,
|
|
92
|
+
{ fingerprint:, hashes:, computed_at: Time.now.iso8601 })
|
|
93
|
+
return true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
prompt = <<~EOT.chomp << ' '
|
|
97
|
+
Keep local prompts (stop nagging)?
|
|
98
|
+
Consider adopting via /prompt sync or /prompt reset. (y/n) %s
|
|
99
|
+
EOT
|
|
100
|
+
if OllamaChat.test_mode? || chat.confirm?(prompt:, yes: /\Ay/i, timeout: 5)
|
|
101
|
+
set(:prompt_defaults_fingerprint,
|
|
102
|
+
{ fingerprint:, hashes:, computed_at: Time.now.iso8601 })
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @!attribute [v] id
|
|
109
|
+
# @return [Integer] The primary key for the state entry.
|
|
110
|
+
#
|
|
111
|
+
# @!attribute [v] key
|
|
112
|
+
# @return [String] The unique state key.
|
|
113
|
+
#
|
|
114
|
+
# @!attribute [v] value
|
|
115
|
+
# @return [Hash, nil] The JSON-serialized state payload.
|
|
116
|
+
#
|
|
117
|
+
# @!attribute [v] created_at
|
|
118
|
+
# @return [Time, nil] The timestamp when the state was created.
|
|
119
|
+
#
|
|
120
|
+
# @!attribute [v] updated_at
|
|
121
|
+
# @return [Time, nil] The timestamp of the last update to the state.
|
|
122
|
+
end
|
data/lib/ollama_chat/oc.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'const_conf'
|
|
2
2
|
require 'pathname'
|
|
3
|
+
require 'shellwords'
|
|
3
4
|
|
|
4
5
|
# Environment configuration module for OllamaChat
|
|
5
6
|
#
|
|
@@ -64,6 +65,14 @@ module OC
|
|
|
64
65
|
end
|
|
65
66
|
end
|
|
66
67
|
|
|
68
|
+
DIFF_COMMAND = set do
|
|
69
|
+
description 'Command (string) to generate a unified diff with'
|
|
70
|
+
|
|
71
|
+
required true
|
|
72
|
+
default { 'diff -u --color=always' }
|
|
73
|
+
decode { Shellwords.split(_1) if _1.present? }
|
|
74
|
+
end
|
|
75
|
+
|
|
67
76
|
DIFF_TOOL = set do
|
|
68
77
|
description 'Diff tool to apply changes with'
|
|
69
78
|
|
|
@@ -240,7 +240,6 @@ prompts:
|
|
|
240
240
|
How does this implementation handle malformed JSON or missing keys in the
|
|
241
241
|
middle of a 2GB file without crashing the process?
|
|
242
242
|
|
|
243
|
-
|
|
244
243
|
What is the time complexity of the current insert logic, and can we implement
|
|
245
244
|
bulk inserts to reduce database round trips?
|
|
246
245
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'tmpdir'
|
|
2
|
+
|
|
1
3
|
# Provides administrative and interactive management for
|
|
2
4
|
# prompt templates stored in the database.
|
|
3
5
|
#
|
|
@@ -382,6 +384,74 @@ module OllamaChat::PromptManagement
|
|
|
382
384
|
end
|
|
383
385
|
end
|
|
384
386
|
|
|
387
|
+
# Synchronizes database prompts with their shipped defaults from the
|
|
388
|
+
# configuration.
|
|
389
|
+
#
|
|
390
|
+
# For each default prompt in the given context, compares the database copy
|
|
391
|
+
# against the shipped default. Drifted prompts are displayed as a unified
|
|
392
|
+
# diff (via `OC::DIFF_COMMAND`), and the user is offered an interactive
|
|
393
|
+
# resolution via `OC::DIFF_TOOL`.
|
|
394
|
+
#
|
|
395
|
+
# Orphaned default prompts (present in the database but no longer in the
|
|
396
|
+
# shipped config) are listed and offered for deletion.
|
|
397
|
+
#
|
|
398
|
+
# @param context [String, nil] the prompt context to sync (default: 'prompt')
|
|
399
|
+
# @return [self, nil] self on success, nil if no drift was found
|
|
400
|
+
def prompt_sync(context: nil)
|
|
401
|
+
context ||= 'prompt'
|
|
402
|
+
shipped = config.prompts[context].to_h.stringify_keys_recursive
|
|
403
|
+
db_prompts = each_prompt(context:, default: true).to_a
|
|
404
|
+
|
|
405
|
+
drifted = db_prompts.select do |p|
|
|
406
|
+
shipped.key?(p.name) && shipped[p.name].to_s != p.to_s
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
orphans = db_prompts.select { |p| !shipped.key?(p.name) }
|
|
410
|
+
|
|
411
|
+
if drifted.empty? && orphans.empty?
|
|
412
|
+
STDOUT.puts "All prompts in context #{bold{context}} are in sync. ✨"
|
|
413
|
+
return self
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
if drifted.any?
|
|
417
|
+
STDOUT.puts "\n#{drifted.count} drifted prompt(s) found:\n"
|
|
418
|
+
drifted.each { |p| STDOUT.puts " • #{bold{p.name}} in #{italic{p.context}}" }
|
|
419
|
+
STDOUT.puts
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
confirm?(prompt: '⏎ Press any key to continue (%s). ', timeout: 5)
|
|
423
|
+
|
|
424
|
+
drifted.each do |p|
|
|
425
|
+
show_prompt_diff(p, shipped[p.name], context:)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
if orphans.any?
|
|
429
|
+
STDOUT.puts "\n#{orphans.count} orphaned prompt(s) "\
|
|
430
|
+
"(no longer in default config):\n"
|
|
431
|
+
orphans.each { |p| STDOUT.puts " • #{bold{p.name}} in #{italic{p.context}}" }
|
|
432
|
+
STDOUT.puts
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
confirm?(prompt: '⏎ Press any key to continue (%s). ', timeout: 5)
|
|
436
|
+
|
|
437
|
+
unless orphans.empty?
|
|
438
|
+
STDOUT.puts
|
|
439
|
+
if confirm?(
|
|
440
|
+
prompt: "🧹 Remove #{orphans.count} orphaned prompt(s)? (y/n) ",
|
|
441
|
+
yes: /\Ay/i
|
|
442
|
+
)
|
|
443
|
+
then
|
|
444
|
+
orphans.each do |p|
|
|
445
|
+
p.destroy
|
|
446
|
+
STDOUT.puts " ✓ Removed #{bold{p.name}}"
|
|
447
|
+
log(:info, "Orphan prompt cleaned up", data: { name: p.name, context: })
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
self
|
|
453
|
+
end
|
|
454
|
+
|
|
385
455
|
private
|
|
386
456
|
|
|
387
457
|
# Helper to wrap a prompt name with its favourite status for the UI.
|
|
@@ -395,6 +465,60 @@ module OllamaChat::PromptManagement
|
|
|
395
465
|
SearchUI::Wrapper.new(name, display:)
|
|
396
466
|
end
|
|
397
467
|
|
|
468
|
+
# Writes the database copy and the shipped default to temp files and
|
|
469
|
+
# displays a unified diff via `OC::DIFF_COMMAND`.
|
|
470
|
+
#
|
|
471
|
+
# If the user opts in, launches `OC::DIFF_TOOL` for interactive
|
|
472
|
+
# resolution; the resolved content (file A) is then written back
|
|
473
|
+
# to the database.
|
|
474
|
+
#
|
|
475
|
+
# @param prompt [OllamaChat::Database::Models::Prompt] the DB prompt
|
|
476
|
+
# @param shipped [String] the shipped default content from config
|
|
477
|
+
# @param context [String] the prompt context
|
|
478
|
+
def show_prompt_diff(prompt, shipped, context:)
|
|
479
|
+
STDOUT.puts "\n#{'─' * 60}"
|
|
480
|
+
STDOUT.puts "📝 #{bold{prompt.name}}"
|
|
481
|
+
STDOUT.puts '─' * 60
|
|
482
|
+
|
|
483
|
+
Dir.mktmpdir('prompt_sync') do |dir|
|
|
484
|
+
file_a = File.join(dir, "#{prompt.name}.local")
|
|
485
|
+
file_b = File.join(dir, "#{prompt.name}.default")
|
|
486
|
+
File.write(file_a, prompt.to_s)
|
|
487
|
+
File.write(file_b, shipped.to_s)
|
|
488
|
+
|
|
489
|
+
cmd = OC::DIFF_COMMAND.dup << file_a << file_b
|
|
490
|
+
output = IO.popen(cmd, &:read).chomp
|
|
491
|
+
|
|
492
|
+
if output.empty?
|
|
493
|
+
STDOUT.puts " (no differences detected)"
|
|
494
|
+
else
|
|
495
|
+
STDOUT.puts output
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
STDOUT.puts
|
|
499
|
+
if confirm?(
|
|
500
|
+
prompt: "🔧 Resolve differences for #{bold{prompt.name}}? (y/n) ",
|
|
501
|
+
yes: /\Ay/i
|
|
502
|
+
)
|
|
503
|
+
then
|
|
504
|
+
unless diff_tool = OC::DIFF_TOOL?
|
|
505
|
+
STDERR.puts ' No DIFF_TOOL available.'
|
|
506
|
+
return
|
|
507
|
+
end
|
|
508
|
+
system(*[diff_tool, file_a, file_b].map(&:to_s))
|
|
509
|
+
resolved = File.read(file_a)
|
|
510
|
+
if resolved != prompt.to_s
|
|
511
|
+
write_prompt(prompt.name, resolved, context:)
|
|
512
|
+
STDOUT.puts " ✓ Updated #{bold{prompt.name}}"
|
|
513
|
+
log(:info, "Prompt synced via diff tool",
|
|
514
|
+
data: { name: prompt.name, context: })
|
|
515
|
+
else
|
|
516
|
+
STDOUT.puts " (no changes made)"
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
398
522
|
# Interactively determines a unique name for a new prompt, ensuring it
|
|
399
523
|
# does not conflict with existing prompts in the database.
|
|
400
524
|
#
|
|
@@ -132,7 +132,7 @@ class OllamaChat::Tools::PatchFile
|
|
|
132
132
|
if args.checksum != current_checksum
|
|
133
133
|
raise OllamaChat::ToolFunctionArgumentError,
|
|
134
134
|
"Stale context: File `#{path}` has been modified since your last read. " \
|
|
135
|
-
"
|
|
135
|
+
"Unexpected checksum `#{args.checksum}`, I cannot patch!"
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
# We use the content we just read for the patch, as it's verified fresh
|
data/lib/ollama_chat/version.rb
CHANGED
|
@@ -24,16 +24,17 @@ module OllamaChat::WebSearching
|
|
|
24
24
|
def search_web(query, n = nil)
|
|
25
25
|
n = n.to_i.clamp(1..)
|
|
26
26
|
query = URI.encode_uri_component(query)
|
|
27
|
-
|
|
27
|
+
engine = search_engine
|
|
28
|
+
search_command = :"search_web_with_#{engine}"
|
|
28
29
|
if respond_to?(search_command, true)
|
|
29
30
|
send(search_command, query, n).tap do |results|
|
|
30
31
|
log(:info, "Web search performed", data: {
|
|
31
|
-
search_engine
|
|
32
|
+
search_engine: engine, query:, results: results.size
|
|
32
33
|
})
|
|
33
34
|
results.each { |url| links.add(url) }
|
|
34
35
|
end
|
|
35
36
|
else
|
|
36
|
-
STDOUT.puts "Search engine #{bold{
|
|
37
|
+
STDOUT.puts "Search engine #{bold{engine}} not implemented!"
|
|
37
38
|
nil
|
|
38
39
|
end
|
|
39
40
|
end
|
data/lib/ollama_chat.rb
CHANGED
|
@@ -20,9 +20,9 @@ module OllamaChat
|
|
|
20
20
|
#
|
|
21
21
|
# The error carries the offending `#path` as an attribute so that
|
|
22
22
|
# callers can log or display the problematic location.
|
|
23
|
-
#
|
|
24
|
-
# @attr [String] path The path that caused the error.
|
|
25
23
|
class InvalidPathError < OllamaChatError
|
|
24
|
+
# @!attribute [r] path
|
|
25
|
+
# @return [String] The path that caused the error.
|
|
26
26
|
attr_accessor :path
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -74,6 +74,24 @@ module OllamaChat
|
|
|
74
74
|
#
|
|
75
75
|
# @return [Regexp] the pattern for validating collection identifiers
|
|
76
76
|
COLLECTION_NAME_REGEXP = /[-\w\.]+/
|
|
77
|
+
|
|
78
|
+
class << self
|
|
79
|
+
# @!attribute [w] test_mode
|
|
80
|
+
# @return [Boolean] test_mode Whether test mode is enabled.
|
|
81
|
+
# Suppresses interactive prompts during seeding.
|
|
82
|
+
attr_writer :test_mode
|
|
83
|
+
|
|
84
|
+
# Checks whether test mode is enabled.
|
|
85
|
+
#
|
|
86
|
+
# When true, `AppState.seed` skips the interactive
|
|
87
|
+
# `confirm?` prompt and auto-accepts new prompt fingerprints.
|
|
88
|
+
#
|
|
89
|
+
# @return [Boolean] true if test mode is enabled
|
|
90
|
+
def test_mode?
|
|
91
|
+
!!@test_mode
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
self.test_mode = false
|
|
77
95
|
end
|
|
78
96
|
|
|
79
97
|
require 'ollama'
|
data/ollama_chat.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: ollama_chat 0.0.
|
|
2
|
+
# stub: ollama_chat 0.0.110 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "ollama_chat".freeze
|
|
6
|
-
s.version = "0.0.
|
|
6
|
+
s.version = "0.0.110".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,8 +12,8 @@ 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/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/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_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]
|
|
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]
|
|
@@ -461,4 +461,114 @@ describe OllamaChat::PromptManagement do
|
|
|
461
461
|
expect(chat.determine_valid_new_name_for_prompt('to add')).to be_nil
|
|
462
462
|
end
|
|
463
463
|
end
|
|
464
|
+
|
|
465
|
+
describe '#prompt_sync' do
|
|
466
|
+
it 'reports all in sync when no drift or orphans' do
|
|
467
|
+
expect(chat.config.prompts).to receive(:[]).with('prompt')
|
|
468
|
+
.and_return({})
|
|
469
|
+
expect(chat).to receive(:each_prompt)
|
|
470
|
+
.with(context: 'prompt', default: true).and_return([])
|
|
471
|
+
|
|
472
|
+
expect(STDOUT).to receive(:puts).with(/in sync/)
|
|
473
|
+
expect(chat.prompt_sync).to eq(chat)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
it 'detects drifted prompts and calls show_prompt_diff' do
|
|
477
|
+
p = prompt_model.create(context: 'prompt', name: 'zz_drifted',
|
|
478
|
+
metadata: { default: true, content: 'local' })
|
|
479
|
+
expect(chat.config.prompts).to receive(:[]).with('prompt')
|
|
480
|
+
.and_return('zz_drifted' => 'shipped')
|
|
481
|
+
expect(chat).to receive(:each_prompt)
|
|
482
|
+
.with(context: 'prompt', default: true).and_return([p])
|
|
483
|
+
|
|
484
|
+
expect(chat).to receive(:confirm?)
|
|
485
|
+
.with(hash_including(prompt: /Press any key/)).twice.and_return(true)
|
|
486
|
+
expect(chat).to receive(:show_prompt_diff)
|
|
487
|
+
.with(p, 'shipped', context: 'prompt')
|
|
488
|
+
expect(chat.prompt_sync).to eq(chat)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it 'detects orphaned prompts and cleans up on confirm' do
|
|
492
|
+
p = prompt_model.create(context: 'prompt', name: 'zz_orphan',
|
|
493
|
+
metadata: { default: true, content: 'x' })
|
|
494
|
+
expect(chat.config.prompts).to receive(:[]).with('prompt')
|
|
495
|
+
.and_return({})
|
|
496
|
+
expect(chat).to receive(:each_prompt)
|
|
497
|
+
.with(context: 'prompt', default: true).and_return([p])
|
|
498
|
+
|
|
499
|
+
expect(chat).to receive(:confirm?)
|
|
500
|
+
.with(hash_including(prompt: /Press any key/)).twice.and_return(true)
|
|
501
|
+
expect(chat).to receive(:confirm?)
|
|
502
|
+
.with(hash_including(prompt: /Remove/)).and_return(true)
|
|
503
|
+
expect { chat.prompt_sync }.to change { prompt_model.count }.by(-1)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
it 'keeps orphans when user declines cleanup' do
|
|
507
|
+
p = prompt_model.create(context: 'prompt', name: 'zz_orphan',
|
|
508
|
+
metadata: { default: true, content: 'x' })
|
|
509
|
+
expect(chat.config.prompts).to receive(:[]).with('prompt')
|
|
510
|
+
.and_return({})
|
|
511
|
+
expect(chat).to receive(:each_prompt)
|
|
512
|
+
.with(context: 'prompt', default: true).and_return([p])
|
|
513
|
+
|
|
514
|
+
expect(chat).to receive(:confirm?)
|
|
515
|
+
.with(hash_including(prompt: /Press any key/)).twice.and_return(true)
|
|
516
|
+
expect(chat).to receive(:confirm?)
|
|
517
|
+
.with(hash_including(prompt: /Remove/)).and_return(false)
|
|
518
|
+
expect { chat.prompt_sync }.not_to change { prompt_model.count }
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
it 'handles both drifted and orphaned prompts' do
|
|
522
|
+
drifted = prompt_model.create(context: 'prompt', name: 'zz_drifted',
|
|
523
|
+
metadata: { default: true, content: 'local' })
|
|
524
|
+
orphan = prompt_model.create(context: 'prompt', name: 'zz_orphan',
|
|
525
|
+
metadata: { default: true, content: 'x' })
|
|
526
|
+
expect(chat.config.prompts).to receive(:[]).with('prompt')
|
|
527
|
+
.and_return('zz_drifted' => 'shipped')
|
|
528
|
+
expect(chat).to receive(:each_prompt)
|
|
529
|
+
.with(context: 'prompt', default: true).and_return([drifted, orphan])
|
|
530
|
+
|
|
531
|
+
expect(chat).to receive(:confirm?)
|
|
532
|
+
.with(hash_including(prompt: /Press any key/)).twice.and_return(true)
|
|
533
|
+
expect(chat).to receive(:show_prompt_diff)
|
|
534
|
+
.with(drifted, 'shipped', context: 'prompt')
|
|
535
|
+
expect(chat).to receive(:confirm?)
|
|
536
|
+
.with(hash_including(prompt: /Remove/)).and_return(true)
|
|
537
|
+
|
|
538
|
+
expect { chat.prompt_sync }
|
|
539
|
+
.to change { prompt_model.where(name: 'zz_orphan').count }
|
|
540
|
+
.from(1).to(0)
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
describe '#show_prompt_diff' do
|
|
545
|
+
it 'displays diff and skips resolution when declined' do
|
|
546
|
+
p = prompt_model.create(context: 'prompt', name: 'zz_diff_me',
|
|
547
|
+
metadata: { default: true, content: 'local' })
|
|
548
|
+
|
|
549
|
+
expect(chat).to receive(:confirm?).and_return(false)
|
|
550
|
+
expect { chat.show_prompt_diff(p, 'shipped', context: 'prompt') }
|
|
551
|
+
.not_to raise_error
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
it 'updates prompt when resolved content differs' do
|
|
555
|
+
p = prompt_model.create(context: 'prompt', name: 'zz_resolve',
|
|
556
|
+
metadata: { default: true, content: 'before' })
|
|
557
|
+
|
|
558
|
+
expect(chat).to receive(:confirm?).and_return(true)
|
|
559
|
+
expect(OC).to receive(:DIFF_TOOL?).and_return(%w[vimdiff])
|
|
560
|
+
# Simulate vimdiff editing file_a by wrapping system to write to it
|
|
561
|
+
expect(chat).to receive(:system) do |*args|
|
|
562
|
+
file_a = args[-2]
|
|
563
|
+
File.write(file_a, 'after resolution')
|
|
564
|
+
true
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
expect(chat).to receive(:write_prompt)
|
|
568
|
+
.with('zz_resolve', 'after resolution', context: 'prompt')
|
|
569
|
+
|
|
570
|
+
expect { chat.show_prompt_diff(p, 'default', context: 'prompt') }
|
|
571
|
+
.not_to raise_error
|
|
572
|
+
end
|
|
573
|
+
end
|
|
464
574
|
end
|
|
@@ -11,26 +11,26 @@ describe OllamaChat::WebSearching do
|
|
|
11
11
|
|
|
12
12
|
describe '#search_web' do
|
|
13
13
|
it 'returns nil and warns for an unimplemented engine' do
|
|
14
|
-
|
|
14
|
+
expect(chat).to receive(:search_engine).and_return('nonexistent')
|
|
15
15
|
expect(STDOUT).to receive(:puts).with(/not implemented/)
|
|
16
16
|
expect(chat.search_web('ruby')).to be_nil
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it 'delegates to the engine method and collects links' do
|
|
20
|
-
|
|
20
|
+
expect(chat).to receive(:search_engine).and_return('duckduckgo')
|
|
21
21
|
urls = %w[https://a.example https://b.example]
|
|
22
22
|
expect(chat).to receive(:search_web_with_duckduckgo)
|
|
23
23
|
.with(/ruby/, 2).and_return(urls)
|
|
24
|
-
|
|
24
|
+
expect(chat).to receive(:log).at_least(:once)
|
|
25
25
|
expect(chat.links).to receive(:add).twice
|
|
26
26
|
expect(chat.search_web('ruby', 2)).to eq(urls)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
it 'clamps n below 1 to a minimum of 1' do
|
|
30
|
-
|
|
30
|
+
expect(chat).to receive(:search_engine).and_return('duckduckgo')
|
|
31
31
|
expect(chat).to receive(:search_web_with_duckduckgo)
|
|
32
32
|
.with(/ruby/, 1).and_return(%w[https://a.example])
|
|
33
|
-
|
|
33
|
+
expect(chat).to receive(:log).at_least(:once)
|
|
34
34
|
chat.search_web('ruby', 0)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
@@ -38,28 +38,26 @@ describe OllamaChat::WebSearching do
|
|
|
38
38
|
describe '#web' do
|
|
39
39
|
let(:urls) { %w[https://a.example https://b.example] }
|
|
40
40
|
|
|
41
|
-
before { allow(chat).to receive(:log) }
|
|
42
|
-
|
|
43
41
|
it 'returns :next when no search results are found' do
|
|
44
|
-
|
|
42
|
+
expect(chat).to receive(:search_web).and_return(nil)
|
|
45
43
|
expect(chat.web('1', 'ruby')).to be(:next)
|
|
46
44
|
end
|
|
47
45
|
|
|
48
46
|
context 'when policy is embedding and embedding is on' do
|
|
49
47
|
before do
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
expect(chat.document_policy).to receive(:selected).
|
|
49
|
+
at_least(:once).and_return('embedding')
|
|
50
|
+
expect(chat.instance_variable_get(:@embedding)).
|
|
53
51
|
to receive(:on?).and_return(true)
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
it 'embeds each source and interpolates the web_embed prompt' do
|
|
57
|
-
|
|
55
|
+
expect(chat).to receive(:prompt).with(:web_embed).
|
|
58
56
|
and_return(double('prompt', to_s: 'Search for: %{query}'))
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
expect(chat).to receive(:search_web).and_return(urls)
|
|
58
|
+
expect(chat).to receive(:fetch_source).twice do |_url, &block|
|
|
59
|
+
block&.call(nil)
|
|
60
|
+
end
|
|
63
61
|
expect(chat).to receive(:embed_source).twice
|
|
64
62
|
result = chat.web('2', 'ruby tutorials')
|
|
65
63
|
expect(result).to eq('Search for: ruby tutorials')
|
|
@@ -68,15 +66,16 @@ describe OllamaChat::WebSearching do
|
|
|
68
66
|
|
|
69
67
|
context 'when policy is summarizing' do
|
|
70
68
|
before do
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
expect(chat.document_policy).to receive(:selected).
|
|
70
|
+
at_least(:once).and_return('summarizing')
|
|
73
71
|
end
|
|
74
72
|
|
|
75
73
|
it 'summarizes each URL and interpolates the prompt' do
|
|
76
|
-
|
|
74
|
+
expect(chat).to receive(:prompt).with(:web_import).
|
|
77
75
|
and_return(double('prompt', to_s: 'Q: %{query} R: %{results}'))
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
expect(chat).to receive(:search_web).and_return(urls)
|
|
77
|
+
expect(chat).to receive(:summarize).twice
|
|
78
|
+
.and_return('summary text')
|
|
80
79
|
result = chat.web('2', 'ruby')
|
|
81
80
|
expect(result).to eq('Q: ruby R: summary textsummary text')
|
|
82
81
|
end
|
|
@@ -84,15 +83,16 @@ describe OllamaChat::WebSearching do
|
|
|
84
83
|
|
|
85
84
|
context 'when policy is importing (default)' do
|
|
86
85
|
before do
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
expect(chat.document_policy).to receive(:selected).
|
|
87
|
+
at_least(:once).and_return('importing')
|
|
89
88
|
end
|
|
90
89
|
|
|
91
90
|
it 'imports each URL and interpolates the prompt' do
|
|
92
|
-
|
|
91
|
+
expect(chat).to receive(:prompt).with(:web_summarize).
|
|
93
92
|
and_return(double('prompt', to_s: 'Q: %{query} R: %{results}'))
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
expect(chat).to receive(:search_web).and_return(urls)
|
|
94
|
+
expect(chat).to receive(:import).twice
|
|
95
|
+
.and_return('imported text')
|
|
96
96
|
result = chat.web('2', 'ruby')
|
|
97
97
|
expect(result).to eq('Q: ruby R: imported textimported text')
|
|
98
98
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -213,6 +213,7 @@ RSpec.configure do |config|
|
|
|
213
213
|
end
|
|
214
214
|
|
|
215
215
|
config.before do
|
|
216
|
+
OllamaChat.test_mode = true
|
|
216
217
|
const_conf_as(
|
|
217
218
|
'OC::OLLAMA::CHAT::HISTORY' => Pathname.pwd.join('tmp', 'history.json'),
|
|
218
219
|
'OC::OLLAMA::CHAT::LOGFILE' => Pathname.pwd.join('tmp', 'chat.log'),
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ollama_chat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.110
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -497,6 +497,8 @@ extra_rdoc_files:
|
|
|
497
497
|
- lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb
|
|
498
498
|
- lib/ollama_chat/database/migrations/007_add_collections_table.rb
|
|
499
499
|
- lib/ollama_chat/database/migrations/008_drop_think_mode_constraint.rb
|
|
500
|
+
- lib/ollama_chat/database/migrations/009_add_app_states_table.rb
|
|
501
|
+
- lib/ollama_chat/database/models/app_state.rb
|
|
500
502
|
- lib/ollama_chat/database/models/collection.rb
|
|
501
503
|
- lib/ollama_chat/database/models/favourite.rb
|
|
502
504
|
- lib/ollama_chat/database/models/model_options.rb
|
|
@@ -626,6 +628,8 @@ files:
|
|
|
626
628
|
- lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb
|
|
627
629
|
- lib/ollama_chat/database/migrations/007_add_collections_table.rb
|
|
628
630
|
- lib/ollama_chat/database/migrations/008_drop_think_mode_constraint.rb
|
|
631
|
+
- lib/ollama_chat/database/migrations/009_add_app_states_table.rb
|
|
632
|
+
- lib/ollama_chat/database/models/app_state.rb
|
|
629
633
|
- lib/ollama_chat/database/models/collection.rb
|
|
630
634
|
- lib/ollama_chat/database/models/favourite.rb
|
|
631
635
|
- lib/ollama_chat/database/models/model_options.rb
|