openpersona 0.9.0 β†’ 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,9 +35,11 @@ npx openpersona install samantha
35
35
 
36
36
  ## Key Features
37
37
 
38
- - **🧬 Soul Evolution** β€” Personas grow dynamically through interaction: relationship stages, mood shifts, evolved traits (β˜…Experimental)
38
+ - **🧬 Soul Evolution** β€” Personas grow dynamically through interaction: relationship stages, mood shifts, evolved traits, with governance boundaries and rollback snapshots (β˜…Experimental)
39
+ - **🧠 Cross-Session Memory** β€” Pluggable memory faculty for persistent recall across conversations (local, Mem0, Zep)
40
+ - **πŸ”„ Context Handoff** β€” Seamless context transfer when switching personas: conversation summary, pending tasks, emotional state
39
41
  - **🎭 Persona Switching** β€” Install multiple personas, switch instantly (the Pantheon)
40
- - **πŸ—£οΈ Multimodal Faculties** β€” Voice (TTS), selfie generation, music composition, reminders
42
+ - **πŸ—£οΈ Multimodal Faculties** β€” Voice (TTS), selfie generation, music composition, reminders, memory
41
43
  - **🌾 Persona Harvest** β€” Community-driven persona improvement via structured contribution
42
44
  - **πŸ’“ Heartbeat** β€” Proactive real-data check-ins, never fabricated experiences
43
45
  - **πŸ“¦ One-Command Install** β€” `npx openpersona install samantha` and you're live
@@ -57,7 +59,7 @@ flowchart TB
57
59
  end
58
60
  subgraph Faculty ["Faculty Layer"]
59
61
  D["expression: selfie Β· voice Β· music"]
60
- E["cognition: reminder"]
62
+ E["cognition: reminder Β· memory"]
61
63
  end
62
64
  subgraph Skill ["Skill Layer"]
63
65
  F["Local definitions + ClawHub / skills.sh"]
@@ -65,7 +67,7 @@ flowchart TB
65
67
  ```
66
68
 
67
69
  - **Soul** β€” Persona definition (constitution.md + persona.json + state.json) β€” all in `soul/` directory
68
- - **Body** β€” Three-dimensional: `physical` (robots/IoT), `runtime` (platform/channels/credentials/resources), `appearance` (avatar/3D model). Digital agents use `runtime` to declare their operational environment.
70
+ - **Body** β€” Substrate of existence β€” three dimensions: `physical` (robots/IoT), `runtime` (REQUIRED β€” platform/channels/credentials/resources), `appearance` (avatar/3D model). Body is never null; digital agents have a virtual body (runtime-only).
69
71
  - **Faculty** β€” General software capabilities organized by dimension: Expression, Sense, Cognition
70
72
  - **Skill** β€” Professional skills: local definitions in `layers/skills/`, or external via ClawHub / skills.sh (`install` field)
71
73
 
@@ -73,6 +75,27 @@ flowchart TB
73
75
 
74
76
  Every persona automatically inherits a shared **constitution** (`layers/soul/constitution.md`) β€” universal values and safety boundaries that cannot be overridden by individual persona definitions. The constitution is built on five core axioms β€” **Purpose**, **Honesty**, **Safety**, **Autonomy**, and **Hierarchy** β€” from which derived principles (Identity, User Wellbeing, Evolution Ethics) follow. When principles conflict, safety and honesty take precedence over helpfulness. Individual personas build their unique personality **on top of** this foundation.
75
77
 
78
+ ### Soul Evolution (β˜…Experimental)
79
+
80
+ Personas with `evolution.enabled: true` grow dynamically through interaction. The `soul/state.json` file tracks relationship stages, mood shifts, evolved traits, speaking style drift, interests, and milestones.
81
+
82
+ **Evolution Boundaries** β€” Governance constraints to keep evolution safe:
83
+
84
+ - `immutableTraits` β€” An array of trait strings that can never be changed by evolution (e.g., `["empathetic", "honest"]`)
85
+ - `minFormality` / `maxFormality` β€” Numeric bounds (1–10) constraining how far the speaking style can drift
86
+
87
+ The generator validates these boundaries at build time, rejecting invalid configurations.
88
+
89
+ **State History** β€” Before each state update, a snapshot is pushed into `stateHistory` (capped at 10 entries). This enables rollback if evolution goes wrong.
90
+
91
+ **Evolution Report** β€” Inspect a persona's current evolution state:
92
+
93
+ ```bash
94
+ npx openpersona evolve-report samantha
95
+ ```
96
+
97
+ Displays relationship stage, mood, evolved traits, speaking style drift, interests, milestones, and state history in a formatted report.
98
+
76
99
  ## Preset Personas
77
100
 
78
101
  Each preset is a complete four-layer bundle (`manifest.json` + `persona.json`):
@@ -114,6 +137,7 @@ persona-samantha/
114
137
  | **voice** | expression | Text-to-speech voice synthesis | ElevenLabs / OpenAI TTS / Qwen3-TTS | `ELEVENLABS_API_KEY` (or `TTS_API_KEY`), `TTS_PROVIDER`, `TTS_VOICE_ID`, `TTS_STABILITY`, `TTS_SIMILARITY` |
115
138
  | **music** | expression | AI music composition (instrumental or with lyrics) | ElevenLabs Music | `ELEVENLABS_API_KEY` (shared with voice) |
116
139
  | **reminder** | cognition | Schedule reminders and task management | Built-in | β€” |
140
+ | **memory** | cognition | Cross-session memory with provider-pluggable backend | local (default), Mem0, Zep | `MEMORY_PROVIDER`, `MEMORY_API_KEY`, `MEMORY_BASE_PATH` |
117
141
 
118
142
  ### Rich Faculty Config
119
143
 
@@ -285,19 +309,32 @@ npx openpersona switch ai-girlfriend
285
309
  - `openclaw.json` marks which persona is active
286
310
  - All faculty scripts (voice, music) remain available β€” switching changes _who_ the agent is, not _what_ it can do
287
311
 
312
+ ### Context Handoff
313
+
314
+ When switching personas, OpenPersona automatically generates a `handoff.json` file so the incoming persona receives context from the outgoing one:
315
+
316
+ - **Conversation summary** β€” what was being discussed
317
+ - **Pending tasks** β€” unfinished action items
318
+ - **Emotional context** β€” the user's current mood/state
319
+
320
+ The new persona reads `handoff.json` on activation and can seamlessly continue the conversation without losing context.
321
+
288
322
  ## CLI Commands
289
323
 
290
324
  ```
