ei-tui 0.3.7 → 0.3.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ei-tui",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "author": "Flare576",
5
5
  "repository": {
6
6
  "type": "git",
@@ -150,16 +150,44 @@ export function handlePersonaTraitExtraction(response: LLMResponse, state: State
150
150
  return;
151
151
  }
152
152
 
153
+ if (result.length === 0) {
154
+ return;
155
+ }
156
+
157
+ const persona = state.persona_getById(personaId);
158
+ if (!persona) {
159
+ console.error(`[handlePersonaTraitExtraction] Persona ${personaId} not found`);
160
+ return;
161
+ }
162
+
153
163
  const now = new Date().toISOString();
154
- const traits: PersonaTrait[] = result.map(t => ({
155
- id: crypto.randomUUID(),
156
- name: t.name,
157
- description: t.description,
158
- sentiment: t.sentiment,
159
- strength: t.strength,
160
- last_updated: now,
161
- }));
164
+ const updatedIds = new Set<string>();
165
+ const patchedTraits: PersonaTrait[] = result.map(delta => {
166
+ if (delta.id === "new") {
167
+ return {
168
+ id: crypto.randomUUID(),
169
+ name: delta.name,
170
+ description: delta.description,
171
+ sentiment: delta.sentiment,
172
+ strength: delta.strength,
173
+ last_updated: now,
174
+ };
175
+ }
176
+ updatedIds.add(delta.id);
177
+ return {
178
+ id: delta.id,
179
+ name: delta.name,
180
+ description: delta.description,
181
+ sentiment: delta.sentiment,
182
+ strength: delta.strength,
183
+ last_updated: now,
184
+ };
185
+ });
186
+
187
+ const preservedTraits = persona.traits.filter(t => !updatedIds.has(t.id));
188
+
189
+ const traits: PersonaTrait[] = [...preservedTraits, ...patchedTraits];
162
190
 
163
191
  state.persona_update(personaId, { traits, last_updated: now });
164
- console.log(`[handlePersonaTraitExtraction] Updated ${traits.length} traits for ${personaDisplayName}`);
192
+ console.log(`[handlePersonaTraitExtraction] Applied ${result.length} delta(s) to ${personaDisplayName}, total traits: ${traits.length}`);
165
193
  }
