ei-tui 0.9.2 → 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.
- package/package.json +17 -1
- package/src/README.md +1 -1
- package/src/cli/commands/personas.ts +11 -2
- package/src/cli/mcp.ts +2 -2
- package/src/cli/retrieval.ts +40 -7
- package/src/cli.ts +63 -72
- package/src/core/context-utils.ts +2 -2
- package/src/core/handlers/heartbeat.ts +9 -1
- package/src/core/handlers/human-extraction.ts +4 -1
- package/src/core/handlers/human-matching.ts +5 -53
- package/src/core/handlers/index.ts +1 -51
- package/src/core/handlers/persona-generation.ts +1 -28
- package/src/core/handlers/utils.ts +2 -9
- package/src/core/heartbeat-manager.ts +4 -4
- package/src/core/message-manager.ts +6 -5
- package/src/core/orchestrators/ceremony.ts +15 -13
- package/src/core/orchestrators/extraction-chunker.ts +3 -3
- package/src/core/orchestrators/human-extraction.ts +27 -39
- package/src/core/orchestrators/index.ts +0 -1
- package/src/core/orchestrators/persona-topics.ts +1 -1
- package/src/core/orchestrators/room-extraction.ts +45 -7
- package/src/core/processor.ts +8 -21
- package/src/core/prompt-context-builder.ts +68 -36
- package/src/core/state/personas.ts +1 -17
- package/src/core/state-manager.ts +0 -66
- package/src/core/types/entities.ts +2 -3
- package/src/core/types/enums.ts +0 -2
- package/src/core/types/rooms.ts +1 -1
- package/src/integrations/claude-code/importer.ts +1 -1
- package/src/integrations/cursor/importer.ts +1 -1
- package/src/integrations/opencode/importer.ts +1 -1
- package/src/prompts/ceremony/index.ts +0 -10
- package/src/prompts/ceremony/types.ts +1 -42
- package/src/prompts/generation/index.ts +0 -3
- package/src/prompts/generation/types.ts +0 -15
- package/src/prompts/heartbeat/check.ts +18 -6
- package/src/prompts/heartbeat/types.ts +2 -1
- package/src/prompts/human/index.ts +0 -2
- package/src/prompts/human/person-update.ts +6 -23
- package/src/prompts/human/types.ts +0 -16
- package/src/prompts/index.ts +0 -19
- package/src/prompts/reflection/index.ts +36 -4
- package/src/prompts/reflection/types.ts +1 -1
- package/src/prompts/response/index.ts +5 -0
- package/src/prompts/response/sections.ts +26 -0
- package/src/prompts/response/types.ts +3 -0
- package/tui/src/commands/registry.test.ts +10 -5
- package/tui/src/globals.d.ts +57 -0
- package/tui/src/util/yaml-persona.ts +8 -4
- package/tui/src/util/yaml-settings.ts +3 -3
- package/src/core/orchestrators/person-migration.ts +0 -55
- package/src/prompts/ceremony/description-check.ts +0 -54
- package/src/prompts/ceremony/expire.ts +0 -37
- package/src/prompts/ceremony/explore.ts +0 -77
- package/src/prompts/ceremony/person-migration.ts +0 -77
- package/src/prompts/generation/descriptions.ts +0 -91
- package/src/prompts/human/fact-scan.ts +0 -150
|
@@ -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
|
-
|
|
286
|
-
|
|
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
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type ExtractionOptions,
|
|
12
12
|
} from "./human-extraction.js";
|
|
13
13
|
import { queuePersonaTopicRating, type PersonaTopicContext, type PersonaTopicOptions } from "./persona-topics.js";
|
|
14
|
-
import {
|
|
14
|
+
import { getRoomVisibleMessages, queueRoomHumanExtraction } from "./room-extraction.js";
|
|
15
15
|
import { buildRewriteScanPrompt, type RewriteItemType } from "../../prompts/ceremony/index.js";
|
|
16
16
|
import { buildReflectionCriticPrompt } from "../../prompts/reflection/index.js";
|
|
17
17
|
import { getModelForPersona } from "../heartbeat-manager.js";
|
|
@@ -75,10 +75,6 @@ export function startCeremony(state: StateManager): void {
|
|
|
75
75
|
},
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
// PHASE 1: Person Migration
|
|
79
|
-
console.log("[ceremony] Starting Phase 1: Person Migration");
|
|
80
|
-
queuePersonMigration(state);
|
|
81
|
-
|
|
82
78
|
// Check if migration work was queued
|
|
83
79
|
if (!state.queue_hasPendingCeremonies()) {
|
|
84
80
|
// No migration work found → immediately advance to Expose phase
|
|
@@ -109,7 +105,7 @@ function queueExposurePhase(personaId: string, state: StateManager, options?: Ex
|
|
|
109
105
|
if (unextractedFacts.length > 0) {
|
|
110
106
|
const context: ExtractionContext = {
|
|
111
107
|
personaId,
|
|
112
|
-
|
|
108
|
+
channelDisplayName: persona.display_name,
|
|
113
109
|
messages_context: allMessages.filter(m => m.f === true),
|
|
114
110
|
messages_analyze: unextractedFacts,
|
|
115
111
|
extraction_flag: "f",
|
|
@@ -122,7 +118,7 @@ function queueExposurePhase(personaId: string, state: StateManager, options?: Ex
|
|
|
122
118
|
if (unextractedTopics.length > 0) {
|
|
123
119
|
const context: ExtractionContext = {
|
|
124
120
|
personaId,
|
|
125
|
-
|
|
121
|
+
channelDisplayName: persona.display_name,
|
|
126
122
|
messages_context: allMessages.filter(m => m.t === true),
|
|
127
123
|
messages_analyze: unextractedTopics,
|
|
128
124
|
extraction_flag: "t",
|
|
@@ -134,7 +130,7 @@ function queueExposurePhase(personaId: string, state: StateManager, options?: Ex
|
|
|
134
130
|
if (unextractedPeople.length > 0) {
|
|
135
131
|
const context: ExtractionContext = {
|
|
136
132
|
personaId,
|
|
137
|
-
|
|
133
|
+
channelDisplayName: persona.display_name,
|
|
138
134
|
messages_context: allMessages.filter(m => m.p === true),
|
|
139
135
|
messages_analyze: unextractedPeople,
|
|
140
136
|
extraction_flag: "p",
|
|
@@ -209,20 +205,26 @@ export function handleCeremonyProgress(state: StateManager, lastPhase: number):
|
|
|
209
205
|
const rooms = state.getRoomList();
|
|
210
206
|
for (const room of rooms) {
|
|
211
207
|
if (room.mode === RoomMode.ChooseYourPath) continue;
|
|
208
|
+
|
|
209
|
+
// Human extraction (t/p) — straggler scan for messages that never hit the
|
|
210
|
+
// per-send threshold in checkAndQueueRoomExtraction
|
|
211
|
+
queueRoomHumanExtraction(state, room.id, 2);
|
|
212
|
+
|
|
213
|
+
// Persona topic rating — uses getRoomVisibleMessages so FFA rooms get all
|
|
214
|
+
// messages, not just the active path chain
|
|
215
|
+
const allRoomMessages = getRoomVisibleMessages(state, room.id);
|
|
212
216
|
for (const personaId of room.persona_ids) {
|
|
213
217
|
const shortId = personaId.slice(0, 8);
|
|
214
218
|
const unprocessedRaw = state.getRoomUnextractedMessagesForPersona(room.id, shortId);
|
|
215
219
|
if (unprocessedRaw.length === 0) continue;
|
|
216
220
|
const personaForRoom = state.persona_getById(personaId);
|
|
217
221
|
if (!personaForRoom) continue;
|
|
218
|
-
const
|
|
219
|
-
const processedIds = new Set(allRoomMessagesRaw.filter(m => !!m.persona_extracted?.[shortId]).map(m => m.id));
|
|
220
|
-
const allNormalized = normalizeRoomMessages(allRoomMessagesRaw, state);
|
|
222
|
+
const processedIds = new Set(allRoomMessages.filter(m => !!m.persona_extracted?.[shortId]).map(m => m.id));
|
|
221
223
|
const unprocessedNormalized = normalizeRoomMessages(unprocessedRaw, state);
|
|
222
224
|
const personaTopicContext: PersonaTopicContext = {
|
|
223
225
|
personaId,
|
|
224
226
|
personaDisplayName: personaForRoom.display_name,
|
|
225
|
-
messages_context:
|
|
227
|
+
messages_context: allRoomMessages.filter(m => processedIds.has(m.id)),
|
|
226
228
|
messages_analyze: unprocessedNormalized,
|
|
227
229
|
topics: personaForRoom.topics,
|
|
228
230
|
};
|
|
@@ -468,7 +470,7 @@ export function queueReflectionDrain(personaId: string, state: StateManager): vo
|
|
|
468
470
|
|
|
469
471
|
const context: ExtractionContext = {
|
|
470
472
|
personaId,
|
|
471
|
-
|
|
473
|
+
channelDisplayName: persona.display_name,
|
|
472
474
|
messages_context: allMessages.filter(m => m.p === true),
|
|
473
475
|
messages_analyze: unextractedPeople,
|
|
474
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
|
});
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
type TopicScanCandidate,
|
|
13
13
|
type ItemMatchResult,
|
|
14
14
|
type ParticipantContext,
|
|
15
|
-
type PersonaEntitySnapshot,
|
|
16
15
|
} from "../../prompts/human/index.js";
|
|
17
16
|
import { buildValidatePrompt } from "../../prompts/ceremony/dedup.js";
|
|
18
17
|
import { normalizeRoomMessages } from "../handlers/utils.js";
|
|
@@ -56,7 +55,7 @@ function buildParticipantContext(personaId: string, state: StateManager): Partic
|
|
|
56
55
|
|
|
57
56
|
export interface ExtractionContext {
|
|
58
57
|
personaId: string;
|
|
59
|
-
|
|
58
|
+
channelDisplayName: string;
|
|
60
59
|
messages_context: Message[];
|
|
61
60
|
messages_analyze: Message[];
|
|
62
61
|
extraction_flag?: "f" | "t" | "p" | "e";
|
|
@@ -100,24 +99,26 @@ function getExtractionMaxTokens(state: StateManager, options?: ExtractionOptions
|
|
|
100
99
|
export function queueFactFind(context: ExtractionContext, state: StateManager, options?: ExtractionOptions): number {
|
|
101
100
|
const human = state.getHuman();
|
|
102
101
|
const extractionModel = options?.extraction_model;
|
|
103
|
-
const missing_fact_names = human.facts
|
|
104
|
-
.filter(f => !f.description || f.description === "")
|
|
105
|
-
.map(f => f.name)
|
|
106
|
-
.filter(name => BUILT_IN_FACT_NAMES.has(name));
|
|
107
|
-
|
|
108
|
-
if (missing_fact_names.length === 0) return 0;
|
|
109
102
|
|
|
110
103
|
const { chunks } = chunkExtractionContext(context, getExtractionMaxTokens(state, options));
|
|
111
104
|
|
|
112
|
-
//
|
|
113
|
-
//
|
|
105
|
+
// Always pre-mark f — even when all facts are already known.
|
|
106
|
+
// Once we stop scanning for facts, messages must still be marked so the
|
|
107
|
+
// ceremony doesn't treat them as perpetually unprocessed.
|
|
114
108
|
for (const chunk of chunks) {
|
|
115
109
|
state.messages_markExtracted(chunk.personaId, chunk.messages_analyze.map(m => m.id), "f");
|
|
116
110
|
}
|
|
117
111
|
|
|
112
|
+
const missing_fact_names = human.facts
|
|
113
|
+
.filter(f => !f.description || f.description === "")
|
|
114
|
+
.map(f => f.name)
|
|
115
|
+
.filter(name => BUILT_IN_FACT_NAMES.has(name));
|
|
116
|
+
|
|
117
|
+
if (missing_fact_names.length === 0) return 0;
|
|
118
|
+
|
|
118
119
|
for (const chunk of chunks) {
|
|
119
120
|
const prompt = buildFactFindPrompt({
|
|
120
|
-
persona_name: chunk.
|
|
121
|
+
persona_name: chunk.channelDisplayName,
|
|
121
122
|
missing_fact_names,
|
|
122
123
|
messages_context: chunk.messages_context,
|
|
123
124
|
messages_analyze: chunk.messages_analyze,
|
|
@@ -133,7 +134,7 @@ export function queueFactFind(context: ExtractionContext, state: StateManager, o
|
|
|
133
134
|
data: {
|
|
134
135
|
...options,
|
|
135
136
|
personaId: chunk.personaId,
|
|
136
|
-
personaDisplayName: chunk.
|
|
137
|
+
personaDisplayName: chunk.channelDisplayName,
|
|
137
138
|
analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
|
|
138
139
|
extraction_flag: context.extraction_flag,
|
|
139
140
|
message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
|
|
@@ -159,7 +160,7 @@ export function queueTopicScan(context: ExtractionContext, state: StateManager,
|
|
|
159
160
|
|
|
160
161
|
for (const chunk of chunks) {
|
|
161
162
|
const prompt = buildHumanTopicScanPrompt({
|
|
162
|
-
persona_name: chunk.
|
|
163
|
+
persona_name: chunk.channelDisplayName,
|
|
163
164
|
messages_context: chunk.messages_context,
|
|
164
165
|
messages_analyze: chunk.messages_analyze,
|
|
165
166
|
participant_context: buildParticipantContext(context.personaId, state),
|
|
@@ -175,7 +176,7 @@ export function queueTopicScan(context: ExtractionContext, state: StateManager,
|
|
|
175
176
|
data: {
|
|
176
177
|
...options,
|
|
177
178
|
personaId: chunk.personaId,
|
|
178
|
-
personaDisplayName: chunk.
|
|
179
|
+
personaDisplayName: chunk.channelDisplayName,
|
|
179
180
|
analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
|
|
180
181
|
extraction_flag: context.extraction_flag,
|
|
181
182
|
message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
|
|
@@ -208,7 +209,7 @@ export function queuePersonScan(context: ExtractionContext, state: StateManager,
|
|
|
208
209
|
|
|
209
210
|
for (const chunk of chunks) {
|
|
210
211
|
const prompt = buildHumanPersonScanPrompt({
|
|
211
|
-
persona_name: chunk.
|
|
212
|
+
persona_name: chunk.channelDisplayName,
|
|
212
213
|
messages_context: chunk.messages_context,
|
|
213
214
|
messages_analyze: chunk.messages_analyze,
|
|
214
215
|
participant_context: buildParticipantContext(context.personaId, state),
|
|
@@ -225,7 +226,7 @@ export function queuePersonScan(context: ExtractionContext, state: StateManager,
|
|
|
225
226
|
data: {
|
|
226
227
|
...options,
|
|
227
228
|
personaId: chunk.personaId,
|
|
228
|
-
personaDisplayName: chunk.
|
|
229
|
+
personaDisplayName: chunk.channelDisplayName,
|
|
229
230
|
analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
|
|
230
231
|
extraction_flag: context.extraction_flag,
|
|
231
232
|
message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
|
|
@@ -272,7 +273,7 @@ export function queueDirectTopicUpdate(
|
|
|
272
273
|
existing_item: topic,
|
|
273
274
|
messages_context: chunk.messages_context,
|
|
274
275
|
messages_analyze: chunk.messages_analyze,
|
|
275
|
-
persona_name: chunk.
|
|
276
|
+
persona_name: chunk.channelDisplayName,
|
|
276
277
|
participant_context: buildParticipantContext(context.personaId, state),
|
|
277
278
|
});
|
|
278
279
|
|
|
@@ -285,7 +286,7 @@ export function queueDirectTopicUpdate(
|
|
|
285
286
|
next_step: LLMNextStep.HandleTopicUpdate,
|
|
286
287
|
data: {
|
|
287
288
|
personaId: context.personaId,
|
|
288
|
-
personaDisplayName: context.
|
|
289
|
+
personaDisplayName: context.channelDisplayName,
|
|
289
290
|
isNewItem: false,
|
|
290
291
|
existingItemId: topic.id,
|
|
291
292
|
analyze_from_timestamp: getAnalyzeFromTimestamp(chunk),
|
|
@@ -422,7 +423,7 @@ export function queueTopicUpdate(
|
|
|
422
423
|
new_topic_category: isNewItem ? context.candidateCategory : undefined,
|
|
423
424
|
messages_context: chunk.messages_context,
|
|
424
425
|
messages_analyze: chunk.messages_analyze,
|
|
425
|
-
persona_name: chunk.
|
|
426
|
+
persona_name: chunk.channelDisplayName,
|
|
426
427
|
participant_context: buildParticipantContext(primaryPersonaId, state),
|
|
427
428
|
});
|
|
428
429
|
|
|
@@ -501,7 +502,7 @@ export function queueEventSummary(
|
|
|
501
502
|
|
|
502
503
|
const context: ExtractionContext = {
|
|
503
504
|
personaId,
|
|
504
|
-
|
|
505
|
+
channelDisplayName: persona.display_name,
|
|
505
506
|
messages_context,
|
|
506
507
|
messages_analyze: windowMessages,
|
|
507
508
|
extraction_flag: "e",
|
|
@@ -511,7 +512,7 @@ export function queueEventSummary(
|
|
|
511
512
|
|
|
512
513
|
for (const chunk of chunks) {
|
|
513
514
|
const prompt = buildEventScanPrompt({
|
|
514
|
-
persona_name: chunk.
|
|
515
|
+
persona_name: chunk.channelDisplayName,
|
|
515
516
|
messages_context: chunk.messages_context,
|
|
516
517
|
messages_analyze: chunk.messages_analyze,
|
|
517
518
|
participant_context: buildParticipantContext(personaId, state),
|
|
@@ -527,7 +528,7 @@ export function queueEventSummary(
|
|
|
527
528
|
data: {
|
|
528
529
|
...options,
|
|
529
530
|
personaId: chunk.personaId,
|
|
530
|
-
personaDisplayName: chunk.
|
|
531
|
+
personaDisplayName: chunk.channelDisplayName,
|
|
531
532
|
extraction_flag: "e",
|
|
532
533
|
message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
|
|
533
534
|
},
|
|
@@ -586,18 +587,6 @@ export function queuePersonUpdate(
|
|
|
586
587
|
|
|
587
588
|
const primaryPersonaIdForUpdate = context.personaId.split("|")[0];
|
|
588
589
|
|
|
589
|
-
const linkedPersonaId = !isNewItem
|
|
590
|
-
? (existingItem?.identifiers ?? []).find(i => i.type.toLowerCase() === 'ei persona')?.value
|
|
591
|
-
: undefined;
|
|
592
|
-
const linkedPersonaEntity = linkedPersonaId ? state.persona_getById(linkedPersonaId) : undefined;
|
|
593
|
-
const personaEntitySnapshot: PersonaEntitySnapshot | undefined = linkedPersonaEntity
|
|
594
|
-
? {
|
|
595
|
-
long_description: linkedPersonaEntity.long_description ?? '',
|
|
596
|
-
traits: (linkedPersonaEntity.traits ?? []).map(t => ({ name: t.name, description: t.description })),
|
|
597
|
-
topics: (linkedPersonaEntity.topics ?? []).map(t => ({ name: t.name, perspective: t.perspective })),
|
|
598
|
-
}
|
|
599
|
-
: undefined;
|
|
600
|
-
|
|
601
590
|
for (const chunk of chunks) {
|
|
602
591
|
const prompt = buildPersonUpdatePrompt({
|
|
603
592
|
existing_item: existingItem,
|
|
@@ -606,10 +595,9 @@ export function queuePersonUpdate(
|
|
|
606
595
|
new_person_relationship: isNewItem ? context.candidateRelationship : undefined,
|
|
607
596
|
messages_context: chunk.messages_context,
|
|
608
597
|
messages_analyze: chunk.messages_analyze,
|
|
609
|
-
persona_name: chunk.
|
|
598
|
+
persona_name: chunk.channelDisplayName,
|
|
610
599
|
participant_context: buildParticipantContext(primaryPersonaIdForUpdate, state),
|
|
611
600
|
known_identifier_types: userIdentifierTypes,
|
|
612
|
-
persona_entity: personaEntitySnapshot,
|
|
613
601
|
});
|
|
614
602
|
|
|
615
603
|
state.queue_enqueue({
|
|
@@ -621,7 +609,7 @@ export function queuePersonUpdate(
|
|
|
621
609
|
next_step: LLMNextStep.HandlePersonUpdate,
|
|
622
610
|
data: {
|
|
623
611
|
personaId: context.personaId,
|
|
624
|
-
personaDisplayName: context.
|
|
612
|
+
personaDisplayName: context.channelDisplayName,
|
|
625
613
|
roomId: context.roomId,
|
|
626
614
|
isNewItem,
|
|
627
615
|
existingItemId: existingItem?.id,
|
|
@@ -685,7 +673,7 @@ export function queueTargetedPersonUpdate(
|
|
|
685
673
|
extraction_model?: string;
|
|
686
674
|
} = {
|
|
687
675
|
personaId: contextPersonaId,
|
|
688
|
-
|
|
676
|
+
channelDisplayName: displayName,
|
|
689
677
|
messages_context: [],
|
|
690
678
|
messages_analyze: allMessages,
|
|
691
679
|
candidateName: existingItem.name,
|
|
@@ -740,7 +728,7 @@ export function queueTargetedTopicUpdate(
|
|
|
740
728
|
const model = state.getHuman().settings?.default_model;
|
|
741
729
|
const context: ExtractionContext = {
|
|
742
730
|
personaId: contextPersonaId,
|
|
743
|
-
|
|
731
|
+
channelDisplayName: displayName,
|
|
744
732
|
messages_context: [],
|
|
745
733
|
messages_analyze: allMessages,
|
|
746
734
|
roomId,
|
|
@@ -38,7 +38,7 @@ export function queuePersonaTopicRating(
|
|
|
38
38
|
const { chunks } = chunkExtractionContext(
|
|
39
39
|
{
|
|
40
40
|
personaId: context.personaId,
|
|
41
|
-
|
|
41
|
+
channelDisplayName: context.personaDisplayName,
|
|
42
42
|
messages_context: context.messages_context,
|
|
43
43
|
messages_analyze: context.messages_analyze,
|
|
44
44
|
},
|
|
@@ -73,11 +73,12 @@ function queueRoomTopicScan(
|
|
|
73
73
|
messages_context: Message[],
|
|
74
74
|
messages_analyze: Message[],
|
|
75
75
|
state: StateManager,
|
|
76
|
-
participantContext: ParticipantContext
|
|
76
|
+
participantContext: ParticipantContext,
|
|
77
|
+
ceremony_progress?: number
|
|
77
78
|
): void {
|
|
78
79
|
const context: HumanExtractionContext = {
|
|
79
80
|
personaId: roomId,
|
|
80
|
-
|
|
81
|
+
channelDisplayName: roomDisplayName,
|
|
81
82
|
messages_context,
|
|
82
83
|
messages_analyze,
|
|
83
84
|
extraction_flag: "t",
|
|
@@ -105,6 +106,7 @@ function queueRoomTopicScan(
|
|
|
105
106
|
personaId: (state.getRoom(roomId)?.persona_ids ?? []).join("|"),
|
|
106
107
|
personaDisplayName: roomDisplayName,
|
|
107
108
|
message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
|
|
109
|
+
...(ceremony_progress !== undefined ? { ceremony_progress } : {}),
|
|
108
110
|
},
|
|
109
111
|
});
|
|
110
112
|
}
|
|
@@ -115,11 +117,12 @@ function queueRoomPersonScan(
|
|
|
115
117
|
roomDisplayName: string,
|
|
116
118
|
messages_context: Message[],
|
|
117
119
|
messages_analyze: Message[],
|
|
118
|
-
state: StateManager
|
|
120
|
+
state: StateManager,
|
|
121
|
+
ceremony_progress?: number
|
|
119
122
|
): void {
|
|
120
123
|
const context: HumanExtractionContext = {
|
|
121
124
|
personaId: roomId,
|
|
122
|
-
|
|
125
|
+
channelDisplayName: roomDisplayName,
|
|
123
126
|
messages_context,
|
|
124
127
|
messages_analyze,
|
|
125
128
|
extraction_flag: "p",
|
|
@@ -146,6 +149,7 @@ function queueRoomPersonScan(
|
|
|
146
149
|
personaId: (state.getRoom(roomId)?.persona_ids ?? []).join("|"),
|
|
147
150
|
personaDisplayName: roomDisplayName,
|
|
148
151
|
message_ids_to_mark: chunk.messages_analyze.map(m => m.id),
|
|
152
|
+
...(ceremony_progress !== undefined ? { ceremony_progress } : {}),
|
|
149
153
|
},
|
|
150
154
|
});
|
|
151
155
|
}
|
|
@@ -176,7 +180,7 @@ function queueRoomEventScan(
|
|
|
176
180
|
);
|
|
177
181
|
const context: HumanExtractionContext = {
|
|
178
182
|
personaId: roomId,
|
|
179
|
-
|
|
183
|
+
channelDisplayName: roomDisplayName,
|
|
180
184
|
messages_context,
|
|
181
185
|
messages_analyze: windowMessages,
|
|
182
186
|
extraction_flag: "e",
|
|
@@ -241,6 +245,40 @@ export function checkAndQueueRoomExtraction(state: StateManager, roomId: string)
|
|
|
241
245
|
console.log(`[checkAndQueueRoomExtraction] Auto-triggered extraction for room ${roomDisplayName} (threshold: ${threshold})`);
|
|
242
246
|
}
|
|
243
247
|
|
|
248
|
+
export function queueRoomHumanExtraction(state: StateManager, roomId: string, ceremony_progress?: number): void {
|
|
249
|
+
const room = state.getRoom(roomId);
|
|
250
|
+
if (!room || room.mode === RoomMode.ChooseYourPath) return;
|
|
251
|
+
|
|
252
|
+
const allVisible = getRoomVisibleMessages(state, roomId);
|
|
253
|
+
if (allVisible.length === 0) return;
|
|
254
|
+
|
|
255
|
+
const participantContext = buildRoomParticipantContext(roomId, state);
|
|
256
|
+
const roomDisplayName = room.display_name;
|
|
257
|
+
|
|
258
|
+
const unextractedT = allVisible.filter(m => !m.t);
|
|
259
|
+
const unextractedP = allVisible.filter(m => !m.p);
|
|
260
|
+
|
|
261
|
+
if (unextractedT.length === 0 && unextractedP.length === 0) return;
|
|
262
|
+
|
|
263
|
+
if (unextractedT.length > 0) {
|
|
264
|
+
const analyzeStart = unextractedT[0].timestamp;
|
|
265
|
+
const messages_contextT = allVisible.filter(
|
|
266
|
+
m => m.t === true && new Date(m.timestamp).getTime() < new Date(analyzeStart).getTime()
|
|
267
|
+
);
|
|
268
|
+
queueRoomTopicScan(roomId, roomDisplayName, messages_contextT, unextractedT, state, participantContext, ceremony_progress);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (unextractedP.length > 0) {
|
|
272
|
+
const analyzeStart = unextractedP[0].timestamp;
|
|
273
|
+
const messages_contextP = allVisible.filter(
|
|
274
|
+
m => m.p === true && new Date(m.timestamp).getTime() < new Date(analyzeStart).getTime()
|
|
275
|
+
);
|
|
276
|
+
queueRoomPersonScan(roomId, roomDisplayName, messages_contextP, unextractedP, state, ceremony_progress);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
console.log(`[queueRoomHumanExtraction] Queued human extraction for room "${roomDisplayName}" (t:${unextractedT.length}, p:${unextractedP.length})`);
|
|
280
|
+
}
|
|
281
|
+
|
|
244
282
|
export function queueRoomCapture(state: StateManager, roomId: string): void {
|
|
245
283
|
const room = state.getRoom(roomId);
|
|
246
284
|
if (!room) return;
|
|
@@ -310,7 +348,7 @@ export function queuePersonaCapture(state: StateManager, personaId: string): voi
|
|
|
310
348
|
);
|
|
311
349
|
const context: HumanExtractionContext = {
|
|
312
350
|
personaId,
|
|
313
|
-
|
|
351
|
+
channelDisplayName: persona.display_name,
|
|
314
352
|
messages_context,
|
|
315
353
|
messages_analyze: unextractedT,
|
|
316
354
|
};
|
|
@@ -324,7 +362,7 @@ export function queuePersonaCapture(state: StateManager, personaId: string): voi
|
|
|
324
362
|
);
|
|
325
363
|
const context: HumanExtractionContext = {
|
|
326
364
|
personaId,
|
|
327
|
-
|
|
365
|
+
channelDisplayName: persona.display_name,
|
|
328
366
|
messages_context,
|
|
329
367
|
messages_analyze: unextractedP,
|
|
330
368
|
};
|
package/src/core/processor.ts
CHANGED
|
@@ -877,8 +877,8 @@ export class Processor {
|
|
|
877
877
|
modified = true;
|
|
878
878
|
}
|
|
879
879
|
|
|
880
|
-
if (human.settings.
|
|
881
|
-
human.settings.
|
|
880
|
+
if (human.settings.default_context_window_ms == null) {
|
|
881
|
+
human.settings.default_context_window_ms = 28800000;
|
|
882
882
|
modified = true;
|
|
883
883
|
}
|
|
884
884
|
|
|
@@ -1044,7 +1044,6 @@ const toolNextSteps = new Set([
|
|
|
1044
1044
|
LLMNextStep.HandleEiHeartbeat,
|
|
1045
1045
|
LLMNextStep.HandleToolContinuation,
|
|
1046
1046
|
LLMNextStep.HandleDedupCurate,
|
|
1047
|
-
LLMNextStep.HandlePersonIdentifierMigration,
|
|
1048
1047
|
]);
|
|
1049
1048
|
const toolPersonaId =
|
|
1050
1049
|
personaId ??
|
|
@@ -1059,13 +1058,8 @@ const toolNextSteps = new Set([
|
|
|
1059
1058
|
(request.next_step === LLMNextStep.HandleToolContinuation &&
|
|
1060
1059
|
request.data.originalNextStep === LLMNextStep.HandleDedupCurate);
|
|
1061
1060
|
|
|
1062
|
-
const isPersonMigrationRequest =
|
|
1063
|
-
request.next_step === LLMNextStep.HandlePersonIdentifierMigration ||
|
|
1064
|
-
(request.next_step === LLMNextStep.HandleToolContinuation &&
|
|
1065
|
-
request.data.originalNextStep === LLMNextStep.HandlePersonIdentifierMigration);
|
|
1066
|
-
|
|
1067
1061
|
let tools: ToolDefinition[] = [];
|
|
1068
|
-
if (isDedupRequest
|
|
1062
|
+
if (isDedupRequest) {
|
|
1069
1063
|
const readMemory = this.stateManager.tools_getByName("read_memory");
|
|
1070
1064
|
if (readMemory?.enabled) {
|
|
1071
1065
|
tools = [readMemory];
|
|
@@ -1201,14 +1195,14 @@ const toolNextSteps = new Set([
|
|
|
1201
1195
|
|
|
1202
1196
|
if (timeSinceHeartbeat >= heartbeatDelay) {
|
|
1203
1197
|
const history = this.stateManager.messages_get(persona.id);
|
|
1204
|
-
const
|
|
1205
|
-
persona.
|
|
1206
|
-
?? this.stateManager.getHuman().settings?.
|
|
1207
|
-
??
|
|
1198
|
+
const contextWindowMs =
|
|
1199
|
+
persona.context_window_ms
|
|
1200
|
+
?? this.stateManager.getHuman().settings?.default_context_window_ms
|
|
1201
|
+
?? 28800000;
|
|
1208
1202
|
const contextHistory = filterMessagesForContext(
|
|
1209
1203
|
history,
|
|
1210
1204
|
persona.context_boundary,
|
|
1211
|
-
|
|
1205
|
+
contextWindowMs
|
|
1212
1206
|
);
|
|
1213
1207
|
const trailing = countTrailingPersonaMessages(contextHistory);
|
|
1214
1208
|
if (trailing < 3) {
|
|
@@ -1621,13 +1615,6 @@ const toolNextSteps = new Set([
|
|
|
1621
1615
|
}
|
|
1622
1616
|
}
|
|
1623
1617
|
|
|
1624
|
-
if (response.request.next_step === LLMNextStep.HandlePersonaDescriptions) {
|
|
1625
|
-
const personaId = response.request.data.personaId as string;
|
|
1626
|
-
if (personaId) {
|
|
1627
|
-
this.interface.onPersonaUpdated?.(personaId);
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
1618
|
if (
|
|
1632
1619
|
response.request.next_step === LLMNextStep.HandlePersonaTraitExtraction ||
|
|
1633
1620
|
response.request.next_step === LLMNextStep.HandlePersonaTopicRating
|