Module: OllamaChat::PersonaeManagement
- Included in:
- Chat
- Defined in:
- lib/ollama_chat/personae_management.rb
Overview
Module for managing personas in Ollama chat application
This module provides functionality to manage persona files, including creating, reading, updating, and deleting persona definitions stored as Markdown files in the personae directory.
Instance Method Summary collapse
-
#add_persona ⇒ String
private
Creates a new persona file interactively.
-
#available_personae ⇒ Array<String>
private
Returns a sorted list of available persona file names.
-
#choose_persona(chosen: nil) ⇒ String?
private
Interactive method to select a persona from a list.
-
#default_persona_name ⇒ String
private
The default_persona_name method returns the name of the currently set default persona by extracting its basename and removing the file extension, unless no persona is set.
-
#delete_persona ⇒ String
private
Interactive method to delete an existing persona with backup functionality.
-
#edit_persona ⇒ Object
private
Interactive method to edit an existing persona file.
-
#info_persona ⇒ Object
private
Displays detailed information about a selected persona.
-
#list_personae ⇒ Object
private
Lists all available persona names.
-
#load_persona_file(persona) ⇒ Array<Pathname, String>
private
Loads a persona file from disk.
-
#load_personae ⇒ Object
private
Interactive method to load multiple personae for use.
-
#persona_backup_pathname(persona) ⇒ Pathname
private
Generates the backup pathname for a persona file with timestamp.
-
#personae_backup_directory ⇒ Pathname
private
Returns the directory path for persona backup files.
-
#personae_directory ⇒ Pathname
private
Returns the directory path where persona files are stored.
-
#personae_result(personae) ⇒ String
private
Returns a JSON hash with results for one or more personae.
-
#play_persona(pathname: nil) ⇒ Object
private
Initiates roleplay with a selected persona.
-
#play_persona_file(pathname) ⇒ Object
private
Initiates roleplay with a persona from a specific file path.
-
#play_persona_prompt(persona:, persona_profile:) ⇒ String
private
Generates the roleplay prompt string for a persona.
-
#reload_default_persona ⇒ Object
private
Reloads the default persona file if one is set and not :none, prompting the user for confirmation before playing the persona file or loading a new default persona and changing the default.
-
#setup_persona_from_opts ⇒ Object
private
The setup_persona_from_opts method initializes persona setup by checking for a provided persona option, determining the appropriate file path, and playing the persona file if it exists.
-
#setup_personae_directory ⇒ Object
private
Creates the personae directory structure if it doesn’t already exist.
Instance Method Details
#add_persona ⇒ String (private)
Creates a new persona file interactively.
The method prompts the user to enter a name for the persona, creates an empty Markdown file with that name in the personas directory (if it does not already exist), opens the file in the configured editor, and finally returns the result of calling #personae_result on the created file.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/ollama_chat/personae_management.rb', line 128 def add_persona persona_name = ask?( prompt: "❓ Enter the name of the new persona (or press return to cancel): " ).full? or return pathname = personae_directory + "#{persona_name}.md" unless pathname.exist? File.write pathname, config.prompts.persona end edit_file(pathname) personae_result(pathname.basename) end |
#available_personae ⇒ Array<String> (private)
Returns a sorted list of available persona file names.
This method scans the personae directory for Markdown files and returns their basenames sorted alphabetically.
115 116 117 |
# File 'lib/ollama_chat/personae_management.rb', line 115 def available_personae personae_directory.glob('*.md').map(&:basename).sort end |
#choose_persona(chosen: nil) ⇒ String? (private)
Interactive method to select a persona from a list.
Allows the user to choose a persona from available options or exit. Selected persona is returned if successful, nil otherwise.
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/ollama_chat/personae_management.rb', line 249 def choose_persona(chosen: nil) personae_list = available_personae.reject { chosen&.member?(_1) } if personae_list.empty? STDERR.puts "No personae defined." return end personae_list.unshift('[EXIT]') case chosen = OllamaChat::Utils::Chooser.choose(personae_list) when '[EXIT]', nil STDOUT.puts "Exiting chooser." return else chosen end end |
#default_persona_name ⇒ String (private)
The default_persona_name method returns the name of the currently set default persona by extracting its basename and removing the file extension, unless no persona is set.
64 65 66 67 68 |
# File 'lib/ollama_chat/personae_management.rb', line 64 def default_persona_name if @default_persona.present? && @default_persona != :none @default_persona.basename.sub_ext('').to_s end end |
#delete_persona ⇒ String (private)
Interactive method to delete an existing persona with backup functionality.
Prompts the user to select a persona, asks for confirmation, and creates a timestamped backup of the persona file before deletion.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/ollama_chat/personae_management.rb', line 167 def delete_persona if persona = choose_persona persona = persona pathname = personae_directory + persona backup_pathname = persona_backup_pathname(persona) if pathname.exist? STDOUT.puts "Deleting '#{bold{persona.sub_ext('')}}'..." STDOUT.puts "Backup will be saved to: #{backup_pathname}" if confirm?(prompt: "🔔 Are you sure? (y/n) ") =~ /y/i FileUtils.mv pathname, backup_pathname STDOUT.puts "✅ Persona #{bold{persona.sub_ext('')}} deleted successfully" { success: true, persona: persona.sub_ext(''), backup_pathname:, }.to_json else STDOUT.puts "Deletion cancelled." return end else STDOUT.puts "Persona not found." return end end end |
#edit_persona ⇒ Object (private)
Interactive method to edit an existing persona file.
Prompts the user to select a persona, opens it for editing, backups the old content, and returns the result after editing.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/ollama_chat/personae_management.rb', line 199 def edit_persona if persona = choose_persona persona = persona pathname = personae_directory + persona old_content = File.read(pathname) if edit_file(pathname) changed = File.read(pathname) != old_content if changed File.write(persona_backup_pathname(persona), old_content) end personae_result(persona) end end end |
#info_persona ⇒ Object (private)
Displays detailed information about a selected persona.
Shows the persona’s profile using kramdown formatting with ansi parsing.
217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/ollama_chat/personae_management.rb', line 217 def info_persona if persona = choose_persona _persona, persona_profile = load_persona_file(persona) use_pager do |output| output.puts kramdown_ansi_parse(<<~EOT) # Persona #{persona.sub_ext('')} --- #{persona_profile} --- EOT end end end |
#list_personae ⇒ Object (private)
Lists all available persona names.
Outputs the sorted list of persona filenames to STDOUT.
234 235 236 237 238 239 240 |
# File 'lib/ollama_chat/personae_management.rb', line 234 def list_personae if personae = available_personae.full? STDOUT.puts available_personae else STDOUT.puts "No personae defined." end end |
#load_persona_file(persona) ⇒ Array<Pathname, String> (private)
Loads a persona file from disk.
312 313 314 315 316 317 |
# File 'lib/ollama_chat/personae_management.rb', line 312 def load_persona_file(persona) pathname = personae_directory + persona if pathname.exist? return pathname, pathname.read end end |
#load_personae ⇒ Object (private)
Interactive method to load multiple personae for use.
Allows sequential selection of multiple personae. Returns JSON results for each loaded persona.
269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/ollama_chat/personae_management.rb', line 269 def load_personae chosen = Set[] while persona = choose_persona(chosen: chosen) chosen << persona end if chosen.empty? STDOUT.puts "No persona loaded." return end personae_result(chosen) end |
#persona_backup_pathname(persona) ⇒ Pathname (private)
The timestamp ensures each backup has a unique filename when multiple backups of the same persona exist
Generates the backup pathname for a persona file with timestamp.
Creates a unique backup filename with the persona name, timestamp, and .md.bak extension. The timestamp format is YYYYMMDDHHMMSS for precise identification of backup versions.
155 156 157 158 |
# File 'lib/ollama_chat/personae_management.rb', line 155 def persona_backup_pathname(persona) = Time.now.strftime('%Y%m%d%H%M%S') personae_backup_directory + (persona.sub_ext('').to_s + ?- + + '.md.bak') end |
#personae_backup_directory ⇒ Pathname (private)
The directory is created automatically if it doesn’t exist
Returns the directory path for persona backup files.
26 27 28 |
# File 'lib/ollama_chat/personae_management.rb', line 26 def personae_backup_directory personae_directory + 'backups' end |
#personae_directory ⇒ Pathname (private)
The directory is created automatically if it doesn’t exist
Returns the directory path where persona files are stored.
The path is constructed using the XDG_CONFIG_HOME environment variable for platform-agnostic configuration storage.
17 18 19 |
# File 'lib/ollama_chat/personae_management.rb', line 17 def personae_directory OC::XDG_CONFIG_HOME + 'personae' end |
#personae_result(personae) ⇒ String (private)
Returns a JSON hash with results for one or more personae.
Loads the profile file for each persona and returns the results as JSON.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/ollama_chat/personae_management.rb', line 289 def personae_result(personae) personae = Array(personae) result = {} personae.each do |persona| pathname = personae_directory + persona pathname.exist? or next result[persona.sub_ext('')] = { pathname: , profile: pathname.read, } end result.to_json end |
#play_persona(pathname: nil) ⇒ Object (private)
Initiates roleplay with a selected persona.
Uses the persona selection and loading methods to generate the appropriate roleplay prompt.
337 338 339 340 341 |
# File 'lib/ollama_chat/personae_management.rb', line 337 def play_persona(pathname: nil) persona = choose_persona or return persona, persona_profile = load_persona_file(persona) play_persona_prompt(persona:, persona_profile:) end |
#play_persona_file(pathname) ⇒ Object (private)
Initiates roleplay with a persona from a specific file path.
Uses the pathname to identify the persona, reads its content, and generates the roleplay prompt.
349 350 351 352 353 |
# File 'lib/ollama_chat/personae_management.rb', line 349 def play_persona_file(pathname) persona = Pathname.new(pathname) persona_profile = pathname.read play_persona_prompt(persona:, persona_profile:) end |
#play_persona_prompt(persona:, persona_profile:) ⇒ String (private)
Generates the roleplay prompt string for a persona.
Creates a formatted prompt string that includes the persona name and profile.
326 327 328 329 330 331 |
# File 'lib/ollama_chat/personae_management.rb', line 326 def play_persona_prompt(persona:, persona_profile:) persona_name = persona.basename.sub_ext('') "Roleplay as persona %{persona_name} loaded from %{persona}\n\n%{persona_profile}" % { persona_name:, persona:, persona_profile: } end |
#reload_default_persona ⇒ Object (private)
Reloads the default persona file if one is set and not :none, prompting the user for confirmation before playing the persona file or loading a new default persona and changing the default.
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 107 |
# File 'lib/ollama_chat/personae_management.rb', line 73 def reload_default_persona 1.times do = [] if name = default_persona_name << SearchUI::Wrapper.new( 'reload_default', display: "Reload current default persona (#{name})" ) end << SearchUI::Wrapper.new( 'keep', display: "Keep it as‑is – do not load a persona" ) << SearchUI::Wrapper.new( 'choose_different', display: "Choose a different persona to become the new default and load it" ) choice = OllamaChat::Utils::Chooser.choose() case choice&.value when nil, 'keep' when 'reload_default' return play_persona_file(@default_persona) when 'choose_different' if persona = choose_persona @default_persona = personae_directory + persona return play_persona_file(@default_persona) else redo end end end nil end |
#setup_persona_from_opts ⇒ Object (private)
The setup_persona_from_opts method initializes persona setup by checking for a provided persona option, determining the appropriate file path, and playing the persona file if it exists.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ollama_chat/personae_management.rb', line 41 def setup_persona_from_opts @default_persona and return @opts[?c] and return if persona = @opts[?p].full? { Pathname.new(_1) } if persona.extname == '.md' pathname = persona else pathname = personae_directory + (persona.to_s + '.md') end if pathname.exist? @default_persona = pathname play_persona_file pathname end end ensure @default_persona ||= :none end |
#setup_personae_directory ⇒ Object (private)
Creates the personae directory structure if it doesn’t already exist.
This method ensures both the main personae directory and the backups subdirectory exist for proper file organization.
34 35 36 |
# File 'lib/ollama_chat/personae_management.rb', line 34 def setup_personae_directory FileUtils.mkdir_p personae_backup_directory end |