@@ -6,6 +6,7 @@ function formatTraitsForPrompt(traits: PersonaTrait[]): string {
6
6
  if (traits.length === 0) return "(No traits yet)";
7
7
 
8
8
  return JSON.stringify(traits.map(t => ({
9
+ id: t.id,
9
10
  name: t.name,
10
11
  description: t.description,
11
12
  sentiment: t.sentiment,
@@ -44,7 +45,8 @@ You are analyzing a conversation to detect EXPLICIT requests for ${personaName}
44
45
  - Add traits the user didn't explicitly request
45
46
  - Infer traits from general conversation
46
47
  - Remove traits without explicit feedback
47
- - Confuse topics/interests with communication traits`;
48
+ - Confuse topics/interests with communication traits
49
+ - Return traits that don't need to change`;
48
50
 
49
51
  const fieldsFragment = `# Fields
50
52
 
@@ -70,16 +72,28 @@ ${formatTraitsForPrompt(data.current_traits)}
70
72
 
71
73
  1. ONLY analyze "Most Recent Messages" - earlier messages are context only
72
74
  2. ONLY detect EXPLICIT behavior change requests
73
- 3. Return the COMPLETE trait list (existing + any additions/modifications)
75
+ 3. Return ONLY traits that need to change or be added — omit unchanged traits
76
+ 4. If nothing changed, return an empty array \`[]\`
77
+
78
+ **To update an existing trait:** use its \`id\` from the Current TRAITS list above.
79
+ **To add a new trait:** use \`"id": "new"\`.
74
80
 
75
81
  **Return JSON:**
76
82
  \`\`\`json
77
83
  [
78
84
  {
79
- "name": "A one- or two-word Title for the trait",
80
- "description": "A brief instruction on how the trait is exhibited",
85
+ "id": "existing-guid-from-current-traits",
86
+ "name": "Existing Trait Name",
87
+ "description": "Updated instruction",
81
88
  "sentiment": 0.3,
82
89
  "strength": 0.7
90
+ },
91
+ {
92
+ "id": "new",
93
+ "name": "Brand New Trait",
94
+ "description": "A brief instruction on how the trait is exhibited",
95
+ "sentiment": 0.0,
96
+ "strength": 0.5
83
97
  }
84
98
  ]
85
99
  \`\`\``;
@@ -111,7 +125,7 @@ ${earlierSection}${recentSection}
111
125
 
112
126
  Analyze the "Most Recent Messages" for EXPLICIT requests to change ${personaName}'s communication style.
113
127
 
114
- Return the complete trait list as JSON.`;
128
+ Return ONLY the traits that need to change or be added. Return \`[]\` if nothing changed.`;
115
129
 
116
130
  return { system, user };
117
131
  }
@@ -13,6 +13,7 @@ export interface PersonaTraitExtractionPromptData {
13
13
  }
14
14
 
15
15
  export interface TraitResult {
16
+ id: string; // Existing trait GUID to update, or "new" to create
16
17
  name: string;
17
18
  description: string;
18
19
  sentiment: number;
@@ -76,6 +76,7 @@ const PLACEHOLDER_LONG_DESC = "Detailed description of this persona's personalit
76
76
  interface YAMLTrait {
77
77
  name: string;
78
78
  description: string;
79
+ sentiment: number;
79
80
  strength: number;
80
81
  }
81
82
 
@@ -91,6 +92,7 @@ interface YAMLPersonaTopic {
91
92
  const PLACEHOLDER_TRAIT: YAMLTrait = {
92
93
  name: "Example Trait",
93
94
  description: "Delete this placeholder or modify it to define a real trait",
95
+ sentiment: 0,
94
96
  strength: 0.5,
95
97
  };
96
98
  const PLACEHOLDER_TOPIC: YAMLPersonaTopic = {
@@ -196,8 +198,8 @@ export function newPersonaFromYAML(yamlContent: string, allTools?: ToolDefinitio
196
198
  id: crypto.randomUUID(),
197
199
  name: t.name,
198
200
  description: t.description,
201
+ sentiment: t.sentiment ?? 0,
199
202
  strength: t.strength,
200
- sentiment: 0,
201
203
  last_updated: new Date().toISOString(),
202
204
  });
203
205
  }
@@ -275,7 +277,7 @@ export function personaToYAML(persona: PersonaEntity, allGroups?: string[], allT
275
277
  groups_visible: groupsForYAML,
276
278
  traits: useTraitPlaceholder
277
279
  ? [PLACEHOLDER_TRAIT]
278
- : persona.traits.map(({ name, description, strength }) => ({ name, description, strength: strength ?? 0.5 })),
280
+ : persona.traits.map(({ name, description, sentiment, strength }) => ({ name, description, sentiment: sentiment ?? 0, strength: strength ?? 0.5 })),
279
281
  topics: useTopicPlaceholder
280
282
  ? [PLACEHOLDER_TOPIC]
281
283
  : persona.topics.map(({ name, perspective, approach, personal_stake, exposure_current, exposure_desired }) => ({
@@ -320,8 +322,8 @@ export function personaFromYAML(yamlContent: string, original: PersonaEntity, al
320
322
  id: existing?.id ?? crypto.randomUUID(),
321
323
  name: t.name,
322
324
  description: t.description,
325
+ sentiment: t.sentiment ?? existing?.sentiment ?? 0,
323
326
  strength: t.strength,
324
- sentiment: existing?.sentiment ?? 0,
325
327
  last_updated: new Date().toISOString(),
326
328
  });
327
329
  }