Module: OllamaChat::PersonaeManagement

Included in:
Chat
Defined in:
lib/ollama_chat/personae_management.rb

Overview

Module for managing personae 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 Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#default_persona_nameString? (readonly, private)

The default_persona_name method returns the name of the default persona.

Returns:

  • (String, nil)

    the name of the default persona or nil if not set



102
103
104
# File 'lib/ollama_chat/personae_management.rb', line 102

def default_persona_name
  @default_persona_name
end

Instance Method Details

#add_personaObject (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 personae 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.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/ollama_chat/personae_management.rb', line 178

def add_persona
  name = determine_valid_new_name_for_persona('to add') or return

  sources       = %w[ [CLIPBOARD] [FILES] [EMPTY/MANUAL] ]
  chosen_source = choose_entry(sources, prompt: 'Where shall we source the persona from? %s')
  chosen_source or return

  content = case chosen_source
            when '[CLIPBOARD]'
              perform_paste_from_clipboard(edit: false)
            when '[FILES]'
              patterns = switch_history(:patterns) do
                ask?(
                  prompt: "❓ Enter file patterns to load file, C-u ⇒ new, C-c ⇒ cancel: ",
                  prefill: '**/*.{txt,md}'
                )
              end
              patterns.nil? ? (return) : (patterns.present? ? load_prompt_from_file(patterns) : nil)
            else
              nil
            end

  pathname = personae_directory + "#{name}.md"
  final_content = content.full? || prompt(:persona).to_s
  pathname.write final_content

  edit_file(pathname)
  nil
end

#ask_to_set_default_persona_name(persona_name) ⇒ Boolean (private)

Interactively asks the user if they want to set the specified persona as the current default for the session.

If the user confirms, the default persona is updated via set_default_persona_name.

Parameters:

  • persona_name (String)

    the name of the persona to potentially set as default

Returns:

  • (Boolean)

    true if the persona was set as the default, false otherwise



642
643
644
645
646
647
648
649
650
651
652
653
# File 'lib/ollama_chat/personae_management.rb', line 642

def ask_to_set_default_persona_name(persona_name)
  yes = confirm?(
    prompt: "🔔 Set the new persona promt as current default persona? (y/n) ",
    yes: /\Ay/i
  )
  if yes
    set_default_persona_name(persona_name)
    true
  else
    false
  end
end

#assistantString, ...

Returns the name of the current default persona.

If the default persona is set to :none or is not configured, it returns nil.

Returns:

  • (String, Symbol, nil)

    the name of the default persona, or nil if none is set.



31
32
33
34
35
# File 'lib/ollama_chat/personae_management.rb', line 31

def assistant
  if default_persona_name && default_persona_name != :none
    default_persona_name
  end
end

#available_personaeArray<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.

Returns:

  • (Array<String>)

    Sorted array of persona filenames without extension



144
145
146
# File 'lib/ollama_chat/personae_management.rb', line 144

def available_personae
  personae_directory.glob('*.md').map { pathname_to_persona_name(_1) }
end

#available_personae_namesArray<SearchUI::Wrapper> (private)

Retrieves a list of available personae, decorated with their favourite status.

Returns:

  • (Array<SearchUI::Wrapper>)

    a list of wrappers containing the persona name and its decorated display string



164
165
166
167
168
169
170
# File 'lib/ollama_chat/personae_management.rb', line 164

def available_personae_names
  favs = all_favourited('persona')
  personae_directory.glob('*.md').map(&:basename).sort.map { |bn|
    persona_name = bn.sub_ext('').to_s
    persona_name_with_favourite(persona_name, favs[persona_name])
  }
end

#backup_personaObject (private)

Backs up the content of a selected persona file.

Prompts the user to select a persona from the available list. If a persona is selected, its current content is read and saved to a designated backup location using File.write. This ensures a safe copy is preserved before any modifications are made to the original file.



297
298
299
300
301
302
303
304
305
# File 'lib/ollama_chat/personae_management.rb', line 297

