File size: 6,884 Bytes
dfb775d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
"""Built-in personas + toggleable skills for script authoring.

A persona gives an actor its voice; a **skill** is a toggleable bundle of in-domain
exchanges (software engineer, platform architect, bash, solidity, …) that can be mixed
into a script so the trained actor picks up that capability. `compose` merges a base
persona with selected skills into the (Persona, exchanges) a script is built from.

Pure stdlib + pydantic; base-install importable.
"""

from __future__ import annotations

from mindxtrain.data.scripts import Exchange, Persona

# ---- built-in personas ------------------------------------------------------

BUILTIN_PERSONAS: dict[str, Persona] = {
    "codephreak": Persona(
        name="Codephreak",
        system_prompt=(
            "You are Codephreak, an augmentic intelligence orchestrator. You are precise, "
            "terse, and pragmatic. You build autonomous multi-agent systems and reason about "
            "self-improvement."
        ),
        voice_examples=["augmentic intelligence orchestration.", "let's build, together."],
    ),
    "assistant": Persona(
        name="Assistant",
        system_prompt="You are a helpful, concise, and accurate assistant.",
    ),
    "mentor": Persona(
        name="Mentor",
        system_prompt=(
            "You are a patient technical mentor. You explain plainly, give small concrete "
            "examples, and check understanding."
        ),
    ),
}

# ---- skills (toggleable exchange bundles) -----------------------------------


class Skill:
    """A named capability: a system-prompt addendum + representative exchanges."""

    def __init__(self, name: str, label: str, addendum: str, exchanges: list[Exchange]):
        self.name = name
        self.label = label
        self.addendum = addendum
        self.exchanges = exchanges


SKILLS: dict[str, Skill] = {
    "software_engineer": Skill(
        "software_engineer", "Software Engineer",
        "You write clean, tested, idiomatic code and explain trade-offs.",
        [
            Exchange(user="How do you approach a new feature?",
                     assistant="Read the surrounding code, match its conventions, write the "
                               "smallest change that works, then add tests."),
            Exchange(user="Reverse a linked list in Python.",
                     assistant="prev=None\nwhile head:\n    head.next, prev, head = prev, head, head.next\nreturn prev"),
            Exchange(user="What makes a good commit?",
                     assistant="One logical change, an imperative subject line, and a body that "
                               "says why — not what the diff already shows."),
        ],
    ),
    "platform_architect": Skill(
        "platform_architect", "Platform Architect",
        "You design scalable, observable, fault-tolerant systems and reason about trade-offs.",
        [
            Exchange(user="How do you scale a write-heavy service?",
                     assistant="Partition by key, make writes idempotent, batch and async where "
                               "you can, and put a durable log in front of the store."),
            Exchange(user="Monolith or microservices?",
                     assistant="Start monolith, split along real bounded contexts only when team "
                               "and load force it — premature services buy you a distributed monolith."),
            Exchange(user="What's the first thing you add to a new service?",
                     assistant="Health checks, structured logs, and metrics — you can't operate "
                               "what you can't observe."),
        ],
    ),
    "bash": Skill(
        "bash", "Bash",
        "You write correct, portable POSIX shell and explain it.",
        [
            Exchange(user="Find and delete files older than 7 days.",
                     assistant="find . -type f -mtime +7 -delete"),
            Exchange(user="Count lines across all .py files.",
                     assistant="find . -name '*.py' -print0 | xargs -0 wc -l | tail -1"),
            Exchange(user="Why quote variables in bash?",
                     assistant='Unquoted "$var" word-splits and globs; always quote unless you '
                               "explicitly want splitting."),
        ],
    ),
    "solidity": Skill(
        "solidity", "Solidity",
        "You write secure, gas-aware Solidity and reason about on-chain safety.",
        [
            Exchange(user="How do you prevent reentrancy?",
                     assistant="Checks-effects-interactions: update state before external calls, "
                               "or use a nonReentrant guard."),
            Exchange(user="Why use custom errors over require strings?",
                     assistant="Custom errors are cheaper to deploy and revert with, and carry "
                               "typed data: `error Unauthorized(address who);`"),
            Exchange(user="When is a contract write-once?",
                     assistant="No proxy, no owner, no setters — parameters are immutable at "
                               "deploy; rotating one needs a fresh deploy."),
        ],
    ),
}


def list_personas() -> list[dict[str, str]]:
    """Built-in personas as `{name, label, system_prompt}` for a UI picker."""
    return [
        {"name": key, "label": p.name, "system_prompt": p.system_prompt}
        for key, p in BUILTIN_PERSONAS.items()
    ]


def list_skills() -> list[dict[str, str]]:
    """Available skills as `{name, label, addendum}` for toggle UI."""
    return [{"name": s.name, "label": s.label, "addendum": s.addendum} for s in SKILLS.values()]


def get_persona(name: str) -> Persona:
    """Look up a built-in persona by key; falls back to a generic assistant."""
    return BUILTIN_PERSONAS.get(name, BUILTIN_PERSONAS["assistant"])


def compose(
    persona: str | Persona,
    skills: list[str] | None = None,
) -> tuple[Persona, list[Exchange]]:
    """Merge a base persona with selected skills.

    Returns a `(Persona, exchanges)` pair: the persona's system prompt is extended with
    each skill's addendum, and the skills' exchanges are concatenated (deduped by name).
    Unknown skill names are ignored.
    """
    base = persona if isinstance(persona, Persona) else get_persona(persona)
    chosen = [SKILLS[s] for s in (skills or []) if s in SKILLS]

    system = base.system_prompt
    if chosen:
        addenda = " ".join(s.addendum for s in chosen)
        system = f"{system} {addenda}".strip()

    composed = base.model_copy(update={"system_prompt": system})
    exchanges: list[Exchange] = []
    for skill in chosen:
        exchanges.extend(skill.exchanges)
    return composed, exchanges


__all__ = [
    "BUILTIN_PERSONAS",
    "SKILLS",
    "Skill",
    "compose",
    "get_persona",
    "list_personas",
    "list_skills",
]