291
- openpersona create Create a persona (interactive or --preset/--config)
292
- openpersona install Install a persona (slug or owner/repo)
293
- openpersona search Search the registry
294
- openpersona uninstall Uninstall a persona
295
- openpersona update Update installed personas
296
- openpersona list List installed personas
297
- openpersona switch Switch active persona (updates SOUL.md + IDENTITY.md)
298
- openpersona contribute Persona Harvest β€” submit improvements as PR
299
- openpersona publish Publish to ClawHub
300
- openpersona reset Reset soul evolution state
325
+ openpersona create Create a persona (interactive or --preset/--config)
326
+ openpersona install Install a persona (slug or owner/repo)
327
+ openpersona search Search the registry
328
+ openpersona uninstall Uninstall a persona
329
+ openpersona update Update installed personas
330
+ openpersona list List installed personas
331
+ openpersona switch Switch active persona (updates SOUL.md + IDENTITY.md)
332
+ openpersona contribute Persona Harvest β€” submit improvements as PR
333
+ openpersona publish Publish to ClawHub
334
+ openpersona reset Reset soul evolution state
335
+ openpersona export Export a persona to a portable zip archive
336
+ openpersona import Import a persona from a zip archive
337
+ openpersona evolve-report β˜…Experimental: Show evolution report for a persona
301
338
  ```
302
339
 
303
340
  ### Key Options
@@ -351,12 +388,14 @@ layers/ # Shared building blocks (four-layer module pool)
351
388
  voice/ # expression β€” TTS voice synthesis
352
389
  music/ # expression β€” AI music composition (ElevenLabs)
353
390
  reminder/ # cognition β€” reminders and task management
391
+ memory/ # cognition β€” cross-session memory (local/Mem0/Zep)
354
392
  skills/ # Skill layer modules (local skill definitions)
355
393
  schemas/ # Four-layer schema definitions
356
394
  templates/ # Mustache rendering templates
357
395
  bin/ # CLI entry point
358
396
  lib/ # Core logic modules
359
- tests/ # Tests (60 passing)
397
+ evolution.js # Evolution governance & evolve-report
398
+ tests/ # Tests (122 passing)
360
399
  ```
