diff --git a/.gitignore b/.gitignore index 7211339..711f1e4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ data/ .env .env.* *.db -/.claude +.claude/settings.local.json EOF \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 7a73a41..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/roadmap.md b/docs/roadmap.md index 180734e..92be1ec 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -43,14 +43,14 @@ *Target: Next development session (Saturday)* ### Bug Fixes -- [ ] **Entity extraction JSON parsing** — robustify response parser in `extraction.js` to handle model returning markdown fences or preamble around JSON +- [x] **Entity extraction JSON parsing** — robustify response parser in `extraction.js` to handle model returning markdown fences or preamble around JSON - [ ] **Qdrant entity search empty results** — verify entities embedded post-isolation-fix are surfacing correctly in project session searches ### Tech Debt -- [ ] **Logging** — introduce `LOG_LEVEL` env var across all services; reduce noise in production -- [ ] **Error response consistency** — audit all endpoints for uniform `{ error, detail }` shape -- [ ] **Constants audit** — move any remaining inline magic numbers (limits, thresholds, timeouts) to shared config -- [ ] **Orchestration `chat/index.js` review** — extract any logic that has grown beyond its intended scope into dedicated modules +- [x] **Logging** — introduce `LOG_LEVEL` env var across all services; reduce noise in production +- [x] **Error response consistency** — audit all endpoints for uniform `{ error, detail }` shape +- [x] **Constants audit** — move any remaining inline magic numbers (limits, thresholds, timeouts) to shared config +- [x] **Orchestration `chat/index.js` review** — extract any logic that has grown beyond its intended scope into dedicated modules --- diff --git a/packages/chat-client/src/api/orchestration.js b/packages/chat-client/src/api/orchestration.js index 3732ee7..d116867 100644 --- a/packages/chat-client/src/api/orchestration.js +++ b/packages/chat-client/src/api/orchestration.js @@ -1,5 +1,5 @@ import { API_DEFAULTS } from "../config/constants"; -import { logger } from "@nexusai/shared"; + const BASE_URL = import.meta.env.VITE_ORCHESTRATION_URL ?? ''; @@ -79,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) { - logger.error('[chat-client] Failed to parse SSE event:', raw, err); + console.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 febaa0e..9f60c3c 100644 --- a/packages/chat-client/src/components/AllChatsView.jsx +++ b/packages/chat-client/src/components/AllChatsView.jsx @@ -1,7 +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; @@ -26,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) { - logger.error('[AllChatsView] Failed to load sessions:', err.message); + console.error('[AllChatsView] Failed to load sessions:', err.message); } finally { setLoading(false); } @@ -55,7 +55,7 @@ export default function AllChatsView({ onSelectSession, onBack, projects }) { setConfirmOpen(false); await loadPage(page); } catch (err) { - logger.error('[AllChatsView] Bulk delete failed:', err.message); + console.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 dce9a0a..842e3af 100644 --- a/packages/chat-client/src/components/AllProjectsView.jsx +++ b/packages/chat-client/src/components/AllProjectsView.jsx @@ -1,7 +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([]); @@ -15,7 +15,7 @@ export default function AllProjectsView({ onProjectsChange, onBack, onSelectProj try { setProjects(await fetchProjects()); } catch (err) { - logger.error('[AllProjectsView] Failed to load:', err.message); + console.error('[AllProjectsView] Failed to load:', err.message); } finally { setLoading(false); } @@ -31,7 +31,7 @@ async function handleSave({ name, description, colour, icon }) { await load(); onProjectsChange?.(); // add this } catch (err) { - logger.error('[AllProjectsView] Save failed:', err.message); + console.error('[AllProjectsView] Save failed:', err.message); } } @@ -41,7 +41,7 @@ async function handleDelete(id) { await load(); onProjectsChange?.(); // add this } catch (err) { - logger.error('[AllProjectsView] Delete failed:', err.message); + console.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 2a74359..0448d4a 100644 --- a/packages/chat-client/src/components/ProjectView.jsx +++ b/packages/chat-client/src/components/ProjectView.jsx @@ -1,7 +1,6 @@ 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([]); @@ -22,7 +21,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi try { setOverview(await fetchProjectOverviewSummary(project.id)); } catch (err) { - logger.error('[ProjectView] Failed to load overview:', err.message); + console.error('[ProjectView] Failed to load overview:', err.message); } finally { setOverviewLoading(false); } @@ -35,7 +34,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi try { setSessions(await fetchSessions(50, 0, project.id)); } catch (err) { - logger.error('[ProjectView] Failed to load sessions:', err.message); + console.error('[ProjectView] Failed to load sessions:', err.message); } finally { setLoading(false); } @@ -61,7 +60,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi onProjectsChange?.(); setModal(null); } catch (err) { - logger.error('[ProjectView] Update failed:', err.message); + console.error('[ProjectView] Update failed:', err.message); } } @@ -71,7 +70,7 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi onProjectsChange?.(); onBack(); } catch (err) { - logger.error('[ProjectView] Delete failed:', err.message); + console.error('[ProjectView] Delete failed:', err.message); } } @@ -376,7 +375,7 @@ function NotesSection({ projectId, initialNotes }) { await updateProject(projectId, { notes }); setSavedNotes(notes); } catch (err) { - logger.error('[NotesSection] Save failed:', err.message); + console.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 3cc2327..ea5cdcd 100644 --- a/packages/chat-client/src/components/SettingsView.jsx +++ b/packages/chat-client/src/components/SettingsView.jsx @@ -2,7 +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(); @@ -277,7 +277,7 @@ function ServiceHealth() { setServices(await getServiceHealth()); setLastChecked(new Date()); } catch (err) { - logger.error('[ServiceHealth]', err.message); + console.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 71e0214..cde7a8c 100644 --- a/packages/chat-client/src/components/Sidebar.jsx +++ b/packages/chat-client/src/components/Sidebar.jsx @@ -2,7 +2,6 @@ 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({ @@ -33,7 +32,7 @@ export default function Sidebar({ await updateSession(session.external_id, { name, projectId }); onSessionsChange(); } catch (err) { - logger.error('[Sidebar] Rename failed:', err.message); + console.error('[Sidebar] Rename failed:', err.message); } } @@ -42,7 +41,7 @@ export default function Sidebar({ await deleteSession(session.external_id); onSessionsChange(session); } catch (err) { - logger.error('[Sidebar] Delete failed:', err.message); + console.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 f6706de..e92ee77 100644 --- a/packages/chat-client/src/hooks/useChat.js +++ b/packages/chat-client/src/hooks/useChat.js @@ -1,6 +1,5 @@ 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); @@ -74,7 +73,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 => logger.warn('[useChat] Failed to assign project:', err.message)); + .catch(err => console.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 ad0b9d7..b783774 100644 --- a/packages/chat-client/src/hooks/useModels.js +++ b/packages/chat-client/src/hooks/useModels.js @@ -2,7 +2,6 @@ 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); @@ -16,7 +15,7 @@ export function useModels() { setSelectedModel(data[0]?.value ?? DEFAULT_MODEL); }) .catch(err => { - logger.warn('[useModels] Falling back to static list:', err.message); + console.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 1f89bca..0a23553 100644 --- a/packages/chat-client/src/hooks/useProjects.js +++ b/packages/chat-client/src/hooks/useProjects.js @@ -1,6 +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([]); @@ -9,7 +9,7 @@ export function useProjects() { try { setProjects(await fetchProjects()); } catch (err) { - logger.warn('[useProjects] Failed to load projects:', err.message); + console.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 9ebd0a5..c86bdb8 100644 --- a/packages/chat-client/src/hooks/useSettings.js +++ b/packages/chat-client/src/hooks/useSettings.js @@ -1,13 +1,12 @@ 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(logger.error); + getSettings().then(setSettings).catch(console.error); }, []); async function saveSetting(key, value) { @@ -16,7 +15,7 @@ export function useSettings() { const updated = await updateSettings({ [key]: value }); setSettings(updated); } catch (err) { - logger.error('[useSettings] Save failed:', err.message); + console.error('[useSettings] Save failed:', err.message); } finally { setSaving(false); }