--- phase: 33-persistent-memory plan: 02 type: execute wave: 1 depends_on: [] files_modified: - ui/src/pages/PersonalAssistant.tsx - ui/src/api/assistantMemory.ts - ui/src/hooks/useNexusMode.ts - ui/src/App.tsx - ui/src/components/Layout.tsx autonomous: true requirements: [ASST-04] must_haves: truths: - "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" artifacts: - path: "ui/src/pages/PersonalAssistant.tsx" provides: "Personal assistant page component" exports: ["PersonalAssistant"] - path: "ui/src/hooks/useNexusMode.ts" provides: "React Query hook for nexus settings mode" exports: ["useNexusMode"] - path: "ui/src/api/assistantMemory.ts" provides: "API client for memory endpoints" exports: ["assistantMemoryApi"] key_links: - from: "ui/src/pages/PersonalAssistant.tsx" to: "ui/src/hooks/useNexusMode.ts" via: "useNexusMode hook" pattern: "useNexusMode" - from: "ui/src/App.tsx" to: "ui/src/pages/PersonalAssistant.tsx" via: "Route element" pattern: "PersonalAssistant" - from: "ui/src/components/Layout.tsx" to: "assistant route" via: "NavLink in sidebar" pattern: "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. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.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: ```typescript export type NexusMode = "personal_ai" | "project_builder" | "both"; export interface NexusSettings { mode: NexusMode; } export function fetchNexusSettings(): Promise; ``` From ui/src/App.tsx (route pattern): ```typescript // Board routes at line 122-180 function boardRoutes() { return <> } /> } /> // ... more routes ; } ``` From ui/src/components/Layout.tsx (sidebar pattern): ```typescript // ChatPanel rendered at line 463 // Sidebar NavLinks with icons (lucide-react) ``` From ui/src/components/ChatPanel.tsx: ```typescript // 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 `` - 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 - 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 After completion, create `.planning/phases/33-persistent-memory/33-02-SUMMARY.md`