logger updates

This commit is contained in:
Storme-bit
2026-04-26 22:28:54 -07:00
parent c86b565eed
commit 86e78cc4c6
23 changed files with 87 additions and 67 deletions

View File

@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(grep -E \"^d|^-.*\\\\.\\(json|md\\)$\")"
]
}
}

View File

@@ -1,4 +1,5 @@
import { API_DEFAULTS } from "../config/constants";
import { logger } from "@nexusai/shared";
const BASE_URL = import.meta.env.VITE_ORCHESTRATION_URL ?? '';
@@ -78,7 +79,7 @@ export function streamMessage(sessionId, message, model, { onChunk, onDone, onEr
if (data.done) onDone({ model: data.model ?? model, tokenCount: data.tokenCount ?? 0 });
if (data.error) onError(new Error(data.error));
} catch (err) {
console.error('[chat-client] Failed to parse SSE event:', raw, err);
logger.error('[chat-client] Failed to parse SSE event:', raw, err);
}
}
}

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { fetchSessions, deleteSession } from '../api/orchestration';
import { CLIENT_DEFAULTS } from '../config/constants';
const { logger } = require('@nexusai/shared');
const PAGE_SIZE = CLIENT_DEFAULTS.PAGE_SIZE;
@@ -25,7 +26,7 @@ export default function AllChatsView({ onSelectSession, onBack, projects }) {
setSessions(data);
setTotal(data.length === PAGE_SIZE ? (p + 2) * PAGE_SIZE : p * PAGE_SIZE + data.length);
} catch (err) {
console.error('[AllChatsView] Failed to load sessions:', err.message);
logger.error('[AllChatsView] Failed to load sessions:', err.message);
} finally {
setLoading(false);
}
@@ -54,7 +55,7 @@ export default function AllChatsView({ onSelectSession, onBack, projects }) {
setConfirmOpen(false);
await loadPage(page);
} catch (err) {
console.error('[AllChatsView] Bulk delete failed:', err.message);
logger.error('[AllChatsView] Bulk delete failed:', err.message);
} finally {
setDeleting(false);
}

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import ProjectModal from './ProjectModal';
import { fetchProjects, createProject, updateProject, deleteProject } from '../api/orchestration';
const { logger } = require('@nexusai/shared');
export default function AllProjectsView({ onProjectsChange, onBack, onSelectProject, onNavigate }) {
const [projects, setProjects] = useState([]);
@@ -14,7 +15,7 @@ export default function AllProjectsView({ onProjectsChange, onBack, onSelectProj
try {
setProjects(await fetchProjects());
} catch (err) {
console.error('[AllProjectsView] Failed to load:', err.message);
logger.error('[AllProjectsView] Failed to load:', err.message);
} finally {
setLoading(false);
}
@@ -30,7 +31,7 @@ async function handleSave({ name, description, colour, icon }) {
await load();
onProjectsChange?.(); // add this
} catch (err) {
console.error('[AllProjectsView] Save failed:', err.message);
logger.error('[AllProjectsView] Save failed:', err.message);
}
}
@@ -40,7 +41,7 @@ async function handleDelete(id) {
await load();
onProjectsChange?.(); // add this
} catch (err) {
console.error('[AllProjectsView] Delete failed:', err.message);
logger.error('[AllProjectsView] Delete failed:', err.message);
}
}

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { fetchSessions, updateProject, deleteProject, generateProjectSummary, fetchProjectOverviewSummary } from '../api/orchestration';
import ProjectModal from './ProjectModal';
const { logger } = require('@nexusai/shared');
export default function ProjectView({ project, onNavigate, onBack, onSelectSession, onNewProjectChat, onProjectsChange }) {
const [sessions, setSessions] = useState([]);
@@ -21,7 +22,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi
try {
setOverview(await fetchProjectOverviewSummary(project.id));
} catch (err) {
console.error('[ProjectView] Failed to load overview:', err.message);
logger.error('[ProjectView] Failed to load overview:', err.message);
} finally {
setOverviewLoading(false);
}
@@ -34,7 +35,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi
try {
setSessions(await fetchSessions(50, 0, project.id));
} catch (err) {
console.error('[ProjectView] Failed to load sessions:', err.message);
logger.error('[ProjectView] Failed to load sessions:', err.message);
} finally {
setLoading(false);
}
@@ -60,7 +61,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi
onProjectsChange?.();
setModal(null);
} catch (err) {
console.error('[ProjectView] Update failed:', err.message);
logger.error('[ProjectView] Update failed:', err.message);
}
}
@@ -70,7 +71,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi
onProjectsChange?.();
onBack();
} catch (err) {
console.error('[ProjectView] Delete failed:', err.message);
logger.error('[ProjectView] Delete failed:', err.message);
}
}
@@ -375,7 +376,7 @@ function NotesSection({ projectId, initialNotes }) {
await updateProject(projectId, { notes });
setSavedNotes(notes);
} catch (err) {
console.error('[NotesSection] Save failed:', err.message);
logger.error('[NotesSection] Save failed:', err.message);
} finally {
setSaving(false);
}