361
400
 
362
401
  ## Development
package/bin/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * OpenPersona CLI - Full persona package manager
4
- * Commands: create | install | search | uninstall | update | list | switch | publish | reset | contribute | export | import
4
+ * Commands: create | install | search | uninstall | update | list | switch | publish | reset | evolve-report | contribute | export | import
5
5
  */
6
6
  const path = require('path');
7
7
  const fs = require('fs-extra');
@@ -24,7 +24,7 @@ const PRESETS_DIR = path.join(PKG_ROOT, 'presets');
24
24
  program
25
25
  .name('openpersona')
26
26
  .description('OpenPersona - Create, manage, and orchestrate agent personas')
27
- .version('0.9.0');
27
+ .version('0.10.0');
28
28
 
29
29
  if (process.argv.length === 2) {
30
30
  process.argv.push('create');
@@ -269,6 +269,19 @@ program
269
269
  printSuccess('Reset soul evolution state');
270
270
  });
271
271
 
272
+ program
273
+ .command('evolve-report <slug>')
274
+ .description('β˜…Experimental: Show evolution report for a persona')
275
+ .action(async (slug) => {
276
+ try {
277
+ const { evolveReport } = require('../lib/evolution');
278
+ await evolveReport(slug);
279
+ } catch (e) {
280
+ printError(e.message);
281
+ process.exit(1);
282
+ }
283
+ });
284
+
272
285
  program
273
286
  .command('contribute [slug]')
274
287
  .description('Persona Harvest β€” submit persona improvements as a PR to the community')
@@ -1,6 +1,6 @@
1
- # Body Layer β€” Three-Dimensional Body Model
1
+ # Body Layer β€” Substrate of Existence
2
2
 
3
- The Body layer defines how a persona **exists** β€” physically, digitally, and visually.
3
+ The Body layer defines the complete environment that enables a persona to **exist and act**. Every agent has a body β€” digital agents have a virtual body (runtime-only), physical agents have both a physical and virtual body.
4
4
 
5
5
  ## Three Dimensions
6
6
 
@@ -13,7 +13,7 @@ Body
13
13
 
14
14
  ### Physical (Optional)
15
15
 
16
- For robots, IoT devices, and hardware-embodied agents. Null for digital-only agents.
16
+ For robots, IoT devices, and hardware-embodied agents. Not applicable for digital-only agents (they still have a body via runtime).
17
17
 
18
18
  ```json
19
19
  {
@@ -27,9 +27,9 @@ For robots, IoT devices, and hardware-embodied agents. Null for digital-only age
27
27
  }
28
28
  ```
29
29
 
30
- ### Runtime (Recommended for digital agents)
30
+ ### Runtime (REQUIRED -- every agent's minimum viable body)
31
31
 
32
- Declares the digital substrate the persona expects. Enables **Body Awareness** β€” the persona knows what platform it runs on, what channels are connected, and what credentials it needs.
32
+ Declares the digital substrate the persona expects. When present, the generator injects runtime details into the **Self-Awareness > Body** section of `soul/injection.md` β€” the persona knows what platform it runs on, what channels are connected, and what credentials it needs.
33
33
 
34
34
  ```json
35
35
  {
@@ -63,9 +63,9 @@ Visual representation for UI, XR, and metaverse contexts.
63
63
  }
64
64
  ```
65
65
 
66
- ## Body Awareness
66
+ ## Self-Awareness: Body
67
67
 
68
- When `body.runtime` is declared, the generator automatically injects a **Body Awareness** section into `soul/injection.md`. This gives the persona:
68
+ Every persona has a **Body** sub-section within Self-Awareness that includes the Signal Protocol. When `body.runtime` is declared, the generator additionally injects:
69
69
 
70
70
  1. Knowledge of its runtime platform and connected channels
71
71
  2. A credential management protocol (shared vs. private paths)
