diff --git a/packages/chat-client/src/App.jsx b/packages/chat-client/src/App.jsx index 36bd793..4586c0c 100644 --- a/packages/chat-client/src/App.jsx +++ b/packages/chat-client/src/App.jsx @@ -65,7 +65,7 @@ export default function App() { streaming, lastTokenCount, lastModel, - useChat, + summarising, } = useChat({ activeSession, appendMessage, updateLastMessage, refreshSessions }); function navigate(nextView) { diff --git a/packages/chat-client/src/api/orchestration.js b/packages/chat-client/src/api/orchestration.js index 5cc3723..13b1c10 100644 --- a/packages/chat-client/src/api/orchestration.js +++ b/packages/chat-client/src/api/orchestration.js @@ -212,3 +212,14 @@ export async function fetchSessionSummaries(sessionId) { return res.json(); } +export async function generateProjectSummary(projectId) { + const res = await fetch(`${BASE_URL}/summaries/project/${projectId}/generate`, { method: 'POST' }); + if (!res.ok) throw new Error(`Failed to generate project summary: ${res.status}`); + return res.json(); +} + +export async function fetchProjectOverviewSummary(projectId) { + const res = await fetch(`${BASE_URL}/summaries/project/${projectId}/overview`); + if (!res.ok) throw new Error(`Failed to fetch project overview: ${res.status}`); + return res.json(); // null if none exists yet +} \ No newline at end of file diff --git a/packages/chat-client/src/components/ProjectView.jsx b/packages/chat-client/src/components/ProjectView.jsx index 062fddb..0448d4a 100644 --- a/packages/chat-client/src/components/ProjectView.jsx +++ b/packages/chat-client/src/components/ProjectView.jsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { fetchSessions, updateProject, deleteProject } from '../api/orchestration'; +import { fetchSessions, updateProject, deleteProject, generateProjectSummary, fetchProjectOverviewSummary } from '../api/orchestration'; import ProjectModal from './ProjectModal'; export default function ProjectView({ project, onNavigate, onBack, onSelectSession, onNewProjectChat, onProjectsChange }) { @@ -8,9 +8,27 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi const [input, setInput] = useState(''); const [menuOpen, setMenuOpen] = useState(false); const [modal, setModal] = useState(null); + const [overview, setOverview] = useState(null); + const [overviewLoading, setOverviewLoading] = useState(true); + const [generating, setGenerating] = useState(false); + const [generateError, setGenerateError] = useState(null); useEffect(() => { load(); }, [project.id]); + useEffect(() => { + async function loadOverview() { + setOverviewLoading(true); + try { + setOverview(await fetchProjectOverviewSummary(project.id)); + } catch (err) { + console.error('[ProjectView] Failed to load overview:', err.message); + } finally { + setOverviewLoading(false); + } + } + loadOverview(); + }, [project.id]); + async function load() { setLoading(true); try { @@ -70,6 +88,23 @@ export default function ProjectView({ project, onNavigate, onBack, onSelectSessi if (diffDays === 1) return 'Yesterday'; return date.toLocaleDateString([], { month: 'short', day: 'numeric', year: 'numeric' }); } + + async function handleGenerateSummary() { + setGenerating(true); + setGenerateError(null); + try { + setOverview(await generateProjectSummary(project.id)); + } catch (err) { + // 422 means no session summaries exist yet — surface a friendly message + setGenerateError( + err.message.includes('422') + ? 'No conversations found in this project yet.' + : 'Failed to generate summary. Please try again.' + ); + } finally { + setGenerating(false); + } +} return (
Project Memory
-Project Memory
+ +Loading…
+ + ) : generateError ? ( ++ {generateError} +
+ + ) : overview ? ( + <> ++ {overview.content} +
++ Last generated {formatTimestamp(overview.created_at)} +
+ > + + ) : ( + // No overview exists yet — explain what this section is for ++ Generate a summary to create a concise overview of this project's goals, + progress, and key decisions — built from your session summaries. +
+- Once this project has enough conversations, NexusAI will automatically - generate a rolling summary of key themes, decisions, and context — giving - the model a condensed view of the project's memory without consuming the - full context window. -
-