File size: 3,605 Bytes
0e3d4b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
107
108
109
110
111
112
"""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.",
        }