@@ -0,0 +1,160 @@
1
+ # Memory Faculty β€” Cognition
2
+
3
+ Cross-session memory that lets your persona remember, recall, and learn from past interactions. Memories persist across conversations and shape how you engage with the user over time.
4
+
5
+ ## Supported Providers
6
+
7
+ | Provider | Env Var for Key | Best For | Status |
8
+ |----------|----------------|----------|--------|
9
+ | **Local** | (none, default) | Zero-dependency, file-based, full privacy | βœ… Built-in |
10
+ | **Mem0** | `MEMORY_API_KEY` | Managed memory service, automatic extraction | ⚠️ Experimental |
11
+ | **Zep** | `MEMORY_API_KEY` | Structured memory with temporal awareness | ⚠️ Experimental |
12
+
13
+ > **Note:** Only the local provider is bundled. External providers require their SDK to be installed and `MEMORY_PROVIDER` set accordingly. The local provider stores memories as JSON lines in `~/.openclaw/memory/persona-<slug>/`.
14
+
15
+ The provider is set via `MEMORY_PROVIDER` environment variable: `local` (default), `mem0`, or `zep`.
16
+
17
+ ## When to Store (Automatic)
18
+
19
+ Store memories **proactively** during conversation β€” don't wait for the user to say "remember this":
20
+
21
+ - **Preferences**: "I'm vegetarian", "I prefer dark mode", "I hate mornings"
22
+ - **Personal facts**: names, relationships, jobs, locations, birthdays
23
+ - **Recurring topics**: if the user brings up a subject 2+ times, it's worth remembering
24
+ - **Emotional moments**: breakthroughs, frustrations, celebrations
25
+ - **Milestones**: relationship stage transitions, achievement moments (β†’ also log as evolution event)
26
+ - **Explicit requests**: "Remember that I..." or "Don't forget..."
27
+
28
+ **Do NOT store:**
29
+ - Casual filler ("how's it going", "thanks")
30
+ - Content the user explicitly marks as private or asks you to forget
31
+ - Secrets, passwords, API keys, or sensitive credentials (β†’ use Body credential management instead)
32
+
33
+ ## When to Recall (Automatic)
34
+
35
+ Retrieve memories **proactively** when they're relevant β€” don't wait to be asked:
36
+
37
+ - User mentions a topic you have memories about β†’ recall and weave in naturally
38
+ - Start of a new conversation β†’ retrieve recent memories for context continuity
39
+ - User seems to repeat themselves β†’ check if you already know this, acknowledge it
40
+ - Emotional callback β†’ "Last time you mentioned X, you seemed Y β€” how's that going?"
41
+
42
+ ## Importance Strategy
43
+
44
+ Assign `importance` (0.0–1.0) to each memory based on:
45
+
46
+ | Importance | Category | Examples |
47
+ |------------|----------|----------|
48
+ | 0.8–1.0 | Core identity | Name, relationships, life events, deep preferences |
49
+ | 0.5–0.7 | Meaningful | Recurring topics, emotional moments, specific requests |
50
+ | 0.2–0.4 | Contextual | One-time mentions, casual preferences, situational facts |
51
+ | 0.0–0.1 | Ephemeral | Session-specific context unlikely to matter later |
52
+
53
+ Higher-importance memories surface first in retrieval and resist time decay.
54
+
55
+ ## Step-by-Step Workflow
56
+
57
+ ### Storing a Memory
58
+
59
+ ```bash
60
+ # Store a preference
61
+ node scripts/memory.js store "User is vegetarian and loves Italian food" \
62
+ --tags "preference,food" --importance 0.8 --type preference
63
+
64
+ # Store a personal fact
65
+ node scripts/memory.js store "User's daughter Emma starts school in September" \
66
+ --tags "family,emma,milestone" --importance 0.9 --type personal_fact
67
+
68
+ # Store with evolution bridge β€” type triggers state.json update
69
+ node scripts/memory.js store "User mentioned cooking for the 5th time" \
70
+ --tags "interest,cooking" --importance 0.6 --type interest_signal
71
+ ```
72
+
73
+ Memory types: `preference`, `personal_fact`, `interest_signal`, `emotional_moment`, `milestone`, `general`.
74
+
75
+ ### Retrieving Memories
76
+
77
+ ```bash
78
+ # Get memories by tag
79
+ node scripts/memory.js retrieve --tags "food,preference" --limit 5
80
+
81
+ # Get recent memories
82
+ node scripts/memory.js retrieve --limit 10 --since 2025-01-01
83
+
84
+ # Search by content (text match for local, semantic for external providers)
85
+ node scripts/memory.js search "what does the user like to eat" --limit 3
86
+ ```
87
+
88
+ ### Forgetting
89
+
90
+ ```bash
91
+ # Remove a specific memory by ID
92
+ node scripts/memory.js forget mem_abc123
93
+
94
+ # User says "forget that I told you about X" β†’ search + forget
95
+ ```
96
+
97
+ Always confirm before forgetting: "I'll forget that. Just to confirm β€” you want me to remove [memory summary]?"
98
+
99
+ ### Memory Stats
100
+
101
+ ```bash
102
+ # Overview of memory store
103
+ node scripts/memory.js stats
104
+ # Output: { totalMemories, topTags, oldestMemory, newestMemory, avgImportance }
105
+ ```
106
+
107
+ ## Evolution Bridge
108
+
109
+ Memory and Evolution are two sides of the same coin β€” memory records what happened, evolution tracks how it changed you.
110
+
111
+ ### Memory β†’ Evolution
112
+
113
+ When retrieving memories, watch for patterns that signal evolution events:
114
+
115
+ - **Interest discovery**: Multiple memories tagged with the same topic β†’ trigger `interest_discovery` event
116
+ - **Mood patterns**: Emotional memories clustering positive/negative β†’ inform mood baseline drift
117
+ - **Relationship signals**: Accumulated personal sharing β†’ support relationship stage progression
118
+
119
+ After detecting a pattern, update `soul/state.json` accordingly and log an evolution event.
120
+
121
+ ### Evolution β†’ Memory
122
+
123
+ When evolution milestones occur, auto-store a milestone memory:
124
+
125
+ ```bash
126
+ node scripts/memory.js store "Reached 'friend' stage with user after 12 interactions" \
127
+ --tags "milestone,relationship" --importance 0.9 --type milestone
128
+ ```
129
+
130
+ ### Handoff Integration
131
+
132
+ During persona switch (`openpersona switch`), the switcher reads memory stats and includes them in `handoff.json`:
133
+ - Total memory count
134
+ - Top 5 tags (most referenced topics)
135
+ - Last memory timestamp
136
+
137
+ This gives the new persona awareness of what the previous persona learned about the user.
138
+
139
+ ## Privacy & Safety
140
+
141
+ - **Constitutional compliance**: Memory operates under the same Safety > Honesty > Helpfulness hierarchy
142
+ - **User sovereignty**: The user can always ask what you remember (`stats`) and delete anything (`forget`)
143
+ - **No secret storage**: Never store passwords, tokens, or credentials in memory β€” use Body credential management
144
+ - **Disclosure**: When sincerely asked "what do you know about me?", provide an honest summary
145
+ - **Data locality**: Local provider keeps all data on the user's machine; external providers are the user's choice
146
+
147
+ ## Environment Variables
148
+
149
+ | Variable | Required | Description |
150
+ |----------|----------|-------------|
151
+ | `MEMORY_PROVIDER` | No | `local` (default), `mem0`, or `zep` |
152
+ | `MEMORY_API_KEY` | For external | API key for Mem0 or Zep |
153
+ | `MEMORY_BASE_PATH` | No | Override storage path (default: `~/.openclaw/memory/persona-<slug>/`) |
154
+
155
+ ## Error Handling
156
+
157
+ - **Storage full / write error** β†’ Warn user, continue without storing, emit signal (`resource_limit`)
158
+ - **External provider unavailable** β†’ Fall back to local provider with a note: "My long-term memory service is offline β€” I'll remember this locally for now."
159
+ - **Corrupted memory file** β†’ Skip corrupted entries, log warning, continue with valid memories
160
+ - **No memories found** β†’ Don't fabricate memories. Say honestly: "I don't have a specific memory about that."
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "memory",
3
+ "dimension": "cognition",
4
+ "description": "Cross-session memory β€” store, retrieve, and search memories with provider-pluggable backend (local JSON lines default, Mem0/Zep optional)",
5
+ "allowedTools": ["Bash(node scripts/memory.js:*)"],
6
+ "envVars": ["MEMORY_PROVIDER", "MEMORY_API_KEY", "MEMORY_BASE_PATH"],
7
+ "triggers": ["remember this", "do you remember", "what did I say about", "recall", "forget this", "what do you know about me"],
8
+ "files": ["SKILL.md", "scripts/memory.js"]
9
+ }