diff --git a/packages/chat-client/src/App.jsx b/packages/chat-client/src/App.jsx index b1f5482..36bd793 100644 --- a/packages/chat-client/src/App.jsx +++ b/packages/chat-client/src/App.jsx @@ -39,7 +39,6 @@ export default function App() { const [viewHistory, setViewHistory] = useState([]); const [activeProject, setActiveProject] = useState(null); const { projects, refreshProjects } = useProjects(); - const [summarising, setSummarising] = useState(false); // Lifted model props — available to header + SettingsView const [modelProps, setModelProps] = useState(null); @@ -66,6 +65,7 @@ export default function App() { streaming, lastTokenCount, lastModel, + useChat, } = useChat({ activeSession, appendMessage, updateLastMessage, refreshSessions }); function navigate(nextView) { diff --git a/packages/chat-client/src/hooks/useChat.js b/packages/chat-client/src/hooks/useChat.js index 144c13f..e92ee77 100644 --- a/packages/chat-client/src/hooks/useChat.js +++ b/packages/chat-client/src/hooks/useChat.js @@ -108,5 +108,6 @@ export function useChat({ activeSession, appendMessage, updateLastMessage, refre error, lastTokenCount, lastModel, + summarising, }; } \ No newline at end of file diff --git a/packages/memory-service/src/entities/extraction.js b/packages/memory-service/src/entities/extraction.js index 2818643..ea100ea 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 } = require('@nexusai/shared'); +const { getEnv, SERVICES, formatEpisodeText, ENTITIES } = require('@nexusai/shared'); const { upsertEntity } = require('./index'); const EXTRACTION_URL = getEnv('EXTRACTION_URL', 'http://localhost:11434'); @@ -63,12 +63,8 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null) try { // Fetch existing entities to guide the model toward consistent name/type pairs const db = require('../db').getDB(); - console.log('[entities] fetching known entities...'); // add this const knownEntities = db.prepare(`SELECT name, type FROM entities ORDER BY rowid DESC LIMIT 20`).all(); - console.log('[entities] known entities count:', knownEntities.length); - const prompt = buildExtractionPrompt(userMessage, aiResponse, knownEntities); - console.log('[entities] prompt preview:', JSON.stringify(prompt.slice(-300))); const res = await fetch(`${EXTRACTION_URL}/api/generate`, { @@ -80,8 +76,8 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null) stream: false, format: 'json', options: { - temperature: 0.1, - num_predict: 1024, + temperature: ENTITIES.TEMPERATURE, + num_predict: ENTITIES.NUM_PREDICT, }, }), }); @@ -90,7 +86,6 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null) const data = await res.json(); const raw = data.response?.trim() ?? ''; - console.log('[entities] raw response:', JSON.stringify(raw.slice(0, 300))); const parsed = JSON.parse(raw); const entities = Array.isArray(parsed.entities) ? parsed.entities : []; @@ -122,7 +117,6 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null) })) .catch(err => { console.warn(`[entities] Failed to embed entity "${entity.name}":`, err.message); - console.warn(`[entities] Embed error stack:`, err.stack); // add this }); saved++; @@ -133,7 +127,6 @@ async function extractAndStoreEntities(userMessage, aiResponse, projectId=null) } catch (err) { // Non-critical — log and move on, episode is already saved console.warn('[entities] Extraction failed:', err.message); - console.warn('[entities] Stack:', err.stack); } } diff --git a/packages/memory-service/src/episodic/index.js b/packages/memory-service/src/episodic/index.js index 03f210e..19f9c56 100644 --- a/packages/memory-service/src/episodic/index.js +++ b/packages/memory-service/src/episodic/index.js @@ -25,7 +25,7 @@ function getSession(id) { } -function getSessions(limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = 0, projectId = null) { +function getSessions(limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = EPISODIC.DEFAULT_OFFSET, projectId = null) { const db = getDB(); const stmt = projectId ? db.prepare(` @@ -143,7 +143,7 @@ function getEpisode(id) { } // Retrieves episodes for a given session, ordered by creation time descending, with pagination -function getEpisodesBySession(sessionId, limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = 0) { +function getEpisodesBySession(sessionId, limit = EPISODIC.DEFAULT_PAGE_SIZE, offset = EPISODIC.DEFAULT_OFFSET) { const db = getDB(); const stmt = db.prepare(` SELECT * FROM episodes diff --git a/packages/orchestration-service/src/chat/index.js b/packages/orchestration-service/src/chat/index.js index cbb73c6..104b28a 100644 --- a/packages/orchestration-service/src/chat/index.js +++ b/packages/orchestration-service/src/chat/index.js @@ -317,10 +317,7 @@ async function chatStream(externalId, userMessage, onChunk, options = {}) { } } - console.log("[orchestration] final streamed text length:", fullText.length); - if (fullText.trim()) { - console.log('[chat] tokenCount before save:', tokenCount); await memory.createEpisode(session.id, userMessage, fullText, tokenCount, session.project_id ?? null); const allEpisodes = await memory.getRecentEpisodes(session.id, 9999); triggerSummary(session, allEpisodes); diff --git a/packages/orchestration-service/src/services/summarization.js b/packages/orchestration-service/src/services/summarization.js index 3cebb20..dcc4360 100644 --- a/packages/orchestration-service/src/services/summarization.js +++ b/packages/orchestration-service/src/services/summarization.js @@ -77,12 +77,9 @@ async function maybeSummarize(session, allEpisodes) { // 1. Sum total tokens for this session const totalTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0); if (totalTokens < THRESHOLD_TOKENS) return; // under threshold — nothing to do - console.log('[summarization] fetching existing summaries...'); + // 2. Fetch existing summaries for session const summariesRes = await fetch(`${MEMORY_URL}/sessions/${session.id}/summaries`); - console.log('[summarization] memory URL:', MEMORY_URL); - console.log('[summarization] session:', session.id, session.external_id); - console.log('[summarization] summaries fetch status:', summariesRes.status); if (!summariesRes.ok) return; const summaries = await summariesRes.json(); @@ -96,19 +93,18 @@ async function maybeSummarize(session, allEpisodes) { if (newEpisodes.length < MIN_EPISODES_SINCE) return; } - // 4. Determine episode range string e.g. "1-42" - const ids = allEpisodes.map(ep => ep.id).sort((a,b) => a - b); - const episodeRange = `${ids.at(0)}-${ids.at(-1)}`; - const totalEpisodeTokens = allEpisodes.reduce((sum, ep) => sum + (ep.token_count || 0), 0); + // 4. Determine episodes to summarize + const episodesToSummarize = latest + ? allEpisodes.filter(ep => ep.id > lastCoveredId) + : allEpisodes; - // 5. Generate summary — pass existing content if updating - const episodesToSummarize = latest - ? allEpisodes.filter(ep => ep.id > lastCoveredId) - : allEpisodes; + // 5. Determine episode range from the episodes actually being summarized + const summarizedIds = episodesToSummarize.map(ep => ep.id).sort((a,b) => a - b); + const episodeRange = `${summarizedIds.at(0)}-${summarizedIds.at(-1)}`; + 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); - console.log('[summarization] total chars:', episodesToSummarize.reduce((s, ep) => s + ep.user_message.length + ep.ai_response.length, 0)); const content = await generateSummary( episodesToSummarize, diff --git a/packages/shared/src/config/constants.js b/packages/shared/src/config/constants.js index 2d084dc..0af3da6 100644 --- a/packages/shared/src/config/constants.js +++ b/packages/shared/src/config/constants.js @@ -74,6 +74,12 @@ const SUMMARIES = { MAX_SUMMARY_TOKENS: 800, //if existing summary exceeds this, create new instead of update MIN_EPISODES_SINCE: 5, // don't resummarize until N new episodes since last summary } + +const ENTITIES = { + TEMPERATURE: 0.1, + NUM_PREDICT: 1024, +} + module.exports = { QDRANT, COLLECTIONS, @@ -85,5 +91,6 @@ module.exports = { INFERENCE_DEFAULTS, SQLITE, ORCHESTRATION, - SUMMARIES + SUMMARIES, + ENTITIES }; \ No newline at end of file diff --git a/packages/shared/src/index.js b/packages/shared/src/index.js index 20e2502..75176e5 100644 --- a/packages/shared/src/index.js +++ b/packages/shared/src/index.js @@ -1,5 +1,5 @@ const {getEnv} = require('./config/env'); -const {QDRANT, COLLECTIONS, EPISODIC, SERVICES, OLLAMA, PORTS, LLAMACPP, INFERENCE_DEFAULTS, SQLITE, ORCHESTRATION, SUMMARIES } = require('./config/constants'); +const {QDRANT, COLLECTIONS, EPISODIC, SERVICES, OLLAMA, PORTS, LLAMACPP, INFERENCE_DEFAULTS, SQLITE, ORCHESTRATION, SUMMARIES, ENTITIES } = require('./config/constants'); const {parseRow, formatEpisodeText} = require('./utils') module.exports = { @@ -17,4 +17,5 @@ module.exports = { parseRow, formatEpisodeText, SUMMARIES, + ENTITIES, }; \ No newline at end of file