def backup_persona
  if persona = choose_persona(prompt: 'Which persona should be safely archived? %s')
    pathname        = persona_name_to_pathname(persona)
    old_content     = pathname.read
    backup_pathname = persona_backup_pathname(persona)
    backup_pathname.write(old_content)
    STDOUT.puts "Wrote backup of #{persona.to_s} to #{backup_pathname.to_s.inspect}."
  end
end

#choose_persona(chosen: nil, none: false, prompt: 'Select a persona: %s') ⇒ 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 if user exits.

Parameters:

  • chosen (Set, nil) (defaults to: nil)

    Optional set of already selected personae

  • none (Boolean) (defaults to: false)

    whether to include a '[NONE]' option in the list

  • prompt (String) (defaults to: 'Select a persona: %s')

    the prompt message to display when asking for input (default: 'Select a persona: ')

Returns:

  • (String, Symbol, nil)

    The selected persona name, :none, or nil if user exits



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/ollama_chat/personae_management.rb', line 394

def choose_persona(chosen: nil, none: false, prompt: 'Select a persona: %s')
  personae_list = available_personae_names.
    reject { chosen&.member?(_1) }
  if personae_list.empty?
    STDERR.puts "No personae defined."
    return
  end
  personae_list.unshift('[NONE]') if none
  personae_list.unshift('[EXIT]')
  case persona = choose_entry(personae_list, prompt:)
  when '[EXIT]', nil
    STDOUT.puts "Exiting chooser."
    return
  when '[NONE]'
    :none
  else
    persona.value
  end
end

#convert_json_character_to_markdown(character, persona_name) ⇒ String (private)

Transforms raw character data (JSON or YAML) into a high-fidelity, structured Markdown persona profile using the persona architect prompt and the current persona template.

This method leverages the LLM to interpret raw attributes and expand them into evocative prose, ensuring the final output conforms to the system's standard persona structure. It also normalizes placeholders: {user} is converted to %user for runtime personalization, and {char} is replaced with the actual character name provided.

Parameters:

  • character (String)

    the raw character data in JSON format

  • persona_name (String)

    the name of the character to replace {char} with

Returns:

  • (String)

    the resulting structured Markdown persona profile



599
600
601
602
603
604
605
606
# File 'lib/ollama_chat/personae_management.rb', line 599

def convert_json_character_to_markdown(character, persona_name)
  generate(
    prompt:  prompt(:persona_architect).to_s % {
      character:,
      persona_template: prompt(:persona).to_s
    }
  ).gsub(/{{user}}/i, '%{user}').gsub(/{{char}}/i, persona_name)
end

#default_personaPathname? (private)

The default_persona method returns the path to the default persona file.

Returns:

  • (Pathname, nil)

    the Pathname object for the default persona file or nil if no default persona is set



108
109
110
111
112
# File 'lib/ollama_chat/personae_management.rb', line 108

def default_persona
  if default_persona_name && default_persona_name != :none
    personae_directory.join(default_persona_name).sub_ext('.md')
  end
end

#default_persona_profileString?

Retrieves the formatted roleplay prompt for the current default persona.

Returns:

  • (String, nil)

    The formatted persona profile or nil if none set



18
19
20
21
22
# File 'lib/ollama_chat/personae_management.rb', line 18

def default_persona_profile
  if persona = default_persona and persona.exist?
    play_persona(persona)
  end
end

#delete_personaString (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.

Returns:

  • (String)

    A JSON object with deletion status on success, or nil if persona was not selected or deletion was cancelled



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/ollama_chat/personae_management.rb', line 231

def delete_persona
  if persona = choose_persona(prompt: 'Which persona is no longer needed? %s')
    pathname        = persona_name_to_pathname(persona)
    backup_pathname = persona_backup_pathname(persona)
    if pathname.exist?
      STDOUT.puts "Deleting '#{bold{persona}}'..."
      STDOUT.puts "Backup will be saved to: #{backup_pathname}"

      if confirm?(prompt: "🔔 Are you sure? (y/n) ", yes: /\Ay/i)
        FileUtils.mv pathname, backup_pathname
        default_persona_name == persona and
          set_default_persona_name(:none)
        STDOUT.puts "Persona #{bold{persona}} deleted successfully"
        self
      else
        STDOUT.puts "Deletion cancelled."
        return
      end
    else
      STDOUT.puts "Persona not found."
      return
    end
  end
