nexus/.planning/phases/33-persistent-memory/33-02-PLAN.md

8.3 KiB

phase plan type wave depends_on files_modified autonomous requirements must_haves
33-persistent-memory 02 execute 1
ui/src/pages/PersonalAssistant.tsx
ui/src/api/assistantMemory.ts
ui/src/hooks/useNexusMode.ts
ui/src/App.tsx
ui/src/components/Layout.tsx
true
ASST-04
truths artifacts key_links
PersonalAssistantPage is visible when mode is personal_ai or both
PersonalAssistantPage is hidden (route redirects) when mode is project_builder
User can navigate to assistant page from sidebar
Assistant page renders the existing ChatPanel component for chat functionality
path provides exports
ui/src/pages/PersonalAssistant.tsx Personal assistant page component
PersonalAssistant
path provides exports
ui/src/hooks/useNexusMode.ts React Query hook for nexus settings mode
useNexusMode
path provides exports
ui/src/api/assistantMemory.ts API client for memory endpoints
assistantMemoryApi
from to via pattern
ui/src/pages/PersonalAssistant.tsx ui/src/hooks/useNexusMode.ts useNexusMode hook useNexusMode
from to via pattern
ui/src/App.tsx ui/src/pages/PersonalAssistant.tsx Route element PersonalAssistant
from to via pattern
ui/src/components/Layout.tsx assistant route NavLink in sidebar assistant
Create the Personal Assistant page, mode-gating hook, and memory API client. Wire the route and sidebar navigation.

Purpose: ASST-04 requires assistant and project builder modes to work standalone or together. The PersonalAssistantPage is the entry point for assistant mode. Output: Working assistant page with mode-gated visibility, sidebar link, and memory API client.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/33-persistent-memory/33-RESEARCH.md @ui/src/App.tsx @ui/src/components/Layout.tsx @ui/src/api/hardware.ts @ui/src/components/ChatPanel.tsx

From ui/src/api/hardware.ts:

export type NexusMode = "personal_ai" | "project_builder" | "both";
export interface NexusSettings { mode: NexusMode; }
export function fetchNexusSettings(): Promise<NexusSettings>;

From ui/src/App.tsx (route pattern):

// Board routes at line 122-180
function boardRoutes() {
  return <>
    <Route index element={<Navigate to="dashboard" replace />} />
    <Route path="dashboard" element={<Dashboard />} />
    // ... more routes
  </>;
}

From ui/src/components/Layout.tsx (sidebar pattern):

// ChatPanel rendered at line 463
// Sidebar NavLinks with icons (lucide-react)

From ui/src/components/ChatPanel.tsx:

// Existing chat panel component — renders conversation list + message list
// Used as slide-over panel in Layout
Task 1: Create useNexusMode hook, memory API client, and PersonalAssistantPage ui/src/hooks/useNexusMode.ts, ui/src/api/assistantMemory.ts, ui/src/pages/PersonalAssistant.tsx Create `ui/src/hooks/useNexusMode.ts`: - Export `useNexusMode()` hook that calls `useQuery` with key `["nexus", "settings"]` fetching `fetchNexusSettings()` from `../api/hardware` - Return `{ mode, isLoading, isAssistantEnabled }` where `isAssistantEnabled = mode !== "project_builder"` - Default mode to `"both"` while loading
Create `ui/src/api/assistantMemory.ts`:
- Export `assistantMemoryApi` object with:
  - `getMemory(companyId: string)` — GET `/assistant-memory/${companyId}` using `api.get`
  - `appendFact(companyId: string, fact: string)` — PATCH `/assistant-memory/${companyId}` with `{ fact }`
  - `clearMemory(companyId: string)` — DELETE `/assistant-memory/${companyId}`
- Import `api` from `./client`

Create `ui/src/pages/PersonalAssistant.tsx`:
- Export default `PersonalAssistant` component
- Use `useNexusMode()` — if `!isAssistantEnabled`, render `<Navigate to="/dashboard" replace />`
- Render a full-page chat layout:
  - Use `useCompany()` to get `selectedCompany`
  - Create or retrieve an assistant conversation (use existing `chatApi.listConversations` with a dedicated agent filter, or create a new one)
  - Render `ChatPanel`-style UI: conversation list on left, messages on right
  - Include a header with "Personal Assistant" title and a "Turn this into a project" button (wired in Plan 03)
- Styling: Use existing Tailwind patterns from Layout.tsx. Full height (`h-full`), flex layout, clean assistant-focused design.
- The "Turn this into a project" button should be present but disabled with tooltip "Coming soon" — Plan 03 wires the actual handoff.
ui/src/api/hardware.ts, ui/src/api/client.ts, ui/src/components/ChatPanel.tsx, ui/src/context/CompanyContext.tsx, ui/src/hooks/useStreamingChat.ts, ui/src/components/ChatMessageList.tsx pnpm --filter @paperclipai/ui tsc --noEmit - grep -q "useNexusMode" ui/src/hooks/useNexusMode.ts - grep -q "isAssistantEnabled" ui/src/hooks/useNexusMode.ts - grep -q "fetchNexusSettings" ui/src/hooks/useNexusMode.ts - grep -q "assistantMemoryApi" ui/src/api/assistantMemory.ts - grep -q "appendFact" ui/src/api/assistantMemory.ts - grep -q "PersonalAssistant" ui/src/pages/PersonalAssistant.tsx - grep -q "useNexusMode" ui/src/pages/PersonalAssistant.tsx - grep -q "project_builder\|isAssistantEnabled" ui/src/pages/PersonalAssistant.tsx PersonalAssistant page renders full-page chat when mode allows, redirects to dashboard when project_builder only. Memory API client ready. Mode hook available for any component. Task 2: Wire assistant route in App.tsx and sidebar link in Layout.tsx ui/src/App.tsx, ui/src/components/Layout.tsx In `ui/src/App.tsx`: - Add lazy import: `const PersonalAssistant = React.lazy(() => import("./pages/PersonalAssistant"));` (or direct import if lazy loading is not used in this codebase — check existing import pattern) - Add route inside `boardRoutes()` function, after the dashboard route: `} />` - Also add `} />` for direct conversation linking
In `ui/src/components/Layout.tsx`:
- Add a sidebar NavLink for the assistant page
- Use `MessageCircle` or `Bot` icon from lucide-react (check which icons are already imported)
- Place it prominently — after Dashboard in the nav order
- Gate visibility using `useNexusMode()` — only show when `isAssistantEnabled` is true
- NavLink target: `/assistant`
- Label: "Assistant"
ui/src/App.tsx, ui/src/components/Layout.tsx pnpm --filter @paperclipai/ui tsc --noEmit - grep -q "PersonalAssistant" ui/src/App.tsx - grep -q "assistant" ui/src/App.tsx - grep -q "assistant" ui/src/components/Layout.tsx - grep -q "useNexusMode\|isAssistantEnabled" ui/src/components/Layout.tsx /assistant route exists and renders PersonalAssistant page. Sidebar shows Assistant link when mode is personal_ai or both, hidden when project_builder. TypeScript compiles clean. pnpm --filter @paperclipai/ui tsc --noEmit

<success_criteria>

  • PersonalAssistantPage renders chat interface when mode allows
  • Route /assistant exists in board routes
  • Sidebar link visible only when assistant mode enabled
  • Mode redirect works (project_builder -> dashboard)
  • TypeScript compiles without errors </success_criteria>
After completion, create `.planning/phases/33-persistent-memory/33-02-SUMMARY.md`