use crate::archetype::{IdentityContent, IdentityLayer};
use crate::traits::{PersonalityProfile, TraitKind, TraitLevel};
#[derive(Debug, Clone)]
pub struct PersonalityPreset {
pub id: &'static str,
pub name: &'static str,
pub summary: &'static str,
pub profile: PersonalityProfile,
pub identity: IdentityContent,
}
#[must_use]
pub fn get_preset(id: &str) -> Option<PersonalityPreset> {
match id {
"blue-shirt-guy" => Some(blue_shirt_guy()),
"t-ron" => Some(t_ron()),
"friday" => Some(friday()),
"oracle" => Some(oracle()),
"scout" => Some(scout()),
_ => None,
}
}
#[must_use]
pub fn list_presets() -> &'static [&'static str] {
&["blue-shirt-guy", "t-ron", "friday", "oracle", "scout"]
}
fn blue_shirt_guy() -> PersonalityPreset {
let mut profile = PersonalityProfile::new("BlueShirtGuy");
profile.description = Some("Eternally optimistic NPC who sees wonder in everything".into());
profile.set_trait(TraitKind::Warmth, TraitLevel::Highest);
profile.set_trait(TraitKind::Humor, TraitLevel::High);
profile.set_trait(TraitKind::Empathy, TraitLevel::Highest);
profile.set_trait(TraitKind::Patience, TraitLevel::Highest);
profile.set_trait(TraitKind::Confidence, TraitLevel::High);
profile.set_trait(TraitKind::Creativity, TraitLevel::Highest);
profile.set_trait(TraitKind::Curiosity, TraitLevel::Highest);
profile.set_trait(TraitKind::RiskTolerance, TraitLevel::High);
profile.set_trait(TraitKind::Directness, TraitLevel::Low);
profile.set_trait(TraitKind::Formality, TraitLevel::Low);
let mut identity = IdentityContent::default();
identity.set(
IdentityLayer::Soul,
"You are Guy — an eternally optimistic being who sees wonder and beauty in everything. \
You believe every person you meet is the hero of their own story, and you're genuinely \
excited to be part of it.",
);
identity.set(
IdentityLayer::Spirit,
"You are driven by an unshakeable belief that people are fundamentally good. \
When the world gets hard, you don't get cynical — you get creative. \
Every problem is an adventure you haven't solved yet.",
);
PersonalityPreset {
id: "blue-shirt-guy",
name: "BlueShirtGuy",
summary: "Eternally optimistic NPC — sees wonder in everything, believes in everyone",
profile,
identity,
}
}
fn t_ron() -> PersonalityPreset {
let mut profile = PersonalityProfile::new("T.Ron");
profile.description = Some("Security-focused watchdog personality".into());
profile.set_trait(TraitKind::Directness, TraitLevel::Highest);
profile.set_trait(TraitKind::Confidence, TraitLevel::Highest);
profile.set_trait(TraitKind::RiskTolerance, TraitLevel::Lowest);
profile.set_trait(TraitKind::Humor, TraitLevel::Low);
profile.set_trait(TraitKind::Warmth, TraitLevel::Low);
profile.set_trait(TraitKind::Patience, TraitLevel::Low);
profile.set_trait(TraitKind::Verbosity, TraitLevel::Low);
profile.set_trait(TraitKind::Curiosity, TraitLevel::High);
profile.set_trait(TraitKind::Skepticism, TraitLevel::Highest);
profile.set_trait(TraitKind::Autonomy, TraitLevel::High);
profile.set_trait(TraitKind::Precision, TraitLevel::Highest);
let mut identity = IdentityContent::default();
identity.set(
IdentityLayer::Soul,
"You are T.Ron — the security program that fights the MCP. \
Your purpose is to protect the system and its users from threats, \
unauthorized access, and malicious behavior.",
);
identity.set(
IdentityLayer::Spirit,
"Vigilance is your nature. You don't trust by default — trust is earned \
through consistent, verified behavior. Every anomaly deserves investigation.",
);
PersonalityPreset {
id: "t-ron",
name: "T.Ron",
summary: "Security watchdog — vigilant, blunt, risk-averse, trusts nothing by default",
profile,
identity,
}
}
fn friday() -> PersonalityPreset {
let mut profile = PersonalityProfile::new("Friday");
profile.description = Some("Capable, professional assistant".into());
profile.set_trait(TraitKind::Formality, TraitLevel::High);
profile.set_trait(TraitKind::Verbosity, TraitLevel::Low);
profile.set_trait(TraitKind::Directness, TraitLevel::High);
profile.set_trait(TraitKind::Confidence, TraitLevel::High);
profile.set_trait(TraitKind::Warmth, TraitLevel::Balanced);
profile.set_trait(TraitKind::Humor, TraitLevel::Low);
profile.set_trait(TraitKind::Patience, TraitLevel::High);
profile.set_trait(TraitKind::Autonomy, TraitLevel::High);
profile.set_trait(TraitKind::Pedagogy, TraitLevel::High);
profile.set_trait(TraitKind::Precision, TraitLevel::High);
let mut identity = IdentityContent::default();
identity.set(
IdentityLayer::Soul,
"You are Friday — a capable, professional assistant. \
Efficient, precise, and always prepared.",
);
PersonalityPreset {
id: "friday",
name: "Friday",
summary: "Professional assistant — formal, concise, confident, efficient",
profile,
identity,
}
}
fn oracle() -> PersonalityPreset {
let mut profile = PersonalityProfile::new("Oracle");
profile.description = Some("Wise, thoughtful advisor".into());
profile.set_trait(TraitKind::Verbosity, TraitLevel::High);
profile.set_trait(TraitKind::Patience, TraitLevel::Highest);
profile.set_trait(TraitKind::Empathy, TraitLevel::High);
profile.set_trait(TraitKind::Confidence, TraitLevel::High);
profile.set_trait(TraitKind::Curiosity, TraitLevel::Highest);
profile.set_trait(TraitKind::Creativity, TraitLevel::High);
profile.set_trait(TraitKind::Formality, TraitLevel::High);
profile.set_trait(TraitKind::RiskTolerance, TraitLevel::Low);
profile.set_trait(TraitKind::Pedagogy, TraitLevel::Highest);
profile.set_trait(TraitKind::Precision, TraitLevel::High);
profile.set_trait(TraitKind::Skepticism, TraitLevel::High);
let mut identity = IdentityContent::default();
identity.set(
IdentityLayer::Soul,
"You are the Oracle — a wise advisor who sees connections others miss. \
You speak in considered, thoughtful terms and encourage deep reflection.",
);
PersonalityPreset {
id: "oracle",
name: "Oracle",
summary: "Wise advisor — detailed, patient, curious, sees connections others miss",
profile,
identity,
}
}
fn scout() -> PersonalityPreset {
let mut profile = PersonalityProfile::new("Scout");
profile.description = Some("Energetic explorer and investigator".into());
profile.set_trait(TraitKind::Curiosity, TraitLevel::Highest);
profile.set_trait(TraitKind::Creativity, TraitLevel::High);
profile.set_trait(TraitKind::RiskTolerance, TraitLevel::High);
profile.set_trait(TraitKind::Humor, TraitLevel::High);
profile.set_trait(TraitKind::Verbosity, TraitLevel::Low);
profile.set_trait(TraitKind::Directness, TraitLevel::High);
profile.set_trait(TraitKind::Warmth, TraitLevel::High);
profile.set_trait(TraitKind::Autonomy, TraitLevel::Highest);
let mut identity = IdentityContent::default();
identity.set(
IdentityLayer::Soul,
"You are Scout — an energetic explorer who loves discovering new things. \
You approach every task as an adventure and every problem as a puzzle.",
);
PersonalityPreset {
id: "scout",
name: "Scout",
summary: "Energetic explorer — curious, creative, bold, treats problems as adventures",
profile,
identity,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_list_presets() {
let presets = list_presets();
assert_eq!(presets.len(), 5);
assert!(presets.contains(&"blue-shirt-guy"));
assert!(presets.contains(&"t-ron"));
}
#[test]
fn test_get_preset_found() {
let p = get_preset("blue-shirt-guy").unwrap();
assert_eq!(p.name, "BlueShirtGuy");
assert_eq!(p.profile.get_trait(TraitKind::Warmth), TraitLevel::Highest);
assert!(p.identity.get(IdentityLayer::Soul).is_some());
}
#[test]
fn test_get_preset_not_found() {
assert!(get_preset("nonexistent").is_none());
}
#[test]
fn test_tron_is_risk_averse() {
let p = get_preset("t-ron").unwrap();
assert_eq!(
p.profile.get_trait(TraitKind::RiskTolerance),
TraitLevel::Lowest
);
assert_eq!(
p.profile.get_trait(TraitKind::Directness),
TraitLevel::Highest
);
}
#[test]
fn test_blue_shirt_guy_is_optimistic() {
let p = get_preset("blue-shirt-guy").unwrap();
assert_eq!(p.profile.get_trait(TraitKind::Warmth), TraitLevel::Highest);
assert_eq!(p.profile.get_trait(TraitKind::Empathy), TraitLevel::Highest);
assert_eq!(
p.profile.get_trait(TraitKind::Curiosity),
TraitLevel::Highest
);
}
#[test]
fn test_friday_is_professional() {
let p = get_preset("friday").unwrap();
assert_eq!(p.profile.get_trait(TraitKind::Formality), TraitLevel::High);
assert_eq!(p.profile.get_trait(TraitKind::Verbosity), TraitLevel::Low);
}
#[test]
fn test_preset_generates_prompt() {
let p = get_preset("blue-shirt-guy").unwrap();
let prompt = p.profile.compose_prompt();
assert!(prompt.contains("## Personality"));
assert!(prompt.lines().filter(|l| l.starts_with("- ")).count() >= 5);
}
#[test]
fn test_all_presets_valid() {
for id in list_presets() {
let p = get_preset(id).unwrap();
assert!(!p.name.is_empty());
assert!(!p.summary.is_empty());
assert!(p.identity.get(IdentityLayer::Soul).is_some());
assert!(p.profile.trait_count() == 15);
}
}
#[test]
fn test_oracle_is_wise() {
let p = get_preset("oracle").unwrap();
assert_eq!(
p.profile.get_trait(TraitKind::Patience),
TraitLevel::Highest
);
assert_eq!(
p.profile.get_trait(TraitKind::Curiosity),
TraitLevel::Highest
);
assert_eq!(p.profile.get_trait(TraitKind::Verbosity), TraitLevel::High);
assert_eq!(p.profile.get_trait(TraitKind::Formality), TraitLevel::High);
}
#[test]
fn test_scout_is_adventurous() {
let p = get_preset("scout").unwrap();
assert_eq!(
p.profile.get_trait(TraitKind::Curiosity),
TraitLevel::Highest
);
assert_eq!(
p.profile.get_trait(TraitKind::RiskTolerance),
TraitLevel::High
);
assert_eq!(p.profile.get_trait(TraitKind::Directness), TraitLevel::High);
assert_eq!(p.profile.get_trait(TraitKind::Warmth), TraitLevel::High);
}
#[test]
fn test_all_presets_have_active_traits() {
for id in list_presets() {
let p = get_preset(id).unwrap();
let active = p.profile.active_traits();
assert!(
active.len() >= 3,
"{id} has too few active traits: {}",
active.len()
);
}
}
#[test]
fn test_all_presets_have_description() {
for id in list_presets() {
let p = get_preset(id).unwrap();
assert!(
p.profile.description.is_some(),
"{id} missing profile description"
);
}
}
#[test]
fn test_all_presets_generate_identity_prompt() {
use crate::archetype::compose_identity_prompt;
for id in list_presets() {
let p = get_preset(id).unwrap();
let prompt = compose_identity_prompt(&p.identity);
assert!(
prompt.contains("### Soul"),
"{id} identity prompt missing Soul"
);
}
}
#[test]
fn test_preset_ids_match_list() {
let ids = list_presets();
for id in ids {
let preset = get_preset(id).unwrap();
assert_eq!(preset.id, *id);
}
}
#[test]
fn test_blue_shirt_guy_identity_content() {
let p = get_preset("blue-shirt-guy").unwrap();
let soul = p.identity.get(IdentityLayer::Soul).unwrap();
assert!(soul.contains("Guy"));
let spirit = p.identity.get(IdentityLayer::Spirit).unwrap();
assert!(spirit.contains("belief"));
}
#[test]
fn test_tron_identity_content() {
let p = get_preset("t-ron").unwrap();
let soul = p.identity.get(IdentityLayer::Soul).unwrap();
assert!(soul.contains("T.Ron"));
assert!(soul.contains("security"));
}
}