ei-tui 1.6.1 → 1.6.3
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 +21 -6
- package/package.json +1 -1
- package/src/cli/README.md +11 -7
- package/src/cli/mcp.ts +3 -3
- package/src/cli/retrieval.ts +44 -0
- package/src/cli.ts +352 -14
- package/src/core/context-utils.ts +0 -1
- package/src/core/orchestrators/ceremony.ts +1 -1
- package/src/core/processor.ts +150 -0
- package/src/core/types/data-items.ts +1 -1
- package/src/core/types/entities.ts +2 -0
- package/src/core/types/llm.ts +1 -1
- package/src/core/utils/message-id.ts +31 -0
- package/src/integrations/claude-code/importer.ts +9 -30
- package/src/integrations/claude-code/types.ts +1 -1
- package/src/integrations/codex/importer.ts +237 -0
- package/src/integrations/codex/index.ts +11 -0
- package/src/integrations/codex/reader.ts +241 -0
- package/src/integrations/codex/types.ts +117 -0
- package/src/integrations/constants.ts +3 -0
- package/src/integrations/cursor/importer.ts +9 -26
- package/src/integrations/cursor/types.ts +1 -1
- package/src/integrations/opencode/reader-factory.ts +4 -4
- package/src/integrations/pi/importer.ts +235 -0
- package/src/integrations/pi/index.ts +3 -0
- package/src/integrations/pi/reader.ts +247 -0
- package/src/integrations/pi/types.ts +151 -0
- package/src/integrations/shared/message-converter.ts +41 -0
- package/tui/README.md +5 -3
- package/tui/src/util/yaml-settings.ts +56 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Integration Types
|
|
3
|
+
*
|
|
4
|
+
* Codex Desktop / CLI stores thread metadata in ~/.codex/state_*.sqlite and
|
|
5
|
+
* per-thread rollout JSONL files under ~/.codex/sessions/YYYY/MM/DD/.
|
|
6
|
+
* Ei imports only visible user/agent event messages and skips tool chatter,
|
|
7
|
+
* prompt scaffolding, token-count events, and system/developer payloads.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Reader Interface
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export interface CodexMessageWindow {
|
|
15
|
+
message: CodexMessage;
|
|
16
|
+
before: CodexMessage[];
|
|
17
|
+
after: CodexMessage[];
|
|
18
|
+
session: CodexSession;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ICodexReader {
|
|
22
|
+
getSessions(): Promise<CodexSession[]>;
|
|
23
|
+
getMessageById(sessionId: string, messageId: string, before?: number, after?: number): Promise<CodexMessageWindow | null>;
|
|
24
|
+
isAvailable(): Promise<boolean>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Raw Storage Types
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
export interface CodexThreadRow {
|
|
32
|
+
id: string;
|
|
33
|
+
rollout_path?: string | null;
|
|
34
|
+
created_at?: number | null;
|
|
35
|
+
updated_at?: number | null;
|
|
36
|
+
created_at_ms?: number | null;
|
|
37
|
+
updated_at_ms?: number | null;
|
|
38
|
+
cwd?: string | null;
|
|
39
|
+
title?: string | null;
|
|
40
|
+
first_user_message?: string | null;
|
|
41
|
+
source?: string | null;
|
|
42
|
+
thread_source?: string | null;
|
|
43
|
+
agent_nickname?: string | null;
|
|
44
|
+
agent_role?: string | null;
|
|
45
|
+
agent_path?: string | null;
|
|
46
|
+
archived?: number | boolean | null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface CodexRolloutRecord {
|
|
50
|
+
timestamp?: string;
|
|
51
|
+
type?: string;
|
|
52
|
+
payload?: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Cleaned Session / Message Types
|
|
57
|
+
// ============================================================================
|
|
58
|
+
|
|
59
|
+
export interface CodexMessage {
|
|
60
|
+
/** Stable synthetic id derived from JSONL line number, e.g. "evt_42" */
|
|
61
|
+
id: string;
|
|
62
|
+
sessionId: string;
|
|
63
|
+
role: "user" | "assistant";
|
|
64
|
+
content: string;
|
|
65
|
+
timestamp: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface CodexSession {
|
|
69
|
+
id: string;
|
|
70
|
+
title: string;
|
|
71
|
+
cwd: string;
|
|
72
|
+
source?: string;
|
|
73
|
+
threadSource?: string;
|
|
74
|
+
agentNickname?: string;
|
|
75
|
+
agentRole?: string;
|
|
76
|
+
agentPath?: string;
|
|
77
|
+
rolloutPath: string;
|
|
78
|
+
firstMessageAt: string;
|
|
79
|
+
lastMessageAt: string;
|
|
80
|
+
messages: CodexMessage[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Constants
|
|
85
|
+
// ============================================================================
|
|
86
|
+
|
|
87
|
+
/** The single persona name for all Codex sessions */
|
|
88
|
+
export const CODEX_PERSONA_NAME = "Codex";
|
|
89
|
+
|
|
90
|
+
/** Topic groups assigned to Codex session topics */
|
|
91
|
+
export const CODEX_TOPIC_GROUPS = ["General", "Coding", "Codex"];
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Minimum session age before import.
|
|
95
|
+
* Mirrors Claude Code / Cursor's 20-minute rule so active sessions can settle.
|
|
96
|
+
*/
|
|
97
|
+
export { MIN_SESSION_AGE_MS } from "../constants.js";
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Human Settings Shape
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Stored under human.settings.codex
|
|
105
|
+
*
|
|
106
|
+
* WARNING: ADDING A NEW FIELD HERE?
|
|
107
|
+
* If it is runtime-managed (not user-editable), also preserve it in
|
|
108
|
+
* settingsFromYAML() in tui/src/util/yaml-settings.ts or /settings will wipe it.
|
|
109
|
+
*/
|
|
110
|
+
export interface CodexSettings {
|
|
111
|
+
integration?: boolean;
|
|
112
|
+
polling_interval_ms?: number;
|
|
113
|
+
extraction_model?: string;
|
|
114
|
+
last_sync?: string;
|
|
115
|
+
extraction_point?: string;
|
|
116
|
+
processed_sessions?: Record<string, string>;
|
|
117
|
+
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { StateManager } from "../../core/state-manager.js";
|
|
2
|
-
import type { Ei_Interface, Message,
|
|
2
|
+
import type { Ei_Interface, Message, PersonaEntity, PersonaTrait } from "../../core/types.js";
|
|
3
3
|
import { DEFAULT_SEED_TRAITS } from "../../core/constants/seed-traits.js";
|
|
4
4
|
import type { ICursorReader, CursorSession, CursorMessage } from "./types.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
MIN_SESSION_AGE_MS,
|
|
8
|
-
} from "./types.js";
|
|
5
|
+
import { CURSOR_PERSONA_NAME } from "./types.js";
|
|
6
|
+
import { MIN_SESSION_AGE_MS, TWELVE_HOURS_MS } from "../constants.js";
|
|
9
7
|
import { CursorReader } from "./reader.js";
|
|
10
8
|
import { isProcessRunning } from "../process-check.js";
|
|
11
9
|
import { getMachineId } from "../machine-id.js";
|
|
12
10
|
import { qualifyCursorMessage } from "../../core/utils/message-id.js";
|
|
11
|
+
import { convertToEiMessage, convertToPreMarkedEiMessage } from "../shared/message-converter.js";
|
|
13
12
|
import {
|
|
14
13
|
queueAllScans,
|
|
15
14
|
type ExtractionContext,
|
|
@@ -33,29 +32,12 @@ export interface CursorImporterOptions {
|
|
|
33
32
|
signal?: AbortSignal;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
const TWELVE_HOURS_MS = 43_200_000;
|
|
37
35
|
const CURSOR_GROUP = "Cursor";
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
id: qualifyCursorMessage(getMachineId(), sessionId, msg.id),
|
|
42
|
-
role: msg.type === 1 ? "human" : "system",
|
|
43
|
-
content: msg.text,
|
|
44
|
-
timestamp: msg.timestamp,
|
|
45
|
-
read: true,
|
|
46
|
-
context_status: "default" as ContextStatus,
|
|
47
|
-
external: true,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
37
|
+
const qualify = qualifyCursorMessage;
|
|
50
38
|
|
|
51
|
-
function
|
|
52
|
-
return {
|
|
53
|
-
...convertToEiMessage(msg, sessionId),
|
|
54
|
-
f: true,
|
|
55
|
-
t: true,
|
|
56
|
-
p: true,
|
|
57
|
-
e: true,
|
|
58
|
-
};
|
|
39
|
+
function normalizeCursorMessage(msg: CursorMessage) {
|
|
40
|
+
return { id: msg.id, role: (msg.type === 1 ? "user" : "assistant") as "user" | "assistant", content: msg.text, timestamp: msg.timestamp };
|
|
59
41
|
}
|
|
60
42
|
|
|
61
43
|
function ensureCursorPersona(
|
|
@@ -209,7 +191,8 @@ export async function importCursorSessions(
|
|
|
209
191
|
for (const msg of messages) {
|
|
210
192
|
const msgMs = new Date(msg.timestamp).getTime();
|
|
211
193
|
const isOld = cutoffMs !== null && msgMs < cutoffMs;
|
|
212
|
-
const
|
|
194
|
+
const normalized = normalizeCursorMessage(msg);
|
|
195
|
+
const eiMsg = isOld ? convertToPreMarkedEiMessage(normalized, targetSession.id, qualify) : convertToEiMessage(normalized, targetSession.id, qualify);
|
|
213
196
|
stateManager.messages_append(persona.id, eiMsg);
|
|
214
197
|
result.messagesImported++;
|
|
215
198
|
if (!isOld) toAnalyze.push(eiMsg);
|
|
@@ -116,7 +116,7 @@ export const CURSOR_TOPIC_GROUPS = ["General", "Coding", "Cursor"];
|
|
|
116
116
|
* Minimum session age before we import it.
|
|
117
117
|
* Mirrors ClaudeCode's 20-minute rule — gives the session time to "settle."
|
|
118
118
|
*/
|
|
119
|
-
export
|
|
119
|
+
export { MIN_SESSION_AGE_MS } from "../constants.js";
|
|
120
120
|
|
|
121
121
|
// ============================================================================
|
|
122
122
|
// Human Settings Shape
|
|
@@ -11,19 +11,19 @@ export async function createOpenCodeReader(basePath?: string): Promise<IOpenCode
|
|
|
11
11
|
if (existsSync(dbPath)) {
|
|
12
12
|
try {
|
|
13
13
|
const { SqliteReader } = await import("./sqlite-reader.js");
|
|
14
|
-
console.
|
|
14
|
+
console.error("[OpenCode] Using SQLite reader");
|
|
15
15
|
return new SqliteReader(dbPath);
|
|
16
16
|
} catch {
|
|
17
|
-
console.
|
|
17
|
+
console.error("[OpenCode] SQLite not available, falling back to JSON reader");
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
if (existsSync(storagePath)) {
|
|
22
|
-
console.
|
|
22
|
+
console.error("[OpenCode] Using JSON reader (legacy)");
|
|
23
23
|
return new JsonReader(storagePath);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
console.
|
|
26
|
+
console.error("[OpenCode] No OpenCode data found");
|
|
27
27
|
return new JsonReader(storagePath);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import type { StateManager } from "../../core/state-manager.js";
|
|
2
|
+
import type { Ei_Interface, Message, PersonaEntity, PersonaTrait } from "../../core/types.js";
|
|
3
|
+
import { DEFAULT_SEED_TRAITS } from "../../core/constants/seed-traits.js";
|
|
4
|
+
import {
|
|
5
|
+
queueAllScans,
|
|
6
|
+
type ExtractionContext,
|
|
7
|
+
} from "../../core/orchestrators/human-extraction.js";
|
|
8
|
+
import {
|
|
9
|
+
queuePersonRewritePhase,
|
|
10
|
+
queueTopicRewritePhase,
|
|
11
|
+
} from "../../core/orchestrators/ceremony.js";
|
|
12
|
+
import { qualifyPiMessage } from "../../core/utils/message-id.js";
|
|
13
|
+
import { convertToEiMessage, convertToPreMarkedEiMessage } from "../shared/message-converter.js";
|
|
14
|
+
import { getMachineId } from "../machine-id.js";
|
|
15
|
+
import { isProcessRunning } from "../process-check.js";
|
|
16
|
+
import { PiReader } from "./reader.js";
|
|
17
|
+
import {
|
|
18
|
+
PI_PERSONA_NAME,
|
|
19
|
+
type PiSession,
|
|
20
|
+
type IPiReader,
|
|
21
|
+
} from "./types.js";
|
|
22
|
+
import { MIN_SESSION_AGE_MS, TWELVE_HOURS_MS } from "../constants.js";
|
|
23
|
+
|
|
24
|
+
export interface PiImportResult {
|
|
25
|
+
sessionsProcessed: number;
|
|
26
|
+
messagesImported: number;
|
|
27
|
+
personaCreated: boolean;
|
|
28
|
+
extractionScansQueued: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface PiImporterOptions {
|
|
32
|
+
stateManager: StateManager;
|
|
33
|
+
interface?: Ei_Interface;
|
|
34
|
+
reader?: IPiReader;
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const PI_GROUP = "Pi";
|
|
39
|
+
|
|
40
|
+
const qualify = qualifyPiMessage;
|
|
41
|
+
|
|
42
|
+
function ensurePiPersona(
|
|
43
|
+
stateManager: StateManager,
|
|
44
|
+
eiInterface?: Ei_Interface
|
|
45
|
+
): PersonaEntity {
|
|
46
|
+
const existing = stateManager.persona_getByName(PI_PERSONA_NAME);
|
|
47
|
+
if (existing) return existing;
|
|
48
|
+
|
|
49
|
+
const now = new Date().toISOString();
|
|
50
|
+
const seedTraits: PersonaTrait[] = DEFAULT_SEED_TRAITS.map((t) => ({
|
|
51
|
+
id: crypto.randomUUID(),
|
|
52
|
+
name: t.name,
|
|
53
|
+
description: t.description,
|
|
54
|
+
sentiment: t.sentiment,
|
|
55
|
+
strength: t.strength,
|
|
56
|
+
last_updated: now,
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
const persona: PersonaEntity = {
|
|
60
|
+
id: crypto.randomUUID(),
|
|
61
|
+
display_name: PI_PERSONA_NAME,
|
|
62
|
+
entity: "system",
|
|
63
|
+
aliases: ["pi", "pi coding agent", "omp", "oh-my-pi"],
|
|
64
|
+
short_description: "Pi - minimal terminal coding harness",
|
|
65
|
+
long_description:
|
|
66
|
+
"Pi is a minimal terminal coding harness. Covers both vanilla Pi (earendil-works/pi) and the oh-my-pi fork (omp), which share the same JSONL session format.",
|
|
67
|
+
group_primary: PI_GROUP,
|
|
68
|
+
groups_visible: [PI_GROUP],
|
|
69
|
+
traits: seedTraits,
|
|
70
|
+
topics: [],
|
|
71
|
+
is_paused: false,
|
|
72
|
+
is_archived: false,
|
|
73
|
+
is_static: false,
|
|
74
|
+
heartbeat_delay_ms: TWELVE_HOURS_MS,
|
|
75
|
+
last_heartbeat: now,
|
|
76
|
+
last_updated: now,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
stateManager.persona_add(persona);
|
|
80
|
+
eiInterface?.onPersonaAdded?.();
|
|
81
|
+
return persona;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function updateProcessedState(stateManager: StateManager, session: PiSession): void {
|
|
85
|
+
const human = stateManager.getHuman();
|
|
86
|
+
const lastMessageMs = new Date(session.lastMessageAt).getTime();
|
|
87
|
+
const extractionPoint = human.settings?.pi?.extraction_point;
|
|
88
|
+
const currentPointMs = extractionPoint ? new Date(extractionPoint).getTime() : 0;
|
|
89
|
+
const newPointMs = Math.max(currentPointMs, lastMessageMs);
|
|
90
|
+
|
|
91
|
+
const processedSessions = {
|
|
92
|
+
...(human.settings?.pi?.processed_sessions ?? {}),
|
|
93
|
+
[session.id]: new Date().toISOString(),
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
stateManager.setHuman({
|
|
97
|
+
...human,
|
|
98
|
+
settings: {
|
|
99
|
+
...human.settings,
|
|
100
|
+
pi: {
|
|
101
|
+
...human.settings?.pi,
|
|
102
|
+
extraction_point: new Date(newPointMs).toISOString(),
|
|
103
|
+
processed_sessions: processedSessions,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function isPiRunning(): Promise<boolean> {
|
|
110
|
+
return (
|
|
111
|
+
(await isProcessRunning("pi")) ||
|
|
112
|
+
(await isProcessRunning("omp"))
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function importPiSessions(options: PiImporterOptions): Promise<PiImportResult> {
|
|
117
|
+
const { stateManager, interface: eiInterface, signal } = options;
|
|
118
|
+
const reader = options.reader ?? new PiReader();
|
|
119
|
+
|
|
120
|
+
const result: PiImportResult = {
|
|
121
|
+
sessionsProcessed: 0,
|
|
122
|
+
messagesImported: 0,
|
|
123
|
+
personaCreated: false,
|
|
124
|
+
extractionScansQueued: 0,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const allSessions = await reader.getSessions();
|
|
128
|
+
if (signal?.aborted) return result;
|
|
129
|
+
|
|
130
|
+
const human = stateManager.getHuman();
|
|
131
|
+
const processedSessions = human.settings?.pi?.processed_sessions ?? {};
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
const toolRunning = await isPiRunning();
|
|
134
|
+
|
|
135
|
+
let targetSession: PiSession | null = null;
|
|
136
|
+
|
|
137
|
+
for (const session of allSessions) {
|
|
138
|
+
const sessionLastMs = new Date(session.lastMessageAt).getTime();
|
|
139
|
+
const ageMs = now - sessionLastMs;
|
|
140
|
+
|
|
141
|
+
if (ageMs < MIN_SESSION_AGE_MS && toolRunning) continue;
|
|
142
|
+
|
|
143
|
+
const lastImported = processedSessions[session.id];
|
|
144
|
+
if (lastImported && sessionLastMs <= new Date(lastImported).getTime()) continue;
|
|
145
|
+
|
|
146
|
+
targetSession = session;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!targetSession) {
|
|
151
|
+
console.log("[Pi] All sessions processed, nothing new to import");
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (signal?.aborted) return result;
|
|
156
|
+
|
|
157
|
+
console.log(
|
|
158
|
+
`[Pi] Processing session: "${targetSession.title}" ` +
|
|
159
|
+
`(last message: ${targetSession.lastMessageAt})`
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const messages = targetSession.messages;
|
|
163
|
+
if (messages.length === 0) {
|
|
164
|
+
updateProcessedState(stateManager, targetSession);
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (signal?.aborted) return result;
|
|
169
|
+
|
|
170
|
+
const personaExistedBefore = stateManager.persona_getByName(PI_PERSONA_NAME) !== null;
|
|
171
|
+
const persona = ensurePiPersona(stateManager, eiInterface);
|
|
172
|
+
result.personaCreated = !personaExistedBefore;
|
|
173
|
+
|
|
174
|
+
if (!personaExistedBefore) {
|
|
175
|
+
stateManager.persona_archive(persona.id);
|
|
176
|
+
} else {
|
|
177
|
+
const existingMsgs = stateManager.messages_get(persona.id);
|
|
178
|
+
const externalIds = existingMsgs.filter((m) => m.external === true).map((m) => m.id);
|
|
179
|
+
if (externalIds.length > 0) {
|
|
180
|
+
stateManager.messages_remove(persona.id, externalIds);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const cutoffIso = processedSessions[targetSession.id] ?? null;
|
|
185
|
+
const cutoffMs = cutoffIso ? new Date(cutoffIso).getTime() : null;
|
|
186
|
+
const toAnalyze: Message[] = [];
|
|
187
|
+
|
|
188
|
+
for (const msg of messages) {
|
|
189
|
+
const msgMs = new Date(msg.timestamp).getTime();
|
|
190
|
+
const isOld = cutoffMs !== null && msgMs < cutoffMs;
|
|
191
|
+
const eiMsg = isOld
|
|
192
|
+
? convertToPreMarkedEiMessage(msg, targetSession.id, qualify)
|
|
193
|
+
: convertToEiMessage(msg, targetSession.id, qualify);
|
|
194
|
+
|
|
195
|
+
stateManager.messages_append(persona.id, eiMsg);
|
|
196
|
+
result.messagesImported++;
|
|
197
|
+
if (!isOld) toAnalyze.push(eiMsg);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
stateManager.messages_sort(persona.id);
|
|
201
|
+
eiInterface?.onMessageAdded?.(persona.id);
|
|
202
|
+
|
|
203
|
+
if (toAnalyze.length > 0 && !signal?.aborted) {
|
|
204
|
+
const allInState = stateManager.messages_get(persona.id);
|
|
205
|
+
const analyzeIds = new Set(toAnalyze.map((m) => m.id));
|
|
206
|
+
const analyzeStartIndex = allInState.findIndex((m) => analyzeIds.has(m.id));
|
|
207
|
+
const contextMsgs = analyzeStartIndex > 0 ? allInState.slice(0, analyzeStartIndex) : [];
|
|
208
|
+
|
|
209
|
+
const context: ExtractionContext = {
|
|
210
|
+
personaId: persona.id,
|
|
211
|
+
channelDisplayName: persona.display_name,
|
|
212
|
+
messages_context: contextMsgs,
|
|
213
|
+
messages_analyze: toAnalyze,
|
|
214
|
+
sources: [`pi:${getMachineId()}:${targetSession.id}`],
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
queuePersonRewritePhase(stateManager);
|
|
218
|
+
queueTopicRewritePhase(stateManager);
|
|
219
|
+
queueAllScans(context, stateManager, {
|
|
220
|
+
extraction_model: human.settings?.pi?.extraction_model,
|
|
221
|
+
external_filter: "only",
|
|
222
|
+
});
|
|
223
|
+
result.extractionScansQueued += 4;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
result.sessionsProcessed = 1;
|
|
227
|
+
updateProcessedState(stateManager, targetSession);
|
|
228
|
+
|
|
229
|
+
console.log(
|
|
230
|
+
`[Pi] Session complete: ${result.messagesImported} messages imported, ` +
|
|
231
|
+
`${result.extractionScansQueued} extraction scans queued`
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
return result;
|
|
235
|
+
}
|