Class: OllamaChat::Database::Models::AppState

Inherits:
Object
  • Object
show all
Defined in:
lib/ollama_chat/database/models/app_state.rb

Overview

Represents a key/value pair of persistent application state stored in the database.

This model provides a generic, JSON-backed store for small bits of runtime state that need to survive across sessions—such as the XOR-SHA256 fingerprint of the shipped default prompts used for boot drift detection.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.get(key) ⇒ Hash?

Retrieves the JSON payload stored under the given key.

Parameters:

  • key (String, Symbol)

    the state key to look up

Returns:

  • (Hash, nil)

    the deserialized JSON payload, or nil if no record exists for the key



29
30
31
# File 'lib/ollama_chat/database/models/app_state.rb', line 29

def self.get(key)
  where(key: key.to_s).first&.value
end

.seed(chat) ⇒ Object

Computes per-prompt SHA256 hashes and an XOR fingerprint of all shipped default prompts.

At boot, if the stored fingerprint differs from the current one, a detail report (modified / added / removed) is printed to STDERR and the user is prompted to accept the new fingerprint. If declined, the old fingerprint is retained and the notice will reappear on the next boot.

This method is invoked automatically by the model seeding loop in OllamaChat::Database.setup_models.

Parameters:

  • chat (OllamaChat::Chat)

    the chat instance providing the config and confirm?



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ollama_chat/database/models/app_state.rb', line 60

def self.seed(chat)
  stored = get(:prompt_defaults_fingerprint)

  stored_fingerprint = stored&.dig('fingerprint')

  hashes = {}
  chat.config.prompts.to_h.each do |context, prompts|
    prompts.each do |name, content|
      hashes["#{context}/#{name}"] =
        Digest::SHA256.hexdigest(content.to_s)
    end
  end

  fingerprint = hashes.values.reduce(0) do |sum, hex|
    sum ^ hex.to_i(16)
  end.to_s(16)

  return true if fingerprint == stored_fingerprint

  if stored&.dig('hashes')
    old     = stored['hashes']
    added   = hashes.keys - old.keys
    removed = old.keys - hashes.keys
    changed = hashes.select { |k, v| old[k] && old[k] != v }.keys

    STDERR.puts "⚠️  Shipped prompts changed since last boot:"
    changed.each { |k| STDERR.puts "  ~ #{k} (modified)" }
    added.each   { |k| STDERR.puts "  + #{k} (new)" }
    removed.each { |k| STDERR.puts "  - #{k} (removed)" }
  elsif !OllamaChat.test_mode?
    STDERR.puts '⚠️  First run — storing prompt fingerprints.'
    set(:prompt_defaults_fingerprint,
        { fingerprint:, hashes:, computed_at: Time.now.iso8601 })
    return true
  end

  prompt = <<~EOT.chomp << ' '
    Keep local prompts (stop nagging)?
    Consider adopting via /prompt sync or /prompt reset. (y/n) %s
  EOT
  if OllamaChat.test_mode? || chat.confirm?(prompt:, yes: /\Ay/i, timeout: 5)
    set(:prompt_defaults_fingerprint,
        { fingerprint:, hashes:, computed_at: Time.now.iso8601 })
  end

  true
end

.set(key, value) ⇒ OllamaChat::Database::Models::AppState

Creates or updates the JSON payload stored under the given key.

Parameters:

  • key (String, Symbol)

    the state key to write

  • value (Hash, nil)

    the JSON-serializable payload to store

Returns:



38
39
40
41
42
43
44
45
# File 'lib/ollama_chat/database/models/app_state.rb', line 38

def self.set(key, value)
  if found = where(key: key.to_s).first
    found.update(value:)
    found
  else
    create(key: key.to_s, value:)
  end
end

Instance Method Details

#created_at=(value) ⇒ Time?

Returns The timestamp when the state was created.

Returns:

  • (Time, nil)

    The timestamp when the state was created.



# File 'lib/ollama_chat/database/models/app_state.rb', line 108

#id=(value) ⇒ Integer

Returns The primary key for the state entry.

Returns:

  • (Integer)

    The primary key for the state entry.



# File 'lib/ollama_chat/database/models/app_state.rb', line 108

#key=(value) ⇒ String

Returns The unique state key.

Returns:

  • (String)

    The unique state key.



# File 'lib/ollama_chat/database/models/app_state.rb', line 108

#updated_at=(value) ⇒ Time?

Returns The timestamp of the last update to the state.

Returns:

  • (Time, nil)

    The timestamp of the last update to the state.



# File 'lib/ollama_chat/database/models/app_state.rb', line 108

#validateObject

Validates the application state entry.

Ensures that the key is present and unique.



18
19
20
21
22
# File 'lib/ollama_chat/database/models/app_state.rb', line 18

def validate
  super
  validates_presence :key
  validates_unique :key
end

#value=(value) ⇒ Hash?

Returns The JSON-serialized state payload.

Returns:

  • (Hash, nil)

    The JSON-serialized state payload.



# File 'lib/ollama_chat/database/models/app_state.rb', line 108