diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..15aa39a --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(grep -E \"^d|^-.*\\\\.\\(json|md\\)$\")" + ] + } +} diff --git a/packages/chat-client/src/api/orchestration.js b/packages/chat-client/src/api/orchestration.js index 13b1c10..3732ee7 100644 --- a/packages/chat-client/src/api/orchestration.js +++ b/packages/chat-client/src/api/orchestration.js @@ -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); } } } diff --git a/packages/chat-client/src/components/AllChatsView.jsx b/packages/chat-client/src/components/AllChatsView.jsx index f4ebb19..febaa0e 100644 --- a/packages/chat-client/src/components/AllChatsView.jsx +++ b/packages/chat-client/src/components/AllChatsView.jsx @@ -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); } diff --git a/packages/chat-client/src/components/AllProjectsView.jsx b/packages/chat-client/src/components/AllProjectsView.jsx index 1431e2a..dce9a0a 100644 --- a/packages/chat-client/src/components/AllProjectsView.jsx +++ b/packages/chat-client/src/components/AllProjectsView.jsx @@ -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); } } diff --git a/packages/chat-client/src/components/ProjectView.jsx b/packages/chat-client/src/components/ProjectView.jsx index 0448d4a..2a74359 100644 --- a/packages/chat-client/src/components/ProjectView.jsx +++ b/packages/chat-client/src/components/ProjectView.jsx @@ -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); } diff --git a/packages/chat-client/src/components/SettingsView.jsx b/packages/chat-client/src/components/SettingsView.jsx index db5e76f..3cc2327 100644 --- a/packages/chat-client/src/components/SettingsView.jsx +++ b/packages/chat-client/src/components/SettingsView.jsx @@ -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); } diff --git a/packages/chat-client/src/components/Sidebar.jsx b/packages/chat-client/src/components/Sidebar.jsx index cde7a8c..71e0214 100644 --- a/packages/chat-client/src/components/Sidebar.jsx +++ b/packages/chat-client/src/components/Sidebar.jsx @@ -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); } } diff --git a/packages/chat-client/src/hooks/useChat.js b/packages/chat-client/src/hooks/useChat.js index e92ee77..f6706de 100644 --- a/packages/chat-client/src/hooks/useChat.js +++ b/packages/chat-client/src/hooks/useChat.js @@ -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)); } }, diff --git a/packages/chat-client/src/hooks/useModels.js b/packages/chat-client/src/hooks/useModels.js index b783774..ad0b9d7 100644 --- a/packages/chat-client/src/hooks/useModels.js +++ b/packages/chat-client/src/hooks/useModels.js @@ -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)); }, []); diff --git a/packages/chat-client/src/hooks/useProjects.js b/packages/chat-client/src/hooks/useProjects.js index 2027ba0..1f89bca 100644 --- a/packages/chat-client/src/hooks/useProjects.js +++ b/packages/chat-client/src/hooks/useProjects.js @@ -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); } }, []); diff --git a/packages/chat-client/src/hooks/useSettings.js b/packages/chat-client/src/hooks/useSettings.js index c86bdb8..9ebd0a5 100644 --- a/packages/chat-client/src/hooks/useSettings.js +++ b/packages/chat-client/src/hooks/useSettings.js @@ -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); } diff --git a/packages/inference-service/src/index.js b/packages/inference-service/src/index.js index b143ce0..e85dac8 100644 --- a/packages/inference-service/src/index.js +++ b/packages/inference-service/src/index.js @@ -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}`); }); \ No newline at end of file diff --git a/packages/inference-service/src/providers/llamacpp.js b/packages/inference-service/src/providers/llamacpp.js index 41f4fb9..d4dec70 100644 --- a/packages/inference-service/src/providers/llamacpp.js +++ b/packages/inference-service/src/providers/llamacpp.js @@ -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 }; } diff --git a/packages/inference-service/src/routes/inference.js b/packages/inference-service/src/routes/inference.js index d850750..33bef19 100644 --- a/packages/inference-service/src/routes/inference.js +++ b/packages/inference-service/src/routes/inference.js @@ -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(); diff --git a/packages/memory-service/src/db/index.js b/packages/memory-service/src/db/index.js index 0bdb4fa..d77b6c6 100644 --- a/packages/memory-service/src/db/index.js +++ b/packages/memory-service/src/db/index.js @@ -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; } diff --git a/packages/memory-service/src/entities/extraction.js b/packages/memory-service/src/entities/extraction.js index ea100ea..ca98099 100644 --- a/packages/memory-service/src/entities/extraction.js +++ b/packages/memory-service/src/entities/extraction.js @@ -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); } } diff --git a/packages/memory-service/src/episodic/index.js b/packages/memory-service/src/episodic/index.js index b2b5192..5e870fc 100644 --- a/packages/memory-service/src/episodic/index.js +++ b/packages/memory-service/src/episodic/index.js @@ -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; diff --git a/packages/memory-service/src/index.js b/packages/memory-service/src/index.js index ebf6351..75678f1 100644 --- a/packages/memory-service/src/index.js +++ b/packages/memory-service/src/index.js @@ -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}`); }); \ No newline at end of file diff --git a/packages/memory-service/src/semantic/index.js b/packages/memory-service/src/semantic/index.js index 8f1f5f4..fea41c8 100644 --- a/packages/memory-service/src/semantic/index.js +++ b/packages/memory-service/src/semantic/index.js @@ -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}`); } } } diff --git a/packages/orchestration-service/src/chat/index.js b/packages/orchestration-service/src/chat/index.js index a9d9c00..7b805fb 100644 --- a/packages/orchestration-service/src/chat/index.js +++ b/packages/orchestration-service/src/chat/index.js @@ -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, diff --git a/packages/orchestration-service/src/routes/chat.js b/packages/orchestration-service/src/routes/chat.js index 3870f14..7b36769 100644 --- a/packages/orchestration-service/src/routes/chat.js +++ b/packages/orchestration-service/src/routes/chat.js @@ -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}) } }); diff --git a/packages/orchestration-service/src/routes/models.js b/packages/orchestration-service/src/routes/models.js index 1326e86..f0575ff 100644 --- a/packages/orchestration-service/src/routes/models.js +++ b/packages/orchestration-service/src/routes/models.js @@ -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' }); } }); diff --git a/packages/orchestration-service/src/services/summarization.js b/packages/orchestration-service/src/services/summarization.js index dcc4360..13c8c08 100644 --- a/packages/orchestration-service/src/services/summarization.js +++ b/packages/orchestration-service/src/services/summarization.js @@ -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) ); }