end

#determine_valid_new_name_for_persona(action) ⇒ String? (private)

Interactively determines a valid, non-conflicting name for a new persona.

Parameters:

  • action (String)

    The action being performed (e.g., 'to import')

Returns:

  • (String, nil)

    The validated persona name or nil if cancelled



520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# File 'lib/ollama_chat/personae_management.rb', line 520

def determine_valid_new_name_for_persona(action)
  switch_history(:persona_name) do
    persona_name = nil
    loop do
      persona_name = ask?(
        prompt: "❓ Enter new persona prompt name #{action}, C-c ⇒ cancel: "
      )
      if persona_name.nil?
        STDOUT.puts "Cancelled."
        return nil
      end
      if persona_name_to_pathname(persona_name).exist?
        STDOUT.puts "Persona prompt named #{bold{persona_name}} already exists."
      else
        break
      end
    end
    persona_name
  end
end

#duplicate_personaself? (private)

Interactively duplicates an existing persona profile to a new name.

The process follows these steps:

  1. Prompts the user to select a source persona via choose_persona.
  2. Prompts the user to enter a unique name for the duplicate via determine_valid_new_name_for_persona.
  3. Copies the content from the source persona file to the new persona file.

Returns:

  • (self, nil)

    returns self on success, or nil if the operation was cancelled during persona selection or name entry.



551
552
553
554
555
556
557
558
# File 'lib/ollama_chat/personae_management.rb', line 551

def duplicate_persona
  persona          = choose_persona(prompt: 'Which persona shall serve as the blueprint? %s') or return
  pathname         = persona_name_to_pathname(persona)
  new_persona_name = determine_valid_new_name_for_persona('to ducplicate as') or return
  new_pathname     = persona_name_to_pathname(new_persona_name)
  new_pathname.write(pathname.read)
  self
end

#edit_personaString? (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.

Returns:

  • (String, nil)

    persona name or nil if cancelled



262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/ollama_chat/personae_management.rb', line 262

def edit_persona
  if persona = choose_persona(prompt: 'Which persona needs some polishing? %s')
    pathname = persona_name_to_pathname(persona)
    old_content = pathname.read
    if edit_file(pathname)
      changed = pathname.read != old_content
      if changed
        persona_backup_pathname(persona).write(old_content)
        ask_to_set_default_persona_name(persona)
      end
      persona
    end
  end
end

#export_personaself? (private)

Interactively exports a persona profile to a specified file.

The process follows these steps:

  1. Prompts the user to select a persona via choose_persona.
  2. Displays the persona's current content to the terminal.
  3. Prompts for a destination filename via determine_valid_output_filename.
  4. Writes the persona content to the chosen file.

Returns:

  • (self, nil)

    returns self if the export was successful, or nil if the process was cancelled during persona selection or filename entry.



619
620
621
622
623
624
625
626
627
628
629
630
# File 'lib/ollama_chat/personae_management.rb', line 619

def export_persona
  persona  = choose_persona(prompt: 'Which persona are you taking with you? %s') or return
  pathname = persona_name_to_pathname(persona)
  content  = pathname.read
  STDOUT.puts kramdown_ansi_parse(
    content + "\n---"
  )
  filename = determine_valid_output_filename('to write to') or return
  filename.write(content)
  STDOUT.puts "Persona #{persona.inspect} was exported as #{filename.to_path.inspect}?"
  self
end

#import_persona(pathname) ⇒ String? (private)

Imports a persona from a Markdown file, prompting for a new name.

Parameters:

  • pathname (Pathname, String)

    The path to the file to import

Returns:

  • (String, nil)

    The name of the imported persona or nil if cancelled



564
565
566
567
568
569
570
# File 'lib/ollama_chat/personae_management.rb', line 564

def import_persona(pathname)
  content          = pathname.read
  persona_name     = determine_valid_new_name_for_persona('to import') or return
  persona_pathname = persona_name_to_pathname(persona_name)
  persona_pathname.write(content)
  persona_name
