chat/index.js cleanup

This commit is contained in:
Storme-bit
2026-04-26 23:04:31 -07:00
parent 45db47a584
commit 696ead29f8

View File

@@ -117,7 +117,7 @@ async function getRelevantEntities(userMessage, projectId=null) {
);
return results.map((r) => r.payload).filter(Boolean);
} catch (err) {
logger.warn(
logger.debug(
"[orchestration] Entity search failed, continuing without:",
err.message,
);
@@ -125,13 +125,16 @@ async function getRelevantEntities(userMessage, projectId=null) {
}
}
async function chat(externalId, userMessage, options = {}) {
const { recentEpisodeLimit, semanticLimit, scoreThreshold, temperature, repeatPenalty, topP, topK, systemPrompt} =
appSettings.load();
async function assembleContext(externalId, userMessage) {
const settings = appSettings.load();
const { recentEpisodeLimit, semanticLimit, scoreThreshold,
temperature, repeatPenalty, topP, topK, systemPrompt } = settings;
// 1. Resolve or create session
let session = await memory.getSessionByExternalId(externalId);
if (!session) session = await memory.createSession(externalId);
// 2. Resolve project context
let projectSessionIds = null;
let activeSystemPrompt = systemPrompt ?? ORCHESTRATION.SYSTEM_PROMPT;
if (session.project_id) {
@@ -139,49 +142,41 @@ async function chat(externalId, userMessage, options = {}) {
const project = await memory.getProject(session.project_id);
if (project) {
const projectSessions = await memory.getProjectSessions(session.project_id);
if (project?.system_prompt) activeSystemPrompt = project.system_prompt;
projectSessionIds = projectSessions.map((s) => s.id);
if (project.system_prompt) activeSystemPrompt = project.system_prompt;
projectSessionIds = projectSessions.map(s => s.id);
}
} catch (err) {
logger.warn(
"[orchestration] Failed to resolve project context:",
err.message,
);
logger.warn('[orchestration] Failed to resolve project context:', err.message);
}
}
// 2. Fetch recent episodes for context
const recentEpisodes = await memory.getRecentEpisodes(
session.id,
recentEpisodeLimit,
);
// 3. Fetch recent episodes
const recentEpisodes = await memory.getRecentEpisodes(session.id, recentEpisodeLimit);
const isFirstMessage = recentEpisodes.length === 0;
const recentIds = new Set(recentEpisodes.map((e) => e.id));
const recentIds = new Set(recentEpisodes.map(e => e.id));
// 3. Semantic Search
// 4. Semantic + entity search
const semanticEpisodes = await getSemanticEpisodes(
userMessage,
session.id,
recentIds,
projectSessionIds,
{ semanticLimit, scoreThreshold },
userMessage, session.id, recentIds, projectSessionIds, { semanticLimit, scoreThreshold }
);
// 3b. Entity Search
const entities = await getRelevantEntities(userMessage, session.project_id ?? null);
// 4. Assemble prompt
const prompt = buildPrompt(
recentEpisodes,
semanticEpisodes,
entities,
userMessage,
activeSystemPrompt,
);
// 5. Assemble prompt
const prompt = buildPrompt(recentEpisodes, semanticEpisodes, entities, userMessage, activeSystemPrompt);
// 5. Run inference
const result = await inference.complete(prompt, {...options, temperature, repeatPenalty, topP, topK});
return {
session,
prompt,
isFirstMessage,
inferenceOptions: { temperature, repeatPenalty, topP, topK },
};
}
async function chat(externalId, userMessage, options = {}) {
const { session, prompt, isFirstMessage, inferenceOptions } = await assembleContext(externalId, userMessage);
const result = await inference.complete(prompt, { ...options, ...inferenceOptions });
// 6. Write episode back to memory
try {
await memory.createEpisode(
session.id, userMessage, result.text,
@@ -191,16 +186,14 @@ async function chat(externalId, userMessage, options = {}) {
} catch (err) {
logger.error('[orchestration] Failed to save episode:', err.message);
}
const allEpisodes = await memory.getRecentEpisodes(session.id, 9999);
triggerSummary(session, allEpisodes);
// 8. Auto-name on first message
if (isFirstMessage && !session.name) {
autoNameSession(externalId, userMessage, result.text).catch(() => {}); // already logged inside autoNameSession
autoNameSession(externalId, userMessage, result.text).catch(() => {});
}
// 9. Return response
return {
sessionId: externalId,
response: result.text,
@@ -210,103 +203,35 @@ async function chat(externalId, userMessage, options = {}) {
}
async function chatStream(externalId, userMessage, onChunk, options = {}) {
try {
const { recentEpisodeLimit, semanticLimit, scoreThreshold, temperature, repeatPenalty, topP, topK, systemPrompt } = appSettings.load();
let session = await memory.getSessionByExternalId(externalId);
if (!session) session = await memory.createSession(externalId);
const { session, prompt, isFirstMessage, inferenceOptions } = await assembleContext(externalId, userMessage);
let projectSessionIds = null;
let activeSystemPrompt = systemPrompt ?? ORCHESTRATION.SYSTEM_PROMPT;
if (session.project_id) {
try {
const project = await memory.getProject(session.project_id);
if (project) {
const projectSessions = await memory.getProjectSessions(
session.project_id,
);
projectSessionIds = projectSessions.map((s) => s.id);
if (project?.system_prompt) activeSystemPrompt = project.system_prompt;
}
const res = await inference.completeStream(prompt, { ...options, ...inferenceOptions });
} catch (err) {
logger.warn(
"[orchestration] Failed to resolve project context:",
err.message,
);
}
}
const recentEpisodes = await memory.getRecentEpisodes(
session.id,
recentEpisodeLimit,
);
const isFirstMessage = recentEpisodes.length === 0;
const recentIds = new Set(recentEpisodes.map((e) => e.id));
const semanticEpisodes = await getSemanticEpisodes(
userMessage,
session.id,
recentIds,
projectSessionIds,
{semanticLimit, scoreThreshold }
);
const entities = await getRelevantEntities(userMessage, session.project_id ?? null);
const prompt = buildPrompt(
recentEpisodes,
semanticEpisodes,
entities,
userMessage,
activeSystemPrompt,
);
const res = await inference.completeStream(prompt, {...options, temperature, repeatPenalty, topP, topK});
let fullText = "";
let model = "";
let tokenCount = 0;
let buffer = "";
let fullText = '', model = '', tokenCount = 0, buffer = '';
for await (const chunk of res.body) {
buffer += Buffer.from(chunk).toString("utf8");
const events = buffer.split("\n\n");
buffer = events.pop() || "";
buffer += Buffer.from(chunk).toString('utf8');
const events = buffer.split('\n\n');
buffer = events.pop() || '';
for (const event of events) {
const lines = event.split("\n");
const dataLines = lines
.filter((line) => line.startsWith("data: "))
.map((line) => line.slice(6));
const dataLines = event.split('\n')
.filter(line => line.startsWith('data: '))
.map(line => line.slice(6));
if (dataLines.length === 0) continue;
const raw = dataLines.join("\n").trim();
if (raw === "[DONE]") continue;
if (!dataLines.length) continue;
const raw = dataLines.join('\n').trim();
if (raw === '[DONE]') continue;
try {
const data = JSON.parse(raw);
if (data.response) {
fullText += data.response;
onChunk(data.response);
}
if (data.response) { fullText += data.response; onChunk(data.response); }
if (data.model) model = data.model;
if (data.done && data.tokenCount !== undefined) {
tokenCount = data.tokenCount;
}
if (data.error) {
throw new Error(data.error);
}
if (data.done && data.tokenCount !== undefined) tokenCount = data.tokenCount;
if (data.error) throw new Error(data.error);
} catch (err) {
logger.error(
"[orchestration] Failed to parse inference SSE event:",
raw,
err.message,
);
logger.error('[orchestration] Failed to parse SSE event:', raw, err.message);
}
}
}
@@ -316,9 +241,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
const allEpisodes = await memory.getRecentEpisodes(session.id, 9999);
triggerSummary(session, allEpisodes);
} else {
logger.warn(
"[orchestration] Stream finished with no assistant text; episode not saved",
);
logger.warn('[orchestration] Stream finished with no assistant text; episode not saved');
}
if (isFirstMessage && !session.name) {
@@ -327,11 +250,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
return { model, tokenCount };
} catch (err) {
logger.error(
"[orchestration] chatStream fatal error:",
err.message,
err.stack,
);
logger.error('[orchestration] chatStream fatal error:', err.message, err.stack);
throw err;
}
}