View File

@@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import { useSettings } from '../hooks/useSettings';
import { useModels } from '../hooks/useModels';
import { getServiceHealth } from '../api/orchestration';
const { logger } = require('@nexusai/shared');
export default function SettingsView({ onNavigate, onBack, modelProps }) {
const { settings, saveSetting, saving } = useSettings();
@@ -276,7 +277,7 @@ function ServiceHealth() {
setServices(await getServiceHealth());
setLastChecked(new Date());
} catch (err) {
console.error('[ServiceHealth]', err.message);
logger.error('[ServiceHealth]', err.message);
} finally {
setLoading(false);
}

View File

@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import SessionModal from './SessionModal';
import { useContextMenu } from '../hooks/useContextMenu';
import { renameSession, deleteSession, updateSession } from '../api/orchestration';
const { logger } = require('@nexusai/shared');
export default function Sidebar({
@@ -32,7 +33,7 @@ export default function Sidebar({
await updateSession(session.external_id, { name, projectId });
onSessionsChange();
} catch (err) {
console.error('[Sidebar] Rename failed:', err.message);
logger.error('[Sidebar] Rename failed:', err.message);
}
}
@@ -41,7 +42,7 @@ export default function Sidebar({
await deleteSession(session.external_id);
onSessionsChange(session);
} catch (err) {
console.error('[Sidebar] Delete failed:', err.message);
logger.error('[Sidebar] Delete failed:', err.message);
}
}

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState, useCallback, useRef } from 'react';
import { streamMessage, updateSession } from '../api/orchestration';
const { logger } = require('@nexusai/shared');
export function useChat({ activeSession, appendMessage, updateLastMessage, refreshSessions }) {
const [streaming, setStreaming] = useState(false);
@@ -73,7 +74,7 @@ export function useChat({ activeSession, appendMessage, updateLastMessage, refre
// Assign project after first message if one was set
if (projectId) {
updateSession(targetSession.external_id, { projectId })
.catch(err => console.warn('[useChat] Failed to assign project:', err.message));
.catch(err => logger.warn('[useChat] Failed to assign project:', err.message));
}
},

View File

@@ -2,6 +2,7 @@
import { useState, useEffect } from 'react';
import { fetchModels } from '../api/orchestration';
import { FALLBACK_MODELS, DEFAULT_MODEL } from '../config/constants';
const { logger } = require('@nexusai/shared');
export function useModels() {
const [models, setModels] = useState(FALLBACK_MODELS);
@@ -15,7 +16,7 @@ export function useModels() {
setSelectedModel(data[0]?.value ?? DEFAULT_MODEL);
})
.catch(err => {
console.warn('[useModels] Falling back to static list:', err.message);
logger.warn('[useModels] Falling back to static list:', err.message);
})
.finally(() => setLoading(false));
}, []);

View File

@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { fetchProjects } from '../api/orchestration';
const { logger } = require('@nexusai/shared');
export function useProjects() {
const [projects, setProjects] = useState([]);
@@ -8,7 +9,7 @@ export function useProjects() {
try {
setProjects(await fetchProjects());
} catch (err) {
console.warn('[useProjects] Failed to load projects:', err.message);
logger.warn('[useProjects] Failed to load projects:', err.message);
}
}, []);

View File

@@ -1,12 +1,13 @@
import { useState, useEffect } from 'react';
import { getSettings, updateSettings } from '../api/orchestration';
const { logger } = require('@nexusai/shared');
export function useSettings() {
const [settings, setSettings] = useState(null);
const [saving, setSaving] = useState(false);
useEffect(() => {
getSettings().then(setSettings).catch(console.error);
getSettings().then(setSettings).catch(logger.error);
}, []);
async function saveSetting(key, value) {
@@ -15,7 +16,7 @@ export function useSettings() {
const updated = await updateSettings({ [key]: value });
setSettings(updated);
} catch (err) {
console.error('[useSettings] Save failed:', err.message);
logger.error('[useSettings] Save failed:', err.message);
} finally {
setSaving(false);
}

View File

@@ -1,6 +1,6 @@
require ('dotenv').config();
const express = require('express');
const {getEnv, PORTS, OLLAMA} = require('@nexusai/shared');
const {getEnv, PORTS, OLLAMA, logger} = require('@nexusai/shared');
const inferenceRouter = require('./routes/inference');
const app = express();
@@ -24,5 +24,5 @@ app.use('/', inferenceRouter);
// Start the server
app.listen(PORT, () => {
console.log(`Inference Service is running on port ${PORT}`);
logger.info(`Inference Service is running on port ${PORT}`);
});

View File

@@ -1,4 +1,4 @@
const { getEnv, LLAMACPP, INFERENCE_DEFAULTS } = require("@nexusai/shared");
const { getEnv, LLAMACPP, INFERENCE_DEFAULTS, logger } = require("@nexusai/shared");
const BASE_URL = getEnv("INFERENCE_URL", LLAMACPP.DEFAULT_URL);
const DEFAULT_MODEL = getEnv("DEFAULT_MODEL", LLAMACPP.DEFAULT_MODEL);
@@ -89,7 +89,7 @@ async function* completeStream(prompt, options = {}) {
}
}
console.log('[llamacpp] finalTokenCount:', finalTokenCount);
logger.info('[llamacpp] finalTokenCount:', finalTokenCount);
yield { response: '', done: true, model: finalModel, tokenCount: finalTokenCount };
}

View File

@@ -1,5 +1,6 @@
const { Router } = require('express');
const { complete, completeStream } = require('../infer');
const { logger } = require('@nexusai/shared');
const router = Router();
@@ -15,7 +16,7 @@ router.post('/complete', async (req, res) => {
const result = await complete (prompt, {model, temperature, maxTokens, topP, topK, repeatPenalty});
res.json(result);
} catch (error) {
console.error('[Inference] Completion error:', error.message);
logger.error('[Inference] Completion error:', error.message);
res.status(500).json({ error: error.message });
}
});
@@ -42,7 +43,7 @@ router.post('/complete/stream', async (req, res) => {
// capture final metadata from the done signal
lastModel = chunk.model ?? lastModel;
tokenCount = chunk.tokenCount ?? tokenCount;
console.log('[inference router] tokenCount from chunk:', chunk.tokenCount, '→', tokenCount);
logger.info('[inference router] tokenCount from chunk:', chunk.tokenCount, '→', tokenCount);
}
}
@@ -51,7 +52,7 @@ router.post('/complete/stream', async (req, res) => {
res.write('data: [DONE]\n\n');
} catch (err) {
console.error('[Inference] Streaming error:', err.message);
logger.error('[Inference] Streaming error:', err.message);
res.write(`data: ${JSON.stringify({ error: err.message })}\n\n`);
} finally {
res.end();

View File

@@ -1,6 +1,6 @@
const Database = require('better-sqlite3');
const schema = require('./schema');
const {getEnv, SQLITE } = require('@nexusai/shared');
const {getEnv, SQLITE, logger } = require('@nexusai/shared');
let db; // Declare db variable in a scope accessible to all functions
@@ -62,7 +62,7 @@ function getDB() {
db.exec(`INSERT OR REPLACE INTO episodes_fts(rowid, user_message, ai_response)
SELECT id, user_message, ai_response FROM episodes`);
console.log(`Connected to SQLite database at ${path}`);
logger.info(`Connected to SQLite database at ${path}`);
}
return db;
}

View File

@@ -1,5 +1,5 @@
const semantic = require('../semantic')
const { getEnv, SERVICES, formatEpisodeText, ENTITIES } = require('@nexusai/shared');
const { getEnv, SERVICES, formatEpisodeText, ENTITIES, logger } = require('@nexusai/shared');
const { upsertEntity } = require('./index');
const EXTRACTION_URL = getEnv('EXTRACTION_URL', 'http://localhost:11434');
@@ -59,7 +59,7 @@ async function embedEntity(entity) {
}
async function extractAndStoreEntities(userMessage, aiResponse, projectId=null) {
console.log('[entities] Extraction triggered')
logger.info('[entities] Extraction triggered')
try {
// Fetch existing entities to guide the model toward consistent name/type pairs
const db = require('../db').getDB();
@@ -90,7 +90,7 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
const parsed = JSON.parse(raw);
const entities = Array.isArray(parsed.entities) ? parsed.entities : [];
if (entities.length === 0) {
console.log('[entities] No entities found in this exchange — skipping');
logger.debug('[entities] No entities found in this exchange — skipping');
return; // not an error, just nothing to extract
}
@@ -105,7 +105,7 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
if (IGNORED_NAMES.includes(name.toLowerCase())) continue;
const entity = upsertEntity(name, type, notes ?? null);
console.log('[entities] Upserted entity:', entity);
logger.info('[entities] Upserted entity:', entity);
// Embed and upsert to Qdrant fire-and-forget
embedEntity(entity)
@@ -116,17 +116,17 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null)
projectId: projectId ?? null,
}))
.catch(err => {
console.warn(`[entities] Failed to embed entity "${entity.name}":`, err.message);
logger.warn(`[entities] Failed to embed entity "${entity.name}":`, err.message);
});
saved++;
}
if (saved > 0) console.log(`[entities] Extracted and stored ${saved} entities`);
if (saved > 0) logger.info(`[entities] Extracted and stored ${saved} entities`);
} catch (err) {
// Non-critical — log and move on, episode is already saved
console.warn('[entities] Extraction failed:', err.message);
logger.warn('[entities] Extraction failed:', err.message);
}
}