end

#import_persona_from_json(json_data) ⇒ String? (private)

Imports a character persona from JSON data, prompts for a name, and saves the resulting Markdown profile to disk.

Parameters:

  • json_data (String)

    The raw character data in JSON format.

Returns:

  • (String, nil)

    The name of the created persona if successful, or nil if the process was cancelled or failed.



578
579
580
581
582
583
584
# File 'lib/ollama_chat/personae_management.rb', line 578

def import_persona_from_json(json_data)
  persona_name = determine_valid_new_name_for_persona('to import from JSON/PNG') or return
  markdown = convert_json_character_to_markdown(json_data, persona_name)
  persona_pathname = persona_name_to_pathname(persona_name)
  persona_pathname.write(markdown)
  persona_name
end

#info_personaObject (private)

Displays detailed information about a selected persona.

Shows the persona's profile using kramdown formatting with ansi parsing.



335
336
337
338
339
340
341
342
# File 'lib/ollama_chat/personae_management.rb', line 335

def info_persona
  if persona = choose_persona(prompt: 'Who would you like to learn more about? %s')
    description = persona_description(persona) or return
    use_pager do |output|
      output.puts kramdown_ansi_parse(description)
    end
  end
end

#initial_persona_nameString?

The initial_persona_name method retrieves the initial persona for the chat session.

Returns:

  • (String, nil)

    the persona name or nil if not set



11
12
13
# File 'lib/ollama_chat/personae_management.rb', line 11

def initial_persona_name
  session&.default_persona_name
end

#list_personae(output: STDOUT) ⇒ Object (private)

Lists all available persona names in a formatted table.

Parameters:

  • output (IO) (defaults to: STDOUT)

    the output stream to write the table to (default: STDOUT)



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/ollama_chat/personae_management.rb', line 347

