ei-tui 0.9.3 → 0.9.4

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.
Files changed (52) hide show
  1. package/package.json +4 -1
  2. package/src/README.md +1 -1
  3. package/src/core/context-utils.ts +2 -2
  4. package/src/core/handlers/heartbeat.ts +9 -1
  5. package/src/core/handlers/human-extraction.ts +4 -1
  6. package/src/core/handlers/human-matching.ts +5 -53
  7. package/src/core/handlers/index.ts +1 -51
  8. package/src/core/handlers/persona-generation.ts +1 -28
  9. package/src/core/handlers/utils.ts +2 -9
  10. package/src/core/heartbeat-manager.ts +3 -3
  11. package/src/core/message-manager.ts +6 -5
  12. package/src/core/orchestrators/ceremony.ts +4 -9
  13. package/src/core/orchestrators/extraction-chunker.ts +3 -3
  14. package/src/core/orchestrators/human-extraction.ts +17 -17
  15. package/src/core/orchestrators/index.ts +0 -1
  16. package/src/core/orchestrators/persona-topics.ts +1 -1
  17. package/src/core/orchestrators/room-extraction.ts +5 -5
  18. package/src/core/processor.ts +8 -21
  19. package/src/core/prompt-context-builder.ts +7 -6
  20. package/src/core/state/personas.ts +1 -17
  21. package/src/core/state-manager.ts +0 -66
  22. package/src/core/types/entities.ts +2 -3
  23. package/src/core/types/enums.ts +0 -2
  24. package/src/core/types/rooms.ts +1 -1
  25. package/src/integrations/claude-code/importer.ts +1 -1
  26. package/src/integrations/cursor/importer.ts +1 -1
  27. package/src/integrations/opencode/importer.ts +1 -1
  28. package/src/prompts/ceremony/index.ts +0 -10
  29. package/src/prompts/ceremony/types.ts +1 -42
  30. package/src/prompts/generation/index.ts +0 -3
  31. package/src/prompts/generation/types.ts +0 -15
  32. package/src/prompts/heartbeat/check.ts +18 -6
  33. package/src/prompts/heartbeat/types.ts +2 -1
  34. package/src/prompts/human/index.ts +0 -2
  35. package/src/prompts/human/types.ts +0 -16
  36. package/src/prompts/index.ts +0 -19
  37. package/src/prompts/reflection/index.ts +35 -5
  38. package/src/prompts/reflection/types.ts +1 -1
  39. package/src/prompts/response/index.ts +5 -0
  40. package/src/prompts/response/sections.ts +26 -0
  41. package/src/prompts/response/types.ts +3 -0
  42. package/tui/src/commands/registry.test.ts +10 -5
  43. package/tui/src/globals.d.ts +57 -0
  44. package/tui/src/util/yaml-persona.ts +8 -4
  45. package/tui/src/util/yaml-settings.ts +3 -3
  46. package/src/core/orchestrators/person-migration.ts +0 -55
  47. package/src/prompts/ceremony/description-check.ts +0 -54
  48. package/src/prompts/ceremony/expire.ts +0 -37
  49. package/src/prompts/ceremony/explore.ts +0 -77
  50. package/src/prompts/ceremony/person-migration.ts +0 -77
  51. package/src/prompts/generation/descriptions.ts +0 -91
  52. package/src/prompts/human/fact-scan.ts +0 -150
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ei-tui",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "author": "Flare576",
5
5
  "repository": {
6
6
  "type": "git",
@@ -63,7 +63,10 @@
63
63
  "test:evals:persona-trait": "vite-node tests/evals/persona-trait-extraction.eval.ts",
64
64
  "test:evals:dedup": "vite-node tests/evals/dedup-tool-calls.eval.ts",
65
65
  "test:evals:response-read-memory": "vite-node tests/evals/response-read-memory.eval.ts",
66
+ "test:evals:response-pending-update": "vite-node tests/evals/response-pending-update.eval.ts",
67
+ "test:evals:heartbeat-pending-update": "vite-node tests/evals/heartbeat-pending-update.eval.ts",
66
68
  "test:evals:real-data": "vite-node tests/evals/real-data-example.eval.ts",
69
+ "test:evals:persona-data-check": "vite-node tests/evals/persona-data-check.eval.ts",
67
70
  "test:all": "npm run test && npm run test:e2e && npm run test:e2e:tui",
68
71
  "typecheck": "tsc --noEmit",
69
72
  "web": "cd web && npm run dev",
package/src/README.md CHANGED
@@ -148,7 +148,7 @@ This is intentional. Concurrent LLM calls sound appealing until you're watching
148
148
 
149
149
  # Context Windows
150
150
 
151
- Personas don't send their entire message history to the LLM. By default, only messages from the last 8 hours are included (`context_window_hours`, configurable per persona). Older messages are still stored — they're just not in the prompt.
151
+ Personas don't send their entire message history to the LLM. By default, only messages from the last 8 hours are included (`context_window_ms`, configurable per persona). Older messages are still stored — they're just not in the prompt.
152
152
 
153
153
  Message rolloff works differently: messages are kept until there are at least 200 of them _and_ any are older than 14 days. So a persona you chat with daily will roll off old messages gradually; one you chat with twice a year will keep everything.
154
154
 
@@ -8,12 +8,12 @@ import { ContextStatus as ContextStatusEnum } from "./types.js";
8
8
  export function filterMessagesForContext(
9
9
  messages: Message[],
10
10
  contextBoundary: string | undefined,
11
- contextWindowHours: number
11
+ contextWindowMs: number
12
12
  ): Message[] {
13
13
  if (messages.length === 0) return [];
14
14
 
15
15
  const now = Date.now();
16
- const windowStartMs = now - contextWindowHours * 60 * 60 * 1000;
16
+ const windowStartMs = now - contextWindowMs;
17
17
  const boundaryMs = contextBoundary ? new Date(contextBoundary).getTime() : 0;
18
18
 
19
19
  return messages.filter((msg) => {
@@ -126,13 +126,15 @@ export function handleReflectionCritic(response: LLMResponse, state: StateManage
126
126
  const personaDisplayName = response.request.data.personaDisplayName as string;
127
127
 
128
128
  const result = response.parsed as ReflectionCriticResult | undefined;
129
- if (!result?.updated_identity || !result.critique) {
129
+ if (!result?.critique) {
130
130
  console.error(`[ReflectionCritic ${personaDisplayName}] Invalid or missing parsed result`);
131
131
  return;
132
132
  }
133
133
 
134
134
  const personRecord = state.human_person_getByIdentifier("Ei Persona", personaId);
135
135
  if (personRecord) {
136
+ // TODO: Remove before v1 — debug logging to inspect person log before it's cleared
137
+ console.log(`[ReflectionCritic ${personaDisplayName}] person_log_snapshot (${personRecord.description?.length ?? 0} chars): ${personRecord.description ?? ""}`);
136
138
  state.human_person_upsert({
137
139
  ...personRecord,
138
140
  description: "",
@@ -140,6 +142,12 @@ export function handleReflectionCritic(response: LLMResponse, state: StateManage
140
142
  console.log(`[ReflectionCritic ${personaDisplayName}] Person record description cleared — ready for fresh evidence after reflection`);
141
143
  }
142
144
 
145
+ // Escape hatch: critic found no meaningful drift — log critique and skip pending_update
146
+ if (!result.updated_identity) {
147
+ console.log(`[ReflectionCritic ${personaDisplayName}] No drift detected — skipping pending_update. Critique: ${result.critique}`);
148
+ return;
149
+ }
150
+
143
151
  const persona = state.persona_getById(personaId);
144
152
  if (!persona) {
145
153
  console.error(`[ReflectionCritic ${personaDisplayName}] Persona not found after critic`);
@@ -189,7 +189,10 @@ export async function handleHumanPersonScan(response: LLMResponse, state: StateM
189
189
  return;
190
190
  }
191
191
 
192
- const context = response.request.data as unknown as ExtractionContext;
192
+ const context = {
193
+ ...(response.request.data as unknown as ExtractionContext),
194
+ channelDisplayName: (response.request.data as Record<string, unknown>).personaDisplayName as string,
195
+ };
193
196
  if (!context?.personaId) return;
194
197
 
195
198
  const { messages_context, messages_analyze } = resolveMessageWindow(response, state);
@@ -8,7 +8,7 @@ import {
8
8
  import type { PersonIdentifier } from "../types/data-items.js";
9
9
  import type { StateManager } from "../state-manager.js";
10
10
  import type { ItemMatchResult, ExposureImpact, TopicUpdateResult, PersonUpdateResult } from "../../prompts/human/types.js";
11
- import { queueTopicUpdate, queuePersonUpdate, queueTopicValidate, type ExtractionContext } from "../orchestrators/index.js";
11
+ import { queueTopicUpdate, queueTopicValidate, type ExtractionContext } from "../orchestrators/index.js";
12
12
  import { getEmbeddingService, getTopicEmbeddingText, getPersonEmbeddingText } from "../embedding-service.js";
13
13
  import { calculateExposureCurrent } from "../utils/exposure.js";
14
14
 
@@ -48,7 +48,7 @@ export function handleTopicMatch(response: LLMResponse, state: StateManager): vo
48
48
  extraction_model?: string;
49
49
  } = {
50
50
  personaId,
51
- personaDisplayName,
51
+ channelDisplayName: personaDisplayName,
52
52
  roomId,
53
53
  messages_context,
54
54
  messages_analyze,
@@ -64,54 +64,6 @@ export function handleTopicMatch(response: LLMResponse, state: StateManager): vo
64
64
  console.log(`[handleTopicMatch] topic "${context.candidateName}": ${matched}`);
65
65
  }
66
66
 
67
- export function handlePersonMatch(response: LLMResponse, state: StateManager): void {
68
- const result = response.parsed as ItemMatchResult | undefined;
69
- if (!result) {
70
- throw new Error("[handlePersonMatch] No parsed result");
71
- }
72
-
73
- const personaId = response.request.data.personaId as string;
74
- const personaDisplayName = response.request.data.personaDisplayName as string;
75
- const roomId = response.request.data.roomId as string | undefined;
76
- const { messages_context, messages_analyze } = resolveMessageWindow(response, state);
77
-
78
- let matched_guid = result.matched_guid;
79
- let resolvedPerson: import('../types/data-items.js').Person | null = null;
80
- if (matched_guid === "new") {
81
- matched_guid = null;
82
- } else if (matched_guid) {
83
- const human = state.getHuman();
84
- resolvedPerson = human.people.find(p => p.id === matched_guid) ?? null;
85
- if (!resolvedPerson) {
86
- console.warn(`[handlePersonMatch] matched_guid "${matched_guid}" not found in people — treating as new`);
87
- matched_guid = null;
88
- }
89
- }
90
- result.matched_guid = matched_guid;
91
-
92
- const context: ExtractionContext & {
93
- candidateName: string;
94
- candidateDescription: string;
95
- candidateRelationship: string;
96
- extraction_model?: string;
97
- } = {
98
- personaId,
99
- personaDisplayName,
100
- roomId,
101
- messages_context,
102
- messages_analyze,
103
- sources: response.request.data.sources as string[] | undefined,
104
- candidateName: response.request.data.candidateName as string,
105
- candidateDescription: response.request.data.candidateDescription as string,
106
- candidateRelationship: response.request.data.candidateRelationship as string,
107
- extraction_model: response.request.data.extraction_model as string | undefined,
108
- };
109
-
110
- queuePersonUpdate(result, context, state, resolvedPerson);
111
- const matched = matched_guid ? `matched GUID "${matched_guid}"` : "no match (new person)";
112
- console.log(`[handlePersonMatch] person "${context.candidateName}": ${matched}`);
113
- }
114
-
115
67
  export async function handleTopicUpdate(response: LLMResponse, state: StateManager): Promise<void> {
116
68
  const result = response.parsed as (TopicUpdateResult & { quotes?: Array<{ text: string; reason: string }> }) | undefined;
117
69
 
@@ -447,7 +399,7 @@ async function validateAndStoreQuotes(
447
399
  candidates: Array<{ text: string; reason: string }> | undefined,
448
400
  messages: Message[],
449
401
  dataItemId: string,
450
- personaName: string,
402
+ channelDisplayName: string,
451
403
  personaGroup: string | null,
452
404
  state: StateManager
453
405
  ): Promise<void> {
@@ -540,8 +492,8 @@ async function validateAndStoreQuotes(
540
492
  data_item_ids: [dataItemId],
541
493
  persona_groups: [personaGroup || "General"],
542
494
  text: matchText,
543
- speaker: message.role === "human" ? "human" : (message.speaker_name ?? personaName),
544
- channel: personaName,
495
+ speaker: message.role === "human" ? "human" : (message.speaker_name ?? channelDisplayName),
496
+ channel: channelDisplayName,
545
497
  timestamp: message.timestamp,
546
498
  start: matchStart,
547
499
  end: matchEnd,
@@ -1,14 +1,11 @@
1
1
  import { LLMNextStep } from "../types.js";
2
- import type { LLMResponse } from "../types.js";
3
- import type { StateManager } from "../state-manager.js";
4
2
  import type { ResponseHandler } from "./persona-response.js";
5
- import type { PersonIdentifier } from "../types/data-items.js";
6
3
 
7
4
  export type { ResponseHandler } from "./persona-response.js";
8
5
 
9
6
  import { handlePersonaResponse, handleToolContinuation, handleOneShot, handleOneShotJSON } from "./persona-response.js";
10
7
  import { handleHeartbeatCheck, handleEiHeartbeat, handleReflectionCritic } from "./heartbeat.js";
11
- import { handlePersonaGeneration, handlePersonaDescriptions, handlePersonaTraitExtraction } from "./persona-generation.js";
8
+ import { handlePersonaGeneration, handlePersonaTraitExtraction } from "./persona-generation.js";
12
9
  import {
13
10
  handlePersonaTopicRating,
14
11
  } from "./persona-topics.js";
@@ -19,55 +16,9 @@ import { handleDedupCurate } from "./dedup.js";
19
16
  import { handleRoomResponse, handleRoomJudge } from "./rooms.js";
20
17
  import { handlePersonaPreview } from "./persona-preview.js";
21
18
 
22
- function handlePersonIdentifierMigration(response: LLMResponse, state: StateManager): void {
23
- const personId = response.request.data.person_id as string;
24
- if (!personId) {
25
- console.error("[handlePersonIdentifierMigration] Missing person_id in request data");
26
- return;
27
- }
28
-
29
- const human = state.getHuman();
30
- const person = human.people.find(p => p.id === personId);
31
- if (!person) {
32
- console.error(`[handlePersonIdentifierMigration] Person not found: ${personId}`);
33
- return;
34
- }
35
-
36
- const result = response.parsed as { identifiers?: Array<{ type: string; value: string; is_primary?: boolean }> } | undefined;
37
- if (!result?.identifiers || !Array.isArray(result.identifiers) || result.identifiers.length === 0) {
38
- console.error(`[handlePersonIdentifierMigration] Invalid or empty identifiers for ${person.name}`);
39
- return;
40
- }
41
-
42
- const hasName = result.identifiers.some(i => i.value === person.name);
43
- if (!hasName) {
44
- result.identifiers.unshift({ type: "nickname", value: person.name });
45
- }
46
-
47
- const hasPrimary = result.identifiers.some(i => i.is_primary);
48
- if (!hasPrimary) {
49
- result.identifiers[0].is_primary = true;
50
- }
51
-
52
- const identifiers: PersonIdentifier[] = result.identifiers.map(i => ({
53
- type: i.type,
54
- value: i.value,
55
- ...(i.is_primary ? { is_primary: i.is_primary } : {}),
56
- }));
57
-
58
- state.human_person_upsert({
59
- ...person,
60
- identifiers,
61
- last_updated: new Date().toISOString(),
62
- });
63
-
64
- console.log(`[handlePersonIdentifierMigration] Migrated ${identifiers.length} identifier(s) for ${person.name}`);
65
- }
66
-
67
19
  export const handlers: Record<LLMNextStep, ResponseHandler> = {
68
20
  handlePersonaResponse,
69
21
  handlePersonaGeneration,
70
- handlePersonaDescriptions,
71
22
  handleFactFind,
72
23
  handleHumanTopicScan,
73
24
  handleHumanPersonScan,
@@ -88,7 +39,6 @@ export const handlers: Record<LLMNextStep, ResponseHandler> = {
88
39
  handleRoomResponse,
89
40
  handleRoomJudge,
90
41
  handlePersonaPreview,
91
- [LLMNextStep.HandlePersonIdentifierMigration]: handlePersonIdentifierMigration,
92
42
  [LLMNextStep.HandleTopicValidate]: handleDedupCurate,
93
43
  [LLMNextStep.HandleReflectionCritic]: handleReflectionCritic,
94
44
  };
@@ -4,7 +4,7 @@ import {
4
4
  type PersonaTopic,
5
5
  } from "../types.js";
6
6
  import type { StateManager } from "../state-manager.js";
7
- import type { PersonaGenerationResult, PersonaDescriptionsResult } from "../../prompts/generation/types.js";
7
+ import type { PersonaGenerationResult } from "../../prompts/generation/types.js";
8
8
  import type { TraitResult } from "../../prompts/persona/types.js";
9
9
  import { orchestratePersonaGeneration, type PartialPersona } from "../orchestrators/index.js";
10
10
 
@@ -111,33 +111,6 @@ export function handlePersonaGeneration(response: LLMResponse, state: StateManag
111
111
  console.log(`[handlePersonaGeneration] Orchestrated: ${personaDisplayName}`);
112
112
  }
113
113
 
114
- export function handlePersonaDescriptions(response: LLMResponse, state: StateManager): void {
115
- const personaId = response.request.data.personaId as string;
116
- const personaDisplayName = response.request.data.personaDisplayName as string;
117
- if (!personaId) {
118
- console.error("[handlePersonaDescriptions] No personaId in request data");
119
- return;
120
- }
121
-
122
- const result = response.parsed as PersonaDescriptionsResult | undefined;
123
- if (!result) {
124
- console.error("[handlePersonaDescriptions] No parsed result");
125
- return;
126
- }
127
-
128
- if (result.no_change) {
129
- console.log(`[handlePersonaDescriptions] No change needed for ${personaDisplayName}`);
130
- return;
131
- }
132
-
133
- state.persona_update(personaId, {
134
- short_description: result.short_description,
135
- long_description: result.long_description,
136
- last_updated: new Date().toISOString(),
137
- });
138
- console.log(`[handlePersonaDescriptions] Updated descriptions for ${personaDisplayName}`);
139
- }
140
-
141
114
  export function handlePersonaTraitExtraction(response: LLMResponse, state: StateManager): void {
142
115
  const personaId = response.request.data.personaId as string;
143
116
  const personaDisplayName = response.request.data.personaDisplayName as string;
@@ -1,15 +1,8 @@
1
1
  import type { Message, RoomMessage, LLMResponse } from "../types.js";
2
2
  import type { StateManager } from "../state-manager.js";
3
3
 
4
- export function getMessageContent(msg: { content?: string; verbal_response?: string; action_response?: string }): string {
5
- if (msg.content) return msg.content;
6
- // Legacy fallback for data not yet migrated on disk
7
- // TODO(v1.0.0): Remove legacy verbal_response/action_response fallback
8
- const legacy = msg as { verbal_response?: string; action_response?: string };
9
- const parts: string[] = [];
10
- if (legacy.action_response) parts.push(`_${legacy.action_response}_`);
11
- if (legacy.verbal_response) parts.push(legacy.verbal_response);
12
- return parts.join('\n\n');
4
+ export function getMessageContent(msg: { content?: string }): string {
5
+ return msg.content ?? '';
13
6
  }
14
7
 
15
8
  export function normalizeRoomMessages(messages: RoomMessage[], state: StateManager): Message[] {
@@ -217,8 +217,8 @@ export async function queueHeartbeatCheck(sm: StateManager, personaId: string, i
217
217
  console.log(`[HeartbeatCheck ${persona.display_name}] Queueing heartbeat check (model: ${model})`);
218
218
  const human = sm.getHuman();
219
219
  const history = sm.messages_get(personaId);
220
- const contextWindowHours = persona.context_window_hours ?? human.settings?.default_context_window_hours ?? 8;
221
- const contextHistory = filterMessagesForContext(history, persona.context_boundary, contextWindowHours);
220
+ const contextWindowMs = persona.context_window_ms ?? human.settings?.default_context_window_ms ?? 28800000;
221
+ const contextHistory = filterMessagesForContext(history, persona.context_boundary, contextWindowMs);
222
222
 
223
223
  if (personaId === "ei") {
224
224
  await queueEiHeartbeat(sm, human, contextHistory, isTUI);
@@ -244,7 +244,7 @@ export async function queueHeartbeatCheck(sm: StateManager, personaId: string, i
244
244
  name: persona.display_name,
245
245
  traits: persona.traits,
246
246
  topics: persona.topics,
247
- has_pending_update: !!persona.pending_update,
247
+ pending_update: persona.pending_update,
248
248
  },
249
249
  human: {
250
250
  topics: sortByEngagementGap(filteredHuman.topics).slice(0, 5),
@@ -223,7 +223,7 @@ export function checkAndQueueHumanExtraction(
223
223
  if (unextractedFacts.length > 0 && unextractedFacts.length >= factsThreshold) {
224
224
  const context: ExtractionContext = {
225
225
  personaId,
226
- personaDisplayName,
226
+ channelDisplayName: personaDisplayName,
227
227
  messages_context: history.filter((m) => m.f === true),
228
228
  messages_analyze: unextractedFacts,
229
229
  extraction_flag: "f",
@@ -239,7 +239,7 @@ export function checkAndQueueHumanExtraction(
239
239
  if (unextractedTopics.length > 0 && unextractedTopics.length >= topicsThreshold) {
240
240
  const context: ExtractionContext = {
241
241
  personaId,
242
- personaDisplayName,
242
+ channelDisplayName: personaDisplayName,
243
243
  messages_context: history.filter((m) => m.t === true),
244
244
  messages_analyze: unextractedTopics,
245
245
  extraction_flag: "t",
@@ -257,7 +257,7 @@ export function checkAndQueueHumanExtraction(
257
257
  const personScanOptions = personaForScan?.pending_update ? { reflection_progress: 1 } : undefined;
258
258
  const context: ExtractionContext = {
259
259
  personaId,
260
- personaDisplayName,
260
+ channelDisplayName: personaDisplayName,
261
261
  messages_context: history.filter((m) => m.p === true),
262
262
  messages_analyze: unextractedPeople,
263
263
  extraction_flag: "p",
@@ -282,8 +282,9 @@ export function fetchMessagesForLLM(
282
282
 
283
283
  const human = sm.getHuman();
284
284
  const history = sm.messages_get(personaId);
285
- const contextWindowHours = persona.context_window_hours ?? human.settings?.default_context_window_hours ?? 8;
286
- const filteredHistory = filterMessagesForContext(history, persona.context_boundary, contextWindowHours);
285
+ const contextWindowMs = persona.context_window_ms ?? human.settings?.default_context_window_ms ?? 28800000;
286
+ const MAX_RESPONSE_MESSAGES = 50;
287
+ const filteredHistory = filterMessagesForContext(history, persona.context_boundary, contextWindowMs).slice(-MAX_RESPONSE_MESSAGES);
287
288
 
288
289
  const humanName = human.settings?.name_display
289
290
  || human.facts?.find(f => f.name === "Nickname/Preferred Name")?.description
@@ -12,7 +12,6 @@ import {
12
12
  } from "./human-extraction.js";
13
13
  import { queuePersonaTopicRating, type PersonaTopicContext, type PersonaTopicOptions } from "./persona-topics.js";
14
14
  import { getRoomVisibleMessages, queueRoomHumanExtraction } from "./room-extraction.js";
15
- import { queuePersonMigration } from "./person-migration.js";
16
15
  import { buildRewriteScanPrompt, type RewriteItemType } from "../../prompts/ceremony/index.js";
17
16
  import { buildReflectionCriticPrompt } from "../../prompts/reflection/index.js";
18
17
  import { getModelForPersona } from "../heartbeat-manager.js";
@@ -76,10 +75,6 @@ export function startCeremony(state: StateManager): void {
76
75
  },
77
76
  });
78
77
 
79
- // PHASE 1: Person Migration
80
- console.log("[ceremony] Starting Phase 1: Person Migration");
81
- queuePersonMigration(state);
82
-
83
78
  // Check if migration work was queued
84
79
  if (!state.queue_hasPendingCeremonies()) {
85
80
  // No migration work found → immediately advance to Expose phase
@@ -110,7 +105,7 @@ function queueExposurePhase(personaId: string, state: StateManager, options?: Ex
110
105
  if (unextractedFacts.length > 0) {
111
106
  const context: ExtractionContext = {
112
107
  personaId,
113
- personaDisplayName: persona.display_name,
108
+ channelDisplayName: persona.display_name,
114
109
  messages_context: allMessages.filter(m => m.f === true),
115
110
  messages_analyze: unextractedFacts,
116
111
  extraction_flag: "f",
@@ -123,7 +118,7 @@ function queueExposurePhase(personaId: string, state: StateManager, options?: Ex
123
118
  if (unextractedTopics.length > 0) {
124
119
  const context: ExtractionContext = {
125
120
  personaId,
126
- personaDisplayName: persona.display_name,
121
+ channelDisplayName: persona.display_name,
127
122
  messages_context: allMessages.filter(m => m.t === true),
128
123
  messages_analyze: unextractedTopics,
129
124
  extraction_flag: "t",
@@ -135,7 +130,7 @@ function queueExposurePhase(personaId: string, state: StateManager, options?: Ex
135
130
  if (unextractedPeople.length > 0) {
136
131
  const context: ExtractionContext = {
137
132
  personaId,
138
- personaDisplayName: persona.display_name,
133
+ channelDisplayName: persona.display_name,
139
134
  messages_context: allMessages.filter(m => m.p === true),
140
135
  messages_analyze: unextractedPeople,
141
136
  extraction_flag: "p",
@@ -475,7 +470,7 @@ export function queueReflectionDrain(personaId: string, state: StateManager): vo
475
470
 
476
471
  const context: ExtractionContext = {
477
472
  personaId,
478
- personaDisplayName: persona.display_name,
473
+ channelDisplayName: persona.display_name,
479
474
  messages_context: allMessages.filter(m => m.p === true),
480
475
  messages_analyze: unextractedPeople,
481
476
  extraction_flag: "p",
@@ -64,7 +64,7 @@ export function chunkExtractionContext(
64
64
  context: ExtractionContext,
65
65
  maxTokens: number = DEFAULT_MAX_TOKENS
66
66
  ): ChunkedContextResult {
67
- const { personaId, personaDisplayName, messages_context, messages_analyze } = context;
67
+ const { personaId, channelDisplayName: personaDisplayName, messages_context, messages_analyze } = context;
68
68
 
69
69
  if (messages_analyze.length === 0) {
70
70
  return {
@@ -85,7 +85,7 @@ export function chunkExtractionContext(
85
85
  return {
86
86
  chunks: [{
87
87
  personaId,
88
- personaDisplayName,
88
+ channelDisplayName: personaDisplayName,
89
89
  messages_context: fittedContext,
90
90
  messages_analyze,
91
91
  }],
@@ -111,7 +111,7 @@ export function chunkExtractionContext(
111
111
 
112
112
  chunks.push({
113
113
  personaId,
114
- personaDisplayName,
114
+ channelDisplayName: personaDisplayName,
115
115
  messages_context: currentContext,
116
116
  messages_analyze: pulled,
117
117
  });
@@ -55,7 +55,7 @@ function buildParticipantContext(personaId: string, state: StateManager): Partic
55
55
 
56
56
  export interface ExtractionContext {
57
57
  personaId: string;
58
- personaDisplayName: string;
58
+ channelDisplayName: string;
59
59
  messages_context: Message[];
60
60
  messages_analyze: Message[];
61
61
  extraction_flag?: "f" | "t" | "p" | "e";
@@ -118,7 +118,7 @@ export function queueFactFind(context: ExtractionContext, state: StateManager, o
118
118
 
119
119
  for (const chunk of chunks) {
120
120
  const prompt = buildFactFindPrompt({
121
- persona_name: chunk.personaDisplayName,
121
+ persona_name: chunk.channelDisplayName,
122
122
  missing_fact_names,
123
123
  messages_context: chunk.messages_context,
124
124
  messages_analyze: chunk.messages_analyze,
@@ -134,7 +134,7 @@ export function queueFactFind(context: ExtractionContext, state: StateManager, o
134
134
  data: {
135
135
  ...options,
136
136
  personaId: chunk.personaId,
137
- personaDisplayName: chunk.personaDisplayName,
137
+ personaDisplayName: chunk.channelDisplayName,
138
138
  analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
139
139
  extraction_flag: context.extraction_flag,
140
140
  message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
@@ -160,7 +160,7 @@ export function queueTopicScan(context: ExtractionContext, state: StateManager,
160
160
 
161
161
  for (const chunk of chunks) {
162
162
  const prompt = buildHumanTopicScanPrompt({
163
- persona_name: chunk.personaDisplayName,
163
+ persona_name: chunk.channelDisplayName,
164
164
  messages_context: chunk.messages_context,
165
165
  messages_analyze: chunk.messages_analyze,
166
166
  participant_context: buildParticipantContext(context.personaId, state),
@@ -176,7 +176,7 @@ export function queueTopicScan(context: ExtractionContext, state: StateManager,
176
176
  data: {
177
177
  ...options,
178
178
  personaId: chunk.personaId,
179
- personaDisplayName: chunk.personaDisplayName,
179
+ personaDisplayName: chunk.channelDisplayName,
180
180
  analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
181
181
  extraction_flag: context.extraction_flag,
182
182
  message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
@@ -209,7 +209,7 @@ export function queuePersonScan(context: ExtractionContext, state: StateManager,
209
209
 
210
210
  for (const chunk of chunks) {
211
211
  const prompt = buildHumanPersonScanPrompt({
212
- persona_name: chunk.personaDisplayName,
212
+ persona_name: chunk.channelDisplayName,
213
213
  messages_context: chunk.messages_context,
214
214
  messages_analyze: chunk.messages_analyze,
215
215
  participant_context: buildParticipantContext(context.personaId, state),
@@ -226,7 +226,7 @@ export function queuePersonScan(context: ExtractionContext, state: StateManager,
226
226
  data: {
227
227
  ...options,
228
228
  personaId: chunk.personaId,
229
- personaDisplayName: chunk.personaDisplayName,
229
+ personaDisplayName: chunk.channelDisplayName,
230
230
  analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
231
231
  extraction_flag: context.extraction_flag,
232
232
  message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
@@ -273,7 +273,7 @@ export function queueDirectTopicUpdate(
273
273
  existing_item: topic,
274
274
  messages_context: chunk.messages_context,
275
275
  messages_analyze: chunk.messages_analyze,
276
- persona_name: chunk.personaDisplayName,
276
+ persona_name: chunk.channelDisplayName,
277
277
  participant_context: buildParticipantContext(context.personaId, state),
278
278
  });
279
279
 
@@ -286,7 +286,7 @@ export function queueDirectTopicUpdate(
286
286
  next_step: LLMNextStep.HandleTopicUpdate,
287
287
  data: {
288
288
  personaId: context.personaId,
289
- personaDisplayName: context.personaDisplayName,
289
+ personaDisplayName: context.channelDisplayName,
290
290
  isNewItem: false,
291
291
  existingItemId: topic.id,
292
292
  analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
@@ -423,7 +423,7 @@ export function queueTopicUpdate(
423
423
  new_topic_category: isNewItem ? context.candidateCategory : undefined,
424
424
  messages_context: chunk.messages_context,
425
425
  messages_analyze: chunk.messages_analyze,
426
- persona_name: chunk.personaDisplayName,
426
+ persona_name: chunk.channelDisplayName,
427
427
  participant_context: buildParticipantContext(primaryPersonaId, state),
428
428
  });
429
429
 
@@ -502,7 +502,7 @@ export function queueEventSummary(
502
502
 
503
503
  const context: ExtractionContext = {
504
504
  personaId,
505
- personaDisplayName: persona.display_name,
505
+ channelDisplayName: persona.display_name,
506
506
  messages_context,
507
507
  messages_analyze: windowMessages,
508
508
  extraction_flag: "e",
@@ -512,7 +512,7 @@ export function queueEventSummary(
512
512
 
513
513
  for (const chunk of chunks) {
514
514
  const prompt = buildEventScanPrompt({
515
- persona_name: chunk.personaDisplayName,
515
+ persona_name: chunk.channelDisplayName,
516
516
  messages_context: chunk.messages_context,
517
517
  messages_analyze: chunk.messages_analyze,
518
518
  participant_context: buildParticipantContext(personaId, state),
@@ -528,7 +528,7 @@ export function queueEventSummary(
528
528
  data: {
529
529
  ...options,
530
530
  personaId: chunk.personaId,
531
- personaDisplayName: chunk.personaDisplayName,
531
+ personaDisplayName: chunk.channelDisplayName,
532
532
  extraction_flag: "e",
533
533
  message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
534
534
  },
@@ -595,7 +595,7 @@ export function queuePersonUpdate(
595
595
  new_person_relationship: isNewItem ? context.candidateRelationship : undefined,
596
596
  messages_context: chunk.messages_context,
597
597
  messages_analyze: chunk.messages_analyze,
598
- persona_name: chunk.personaDisplayName,
598
+ persona_name: chunk.channelDisplayName,
599
599
  participant_context: buildParticipantContext(primaryPersonaIdForUpdate, state),
600
600
  known_identifier_types: userIdentifierTypes,
601
601
  });
@@ -609,7 +609,7 @@ export function queuePersonUpdate(
609
609
  next_step: LLMNextStep.HandlePersonUpdate,
610
610
  data: {
611
611
  personaId: context.personaId,
612
- personaDisplayName: context.personaDisplayName,
612
+ personaDisplayName: context.channelDisplayName,
613
613
  roomId: context.roomId,
614
614
  isNewItem,
615
615
  existingItemId: existingItem?.id,
@@ -673,7 +673,7 @@ export function queueTargetedPersonUpdate(
673
673
  extraction_model?: string;
674
674
  } = {
675
675
  personaId: contextPersonaId,
676
- personaDisplayName: displayName,
676
+ channelDisplayName: displayName,
677
677
  messages_context: [],
678
678
  messages_analyze: allMessages,
679
679
  candidateName: existingItem.name,
@@ -728,7 +728,7 @@ export function queueTargetedTopicUpdate(
728
728
  const model = state.getHuman().settings?.default_model;
729
729
  const context: ExtractionContext = {
730
730
  personaId: contextPersonaId,
731
- personaDisplayName: displayName,
731
+ channelDisplayName: displayName,
732
732
  messages_context: [],
733
733
  messages_analyze: allMessages,
734
734
  roomId,
@@ -24,7 +24,6 @@ export {
24
24
  runHumanCeremony,
25
25
  } from "./ceremony.js";
26
26
  export { queueUserDedupRequest } from "./dedup-phase.js";
27
- export { queuePersonMigration } from "./person-migration.js";
28
27
  export {
29
28
  queuePersonaTopicRating,
30
29
  type PersonaTopicContext,
@@ -38,7 +38,7 @@ export function queuePersonaTopicRating(
38
38
  const { chunks } = chunkExtractionContext(
39
39
  {
40
40
  personaId: context.personaId,
41
- personaDisplayName: context.personaDisplayName,
41
+ channelDisplayName: context.personaDisplayName,
42
42
  messages_context: context.messages_context,
43
43
  messages_analyze: context.messages_analyze,
44
44
  },