View File

@@ -1,5 +1,5 @@
const {getDB} = require('../db');
const { EPISODIC, getEnv, SERVICES, parseRow, formatEpisodeText, SUMMARIES } = require('@nexusai/shared');
const { EPISODIC, getEnv, SERVICES, parseRow, formatEpisodeText, SUMMARIES, logger } = require('@nexusai/shared');
const semantic = require('../semantic');
const { extractAndStoreEntities } = require('../entities/extraction')
@@ -125,10 +125,10 @@ async function createEpisode(sessionId, userMessage, aiResponse, tokenCount = nu
sessionId: episode.session_id,
createdAt: episode.created_at
}))
.catch(err => console.error(`Failed to embed episode ${episode.id}:`, err.message));
.catch(err => logger.error(`Failed to embed episode ${episode.id}:`, err.message));
extractAndStoreEntities(userMessage, aiResponse, projectId)
.catch(err => console.error(`Failed to extract entities for episode ${episode.id}:`, err.message));
.catch(err => logger.error(`Failed to extract entities for episode ${episode.id}:`, err.message));
return episode;

View File

@@ -1,6 +1,6 @@
require ('dotenv').config();
const express = require('express');
const {getEnv, PORTS, EPISODIC} = require('@nexusai/shared');
const {getEnv, PORTS, EPISODIC, logger} = require('@nexusai/shared');
const { getDB } = require('./db');
const { createProject, getProjects, getProject, updateProject, deleteProject } = require('./db/projects');
const { createSummary, getSummary, getSummariesBySession, getSummariesByProject, updateSummary, deleteSummary } = require('./db/summaries');
@@ -19,8 +19,8 @@ const PORT = getEnv('PORT', PORTS.MEMORY);
const db = getDB();
semantic.initCollections()
.then(() => console.log(`QDrant collections ready`))
.catch(err => console.error(`QDrant initialization error:`, err.message));
.then(() => logger.info(`QDrant collections ready`))
.catch(err => logger.error(`QDrant initialization error:`, err.message));
// Health check endpoint
app.get('/health', (req, res) => {
@@ -158,7 +158,7 @@ app.delete('/episodes/:id', (req, res) => {
episodic.deleteEpisode(id);
semantic.deleteEpisode(id) // fire-and-forget
.catch(err => console.error(`[Memory] Qdrant delete failed for episode ${id}:`, err.message));
.catch(err => logger.error(`[Memory] Qdrant delete failed for episode ${id}:`, err.message));
res.status(204).send();
});
@@ -338,5 +338,5 @@ app.delete('/summaries/:id', (req, res) => {
/********** Start Server ********** */
/********************************** */
app.listen(PORT, () => {
console.log(`Memory Service is running on port ${PORT}`);
logger.info(`Memory Service is running on port ${PORT}`);
});

View File

@@ -1,5 +1,5 @@
const {QdrantClient} = require('@qdrant/js-client-rest');
const {QDRANT, COLLECTIONS, getEnv} = require('@nexusai/shared');
const {QDRANT, COLLECTIONS, getEnv, logger} = require('@nexusai/shared');
let client;
@@ -24,9 +24,9 @@ async function initCollections() {
distance: QDRANT.DISTANCE_METRIC
}
});
console.log(`Created Qdrant collection: ${name}`);
logger.info(`Created Qdrant collection: ${name}`);
} else {
console.log(`Qdrant collection already exists: ${name}`);
logger.info(`Qdrant collection already exists: ${name}`);
}
}
}

View File

@@ -2,7 +2,7 @@ const memory = require("../services/memory");
const inference = require("../services/inference");
const embedding = require("../services/embedding");
const qdrant = require("../services/qdrant");
const { ORCHESTRATION } = require("@nexusai/shared");
const { ORCHESTRATION, logger } = require("@nexusai/shared");
const appSettings = require("../config/settings");
const {triggerSummary} = require('../services/summarization')
@@ -64,12 +64,12 @@ async function autoNameSession(externalId, userMessage, aiResponse) {
const name = result.text?.trim().replace(/^["']|["']$/g, ""); // strip any quotes the model adds
if (name) {
await memory.updateSession(externalId, { name });
console.log(
logger.info(
`[orchestration] Auto-named session "${externalId}": "${name}"`,
);
}
} catch (err) {
console.warn(
logger.warn(
"[orchestration] Auto-naming failed (non-critical):",
err.message,
);
@@ -99,7 +99,7 @@ async function getSemanticEpisodes(
);
return fetched.filter(Boolean);
} catch (err) {
console.warn(
logger.warn(
`[orchestration] Semantic search failed, continuing without: `,
err.message,
);
@@ -111,13 +111,13 @@ async function getRelevantEntities(userMessage, projectId=null) {
try {
const vector = await embedding.embed(userMessage);
const results = await qdrant.searchEntities(vector, { projectId });
console.log(
logger.info(
"[orchestration] Entity search results:",
results.map((r) => ({ name: r.payload?.name, score: r.score })),
);
return results.map((r) => r.payload).filter(Boolean);
} catch (err) {
console.warn(
logger.warn(
"[orchestration] Entity search failed, continuing without:",
err.message,
);
@@ -143,7 +143,7 @@ async function chat(externalId, userMessage, options = {}) {
projectSessionIds = projectSessions.map((s) => s.id);
}
} catch (err) {
console.warn(
logger.warn(
"[orchestration] Failed to resolve project context:",
err.message,
);
@@ -189,7 +189,7 @@ async function chat(externalId, userMessage, options = {}) {
session.project_id ?? null,
);
} catch (err) {
console.error('[orchestration] Failed to save episode:', err.message);
logger.error('[orchestration] Failed to save episode:', err.message);
}
const allEpisodes = await memory.getRecentEpisodes(session.id, 9999);
triggerSummary(session, allEpisodes);
@@ -231,7 +231,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
}
} catch (err) {
console.warn(
logger.warn(
"[orchestration] Failed to resolve project context:",
err.message,
);
@@ -302,7 +302,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
throw new Error(data.error);
}
} catch (err) {
console.error(
logger.error(
"[orchestration] Failed to parse inference SSE event:",
raw,
err.message,
@@ -316,7 +316,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
const allEpisodes = await memory.getRecentEpisodes(session.id, 9999);
triggerSummary(session, allEpisodes);
} else {
console.warn(
logger.warn(
"[orchestration] Stream finished with no assistant text; episode not saved",
);
}
@@ -327,7 +327,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) {
return { model, tokenCount };
} catch (err) {
console.error(
logger.error(
"[orchestration] chatStream fatal error:",
err.message,
err.stack,

View File

@@ -1,6 +1,8 @@
const { Router } = require('express')
const { chat, chatStream } = require('../chat/index');
const memory = require('../services/memory')
const logger = require('@nexusai/shared');
const router = Router();
@@ -17,7 +19,7 @@ router.post('/', async (req, res) => {
});
res.json(result)
} catch (err) {
console.error(`[orchestration] chat error: `, err.message)
logger.error(`[orchestration] chat error: `, err.message)
res.status(500).json ({ error: err.message})
}
});

View File

@@ -4,7 +4,7 @@ const fs = require('fs');
const path = require('path');
const appSettings = require('../config/settings');
const { getEnv, LLAMACPP } = require('@nexusai/shared');
const { getEnv, LLAMACPP, logger } = require('@nexusai/shared');
const LLAMA_URL = getEnv('LLAMA_SERVER_URL', LLAMACPP.DEFAULT_URL);
router.get('/', (req, res) => {
@@ -38,7 +38,7 @@ router.get('/', (req, res) => {
res.json(models);
} catch (err) {
console.error('[models] Failed to scan folder:', err.message);
logger.error('[models] Failed to scan folder:', err.message);
res.status(500).json({ error: `Could not read models folder: ${modelsFolderPath}` });
}
});
@@ -53,7 +53,7 @@ router.get('/props', async (req, res) => {
modelAlias: data.model_alias,
});
} catch (err) {
console.error('[models/props]', err.message);
logger.error('[models/props]', err.message);
res.status(503).json({ error: 'Could not reach llama-server' });
}
});

View File

@@ -1,4 +1,4 @@
const { getEnv, SERVICES, SUMMARIES } = require('@nexusai/shared');
const { getEnv, SERVICES, SUMMARIES, logger } = require('@nexusai/shared');
const EXTRACTION_URL = getEnv('EXTRACTION_URL', 'http://localhost:11434');
const EXTRACTION_MODEL = getEnv('EXTRACTION_MODEL', 'qwen2.5:3b');
@@ -104,7 +104,7 @@ async function maybeSummarize(session, allEpisodes) {
const totalEpisodeTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0);
// add temporarily before the generateSummary call
console.log('[summarization] episodes to summarize:', episodesToSummarize.length);
logger.debug('[summarization] episodes to summarize:', episodesToSummarize.length);
const content = await generateSummary(
episodesToSummarize,
@@ -126,7 +126,7 @@ async function maybeSummarize(session, allEpisodes) {
episodeRange,
}),
});
console.log(`[summarization] Created new summary for session ${session.id}`);
logger.debug(`[summarization] Created new summary for session ${session.id}`);
} else {
await fetch(`${MEMORY_URL}/summaries/${latest.id}`, {
method: 'PATCH',
@@ -137,14 +137,14 @@ async function maybeSummarize(session, allEpisodes) {
episodeRange,
}),
});
console.log(`[summarization] Updated summary ${latest.id} for session ${session.id}`);
logger.debug(`[summarization] Updated summary ${latest.id} for session ${session.id}`);
}
}
async function triggerSummary(session, allEpisodes) {
// Intentionally fire-and-forget — caller doesn't await this
maybeSummarize(session, allEpisodes).catch(err =>
console.warn('[summarization] Summary failed (non-critical):', err.message)
logger.warn('[summarization] Summary failed (non-critical):', err.message)
);
}