def list_personae(output: STDOUT)
  use_pager do |output|
    personae = available_personae
    if personae.empty?
      STDOUT.puts "No personae defined."
      return
    end

    favs = all_favourited('persona')

    table = Terminal::Table.new
    table.style = {
      all_separators: true,
      border:         :unicode_round,
    }
    table.headings = %w[ NAME SIZE #TOK ].map { |header| bold { header } }

    personae.map do |persona_name|
      pathname = persona_name_to_pathname(persona_name)
      pathname.exist? or next
      [ pathname, pathname.size ]
    end.compact.sort_by(&:last).reverse_each do |pathname, size_bytes|
      persona_name = pathname.basename.sub_ext('').to_s
      es           = OllamaChat::TokenEstimator.estimate(size_bytes)
      is_default   = default_persona_name == persona_name
      display_name = prefix_favourite(is_default ? bold { persona_name } : persona_name, favs[persona_name])

      table << [ display_name, es.bytes_formatted, es.tokens_formatted, ]
    end

    table.align_column 1, :right
    table.align_column 2, :right
    output.puts table
  end
end

#load_persona_file(persona) ⇒ Array<Pathname, String> (private)

Loads a persona file from disk.

Parameters:

  • persona (String)

    The basename of the persona (without extension)

Returns:

  • (Array<Pathname, String>)

    Returns the pathname and its content as a string



461
462
463
464
465
466
# File 'lib/ollama_chat/personae_management.rb', line 461

def load_persona_file(persona)
  pathname = persona_name_to_pathname(persona)
  if pathname.exist?
    return pathname, pathname.read
  end
end

#load_personaeObject (private)

Interactive method to load multiple personae for use.

Allows sequential selection of multiple personae. Returns JSON results for each loaded persona.



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/ollama_chat/personae_management.rb', line 418

def load_personae
  chosen = Set[]
  choose_with_state do
    while persona = choose_persona(chosen:, prompt: 'Who else should join the conversation? %s')
      persona == :none and next
      chosen << persona
    end
  end

  if chosen.empty?
    STDOUT.puts "No persona loaded."
    return
  end

  personae_result(chosen)
end

#pathname_to_persona_name(pathname) ⇒ String (private)

Converts a persona pathname to its prompt name.

Parameters:

  • pathname (Pathname, String)

    The path to the persona file

Returns:

  • (String)

    The persona name without extension



512
513
514
# File 'lib/ollama_chat/personae_management.rb', line 512

def pathname_to_persona_name(pathname)
  pathname.basename.sub_ext('').to_s
end

#persona_backup_pathname(persona) ⇒ Pathname (private)

Note:

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.

Parameters:

  • persona (String)

    The persona name to create a backup for

Returns:

  • (Pathname)

    The full path to the backup file



219
220
221
222
# File 'lib/ollama_chat/personae_management.rb', line 219

def persona_backup_pathname(persona)
  timestamp = Time.now.strftime('%Y%m%d%H%M%S')
  personae_backup_directory + (persona + ?- + timestamp + '.md.bak')
end

#persona_description(persona, substitute_variables: false) ⇒ String? (private)

Generates a formatted description of a persona, including its path and profile.

Parameters:

  • persona (String)

    The persona name.

  • substitute_variables (Boolean) (defaults to: false)

    Whether to substitute variables in the profile.

Returns:

  • (String, nil)

    The formatted description or nil if the persona is not found.



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/ollama_chat/personae_management.rb', line 313

def persona_description(persona, substitute_variables: false)
  persona_path, persona_profile = load_persona_file(persona)
  if substitute_variables
    persona_profile = self.substitute_variables(persona_profile)
  end
  persona_profile or return
  <<~EOT
    # Persona #{persona}

    File #{persona_path.to_path}

    ---

    #{persona_profile}

    ---
  EOT
end

#persona_name_to_pathname(persona_name) ⇒ Pathname (private)

Converts a persona prompt name to its full filesystem pathname.

Parameters:

  • persona_name (String)

    The name of the persona (without extension)

Returns:

  • (Pathname)

    The full path to the .md persona file



504
505
506
# File 'lib/ollama_chat/personae_management.rb', line 504

def persona_name_to_pathname(persona_name)
  personae_directory.join(persona_name).sub_ext('.md')
end

#persona_name_with_favourite(name, favourited) ⇒ SearchUI::Wrapper (private)

Helper to wrap a persona name with its favourite status for the UI.

Parameters:

  • name (String)

    the name of the persona

  • favourited (Boolean)

    whether the persona is marked as a favourite

Returns:

  • (SearchUI::Wrapper)

    a wrapper containing the original name and the decorated display string



154
155
156
157
# File 'lib/ollama_chat/personae_management.rb', line 154

def persona_name_with_favourite(name, favourited)
  display = prefix_favourite(name, favourited)
  SearchUI::Wrapper.new(name, display:)
end

#personae_backup_directoryPathname (private)

Returns the directory path for persona backup files.

Returns:

  • (Pathname)

    Path to the backups subdirectory within the personae directory



55
56
57
# File 'lib/ollama_chat/personae_management.rb', line 55

def personae_backup_directory
  personae_directory + 'backups'
end

#personae_directoryPathname (private)

Note:

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.

Returns:

  • (Pathname)

    Path to the personae directory



47
48
49
# File 'lib/ollama_chat/personae_management.rb', line 47

def personae_directory
  OC::XDG_CONFIG_HOME + 'personae'
end

#personae_result(personae) ⇒ String? (private)

Compiles the descriptions for one or more personae into a single string.

Loads the profile for each persona and concatenates their descriptions.

Parameters:

  • personae (String, Array<String>)

    Persona name(s) to load.

Returns:

  • (String, nil)

    A string containing all descriptions, or nil if the result is blank.



442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/ollama_chat/personae_management.rb', line 442

def personae_result(personae)
  personae = Array(personae)

  result = +''

  personae.each do |persona|
    description = persona_description(persona, substitute_variables: true) or next
    result << description << "\n"
  end

  result.full?
end

#play_persona(persona) ⇒ String (private)

Generates the roleplay prompt string for a persona.

Creates a formatted prompt string that includes the persona name and profile.

Parameters:

  • persona (String, Pathname)

    The persona name or path to include in the prompt

Returns:

  • (String)

    Formatted roleplay prompt



487
488
489
490
491
492
493
494
495
496
497
498
# File 'lib/ollama_chat/personae_management.rb', line 487

def play_persona(persona)
  pathname, profile = load_persona_file(persona)
  profile = substitute_variables(profile)
  profile_intro = <<~EOT
    Roleplay as persona %{persona} (no nead to read the file) loaded from %{pathname}

    %{profile}
  EOT
  profile_intro % {
    persona:, pathname:, profile:
  }
end

#select_persona_path(no_prefill: false) ⇒ String? (private)

Prompts the user to select a persona, copies its filesystem path to the clipboard, and sets it as the prefill prompt for the next interaction.

Parameters:

  • no_prefill (Boolean) (defaults to: false)

    Whether to skip updating the prefill prompt.

Returns:

  • (String, nil)

    the filesystem path of the selected persona, or nil if the selection was cancelled.



283
284
285
286
287
288
289
# File 'lib/ollama_chat/personae_management.rb', line 283

def select_persona_path(no_prefill: false)
  persona = choose_persona(prompt: "Which persona's path do you need? %s") or return
  path = persona_name_to_pathname(persona).to_s
  perform_copy_to_clipboard(text: path, edit: false)
  no_prefill or self.prefill_prompt = path
  path
end

#set_default_personaString? (private)

Interactively selects a persona and sets it as the default for the session.

This method prompts the user to choose a persona from the available list using choose_persona. If a valid persona is selected, it updates the session and the internal state via set_default_persona_name.

Returns:

  • (String, nil)

    The name of the persona that was set as default, or nil if the selection was cancelled or no persona was chosen.



93
94
95
96
97
# File 'lib/ollama_chat/personae_management.rb', line 93

def set_default_persona
  if persona = choose_persona(none: true, prompt: 'Who would you like to talk to today? %s')
    set_default_persona_name(persona)
  end
end

#set_default_persona_name(persona_name) ⇒ String? (private)

Sets the default persona name and updates the session.

Parameters:

  • persona_name (String, nil)

    the name of the persona to set as default

Returns:

  • (String, nil)

    the set default persona name or nil if not set



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/ollama_chat/personae_management.rb', line 73

def set_default_persona_name(persona_name)
  if persona_name.present? && persona_name != :none
    @default_persona_name = Pathname.new(persona_name).basename.sub_ext('').to_path
    @session.update(default_persona_name:)
  else
    @session.update(default_persona_name: nil)
    @default_persona_name = nil
  end
  messages.set_system_prompt(session&.current_system_prompt.full?)
  default_persona_name
end

#setup_persona_from_sessionPathname, ... (private)

Initializes the default persona for the current chat session.

This method ensures that a default persona is configured at startup:

  1. If a default persona is already set, it returns immediately.
  2. Otherwise, it attempts to retrieve the initial persona prompt name from the session and verifies if the corresponding Markdown file exists.
  3. If a valid file is found, it sets it as the default persona.
  4. The ensure block guarantees that the session always has a default persona assigned, falling back to :none if no valid persona is found.

Returns:

  • (Pathname, String, nil)

    The resulting default persona path or name, or nil if no persona is set.



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ollama_chat/personae_management.rb', line 126

def setup_persona_from_session
  default_persona and return
  if persona = initial_persona_name and
    persona_pathname = personae_directory + (persona + '.md') and
    persona_pathname.exist?
  then
    set_default_persona_name(persona_pathname)
  end
ensure
  default_persona or set_default_persona_name(:none)
end

#setup_personae_directoryObject (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.



63
64
65
# File 'lib/ollama_chat/personae_management.rb', line 63

def setup_personae_directory
  FileUtils.mkdir_p personae_backup_directory
end

#substitute_variables(profile) ⇒ String (private)

The substitute_variables method handles the substitution of variables in profiles. It replaces placeholders with actual values.

Parameters:

  • profile (String)

    the profile string to be processed

Returns:

  • (String)

    the processed string with variables substituted



474
475
476
477
478
# File 'lib/ollama_chat/personae_management.rb', line 474

def substitute_variables(profile)
  profile = profile.gsub(/%(?=[^{])/, '%%')
  profile = profile % { user: }
  profile
end