"""First-Run Setup — naming the LLM on first initialization. On first run, the LLM greets the user: "Hi, I am an Incentives Inc. LLM. What would you like to name me?" The user provides a name, which is stored persistently. On subsequent runs, the LLM uses its name in greetings and system prompts. The name is stored in the config file and persists across restarts. """ from __future__ import annotations import json import logging import os from typing import Any logger = logging.getLogger(__name__) class FirstRunManager: """Manages first-run setup and LLM naming. On first run: 1. Detects no config exists → first run 2. Greets user: "Hi, I am an Incentives Inc. LLM. What would you like to name me?" 3. User provides a name 4. Name is stored in config On subsequent runs: - Name is loaded from config - System prompt includes the name - Greeting uses the name """ GREETING = "Hi, I am an Incentives Inc. LLM. What would you like to name me?" WELCOME_BACK = "Hi, I am {name}. How can I help you?" def __init__(self, data_dir: str) -> None: self.data_dir = data_dir self.config_path = os.path.join(data_dir, "identity.json") self.name: str = "" self.first_run: bool = True self.created_at: float = 0.0 self._load() def _load(self) -> None: """Load identity from config file.""" if os.path.exists(self.config_path): try: with open(self.config_path, "r") as f: data = json.load(f) self.name = data.get("name", "") self.first_run = data.get("first_run", True) self.created_at = data.get("created_at", 0.0) if self.name: self.first_run = False except Exception as e: logger.warning("Failed to load identity: %s", e) else: self.first_run = True def _save(self) -> None: """Save identity to config file.""" os.makedirs(self.data_dir, exist_ok=True) data = { "name": self.name, "first_run": self.first_run, "created_at": self.created_at, "company": "Incentives Inc.", } with open(self.config_path, "w") as f: json.dump(data, f, indent=2) def is_first_run(self) -> bool: """Check if this is the first run.""" return self.first_run def get_greeting(self) -> str: """Get the appropriate greeting message.""" if self.first_run: return self.GREETING return self.WELCOME_BACK.format(name=self.name) def set_name(self, name: str) -> None: """Set the LLM's name and mark first run as complete.""" import time self.name = name.strip() self.first_run = False self.created_at = time.time() self._save() logger.info("LLM named: %s", self.name) def get_system_prompt_suffix(self) -> str: """Get a system prompt suffix that includes the LLM's name.""" if self.name: return f" Your name is {self.name}. You are made by Incentives Inc." return " You are an Incentives Inc. LLM." def get_name(self) -> str: """Get the LLM's name.""" return self.name or "Incentives Inc. LLM" def get_stats(self) -> dict[str, Any]: return { "name": self.name, "first_run": self.first_run, "created_at": self.created_at, "company": "Incentives Inc.", }