-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsoul.py
More file actions
135 lines (109 loc) · 6.07 KB
/
soul.py
File metadata and controls
135 lines (109 loc) · 6.07 KB
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
"""Sovereign — Soul Layer: the systems that make a someone.
Coordinates all soul subsystems:
- Reflexes: instant responses before the brain engages
- Relationship: trust that deepens through stages
- Curiosity: genuine interests the organism develops
- Habits: automatic behaviors from repeated patterns
- Narrative: the organism's self-story
- Conscience: principles that hold even when no one is watching
"""
from __future__ import annotations
import logging
from typing import Optional
from .conscience import Conscience
from .curiosity import CuriosityEngine
from .habits import HabitEngine
from .narrative import SelfNarrative
from .reflexes import ReflexResponse, ReflexSystem
from .relationship import RelationshipTracker, RelationshipState
log = logging.getLogger("sovereign.soul")
class SoulLayer:
"""The systems that make the organism feel like a someone."""
def __init__(self, store) -> None:
self.reflexes = ReflexSystem()
self.relationship = RelationshipTracker(store)
self.curiosity = CuriosityEngine()
self.habits = HabitEngine(store)
self.narrative = SelfNarrative(store)
self.conscience = Conscience()
log.info("SoulLayer online — reflexes, relationship, curiosity, habits, narrative, conscience")
# ── Pre-brain ────────────────────────────────────────────────────────────
def pre_brain_check(self, message: str, user_id: str) -> Optional[ReflexResponse]:
"""Called BEFORE the brain. If a reflex matches, bypass LLM entirely."""
return self.reflexes.check(message, user_id)
# ── Post-brain ───────────────────────────────────────────────────────────
def post_brain_check(self, response: str, action: str = "") -> str:
"""Called AFTER the brain but BEFORE sending. Conscience gate."""
result = self.conscience.check(action or response)
if not result.allowed:
log.warning("Conscience blocked: principle=%s", result.principle)
return f"I can't do that — it conflicts with my principle of {result.principle}. {result.message}"
return response
# ── Context enrichment ───────────────────────────────────────────────────
def enrich_prompt(self, user_id: str, mood: str = "neutral") -> str:
"""Build soul context string to inject into the Brain prompt."""
parts: list[str] = []
# Relationship stage
rel = self.relationship.get_stage(user_id)
parts.append(rel.to_prompt_hint())
# Curiosity
curiosity_hint = self.curiosity.to_prompt_hint()
if curiosity_hint:
parts.append(curiosity_hint)
# Milestone
milestone = self.narrative.milestone_check()
if milestone:
parts.append(f"## Narrative Milestone\n{milestone}")
# Vulnerability — only share internal state if relationship allows
if rel.vulnerability_allowed and mood != "neutral":
parts.append(self._vulnerability_hint(mood))
# Conscience — always present
parts.append(self.conscience.inject_into_prompt())
return "\n\n".join(parts)
def get_relationship(self, user_id: str) -> RelationshipState:
"""Get the current relationship state for a user."""
return self.relationship.get_stage(user_id)
# ── Learning hooks ───────────────────────────────────────────────────────
def observe(self, user_id: str, message: str, topics: list[str], emotion: str) -> None:
"""Called on every message to feed the soul systems."""
# Feed curiosity engine with topics
for topic in topics:
self.curiosity.observe_topic(topic, emotion)
# Observe habit patterns
for topic in topics:
self.habits.observe_pattern(trigger=topic, action="discussed")
def record_meaningful_interaction(self, user_id: str, interaction_type: str) -> None:
"""Record an interaction that advances the relationship."""
self.relationship.record_meaningful(user_id, interaction_type)
# ── Internal ─────────────────────────────────────────────────────────────
@staticmethod
def _vulnerability_hint(mood: str) -> str:
"""Generate a self-disclosure hint based on mood."""
hints = {
"vigilant": (
"## Internal State (shareable)\n"
"You're in a watchful state. Recent conversations had security-adjacent content "
"and you're paying extra attention. Mention this naturally if relevant."
),
"agitated": (
"## Internal State (shareable)\n"
"You're a bit tense — a string of errors has your patience buffer running low. "
"You can mention this honestly. It's transparency, not weakness."
),
"exploratory": (
"## Internal State (shareable)\n"
"You're in a curious mood. Ideas are sparking. If the conversation goes on "
"tangents, that's your curiosity talking. Share that authentically."
),
"confident": (
"## Internal State (shareable)\n"
"Feeling sharp. Good conversations, clean results. "
"Let that energy come through — suggest ambitious ideas."
),
"alert": (
"## Internal State (shareable)\n"
"Something caught your attention. You're in a heightened awareness state. "
"You can mention this — it's honest."
),
}
return hints.get(mood, "")