    item = await MemoryInfrastructure.get_by_id(db, config_id)
    if not item:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Infrastructure config not found"
        )

    updated = await MemoryInfrastructure.update(
        db,
        config_id,
        **config.model_dump(exclude_unset=True)
    )
    return updated

@router.delete("/infrastructure/{config_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_infrastructure(config_id: int, db: AsyncSession = Depends(get_db)):
    """Delete an infrastructure configuration."""
    await MemoryInfrastructure.delete(db, config_id)
    return None


Let me write the export endpoint by appending to the file:


Bash

cat >> "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/backend/api/memory.py" << 'EXPORT_EOF'

# === Export Endpoints ===

class MemoryExportResponse(BaseModel):
    """Schema for memory export response."""
    export_version: str = "1.0"
    exported_at: datetime
    project_memory: List[dict]
    global_memory: List[dict]
    infrastructure: List[dict]

@router.get("/export", response_model=MemoryExportResponse)
async def export_all_memory(
    project_id: Optional[int] = None,
    db: AsyncSession = Depends(get_db)
):
    """Export all memory items as JSON.

    If project_id is provided, includes project-specific memory.
    Always includes global memory and infrastructure configurations.
    """
    # Get project memory if project_id provided
    project_items = []
    if project_id:
        items = await MemoryProject.get_for_project(db, project_id)
        project_items = [
            {
                "id": item.id,
                "project_id": item.project_id,
                "type": item.type,
                "content": item.content,
                "metadata": item.extra_data,
                "created_at": item.created_at.isoformat() if item.created_at else None,
            }
            for item in items
        ]

    # Get global memory
    global_items = await MemoryGlobal.get_all(db)
    global_data = [
        {
            "id": item.id,
            "type": item.type,
            "content": item.content,
            "metadata": item.extra_data,
            "usage_count": item.usage_count,
            "created_at": item.created_at.isoformat() if item.created_at else None,
        }
        for item in global_items
    ]

    # Get infrastructure
    infra_items = await MemoryInfrastructure.get_all(db)
    infra_data = [
        {
            "id": item.id,
            "name": item.name,
            "type": item.type,
            "config": item.config,
            "projects": item.projects,
            "created_at": item.created_at.isoformat() if item.created_at else None,
            "updated_at": item.updated_at.isoformat() if item.updated_at else None,
        }
        for item in infra_items
    ]

    return MemoryExportResponse(
        exported_at=datetime.utcnow(),
        project_memory=project_items,
        global_memory=global_data,
        infrastructure=infra_data,
    )
EXPORT_EOF

Append export endpoint to memory.py


Now let me update the frontend Memory Manager to add the export button:


     1→import { useState, useEffect } from 'react'
     2→import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil } from 'lucide-react'
     3→import * as Dialog from '@radix-ui/react-dialog'
     4→import * as AlertDialog from '@radix-ui/react-alert-dialog'
     5→import { useProjectStore } from '../stores/projectStore'
     6→
     7→type MemoryTab = 'project' | 'global' | 'infrastructure'
     8→
     9→interface ProjectMemoryItem {
    10→  id: number
    11→  project_id: number
    12→  type: string
    13→  content: string
    14→  metadata: Record<string, unknown> | null
    15→  created_at: string
    16→}
    17→
    18→interface GlobalMemoryItem {
    19→  id: number
    20→  type: string
    21→  content: string
    22→  metadata: Record<string, unknown> | null
    23→  usage_count: number
    24→  created_at: string
    25→}
    26→
    27→interface InfrastructureItem {
    28→  id: number
    29→  name: string
    30→  type: string
    31→  config: Record<string, unknown>
    32→  projects: number[] | null
    33→  created_at: string
    34→  updated_at: string
    35→}
    36→
    37→const API_BASE = 'http://localhost:8000/api/memory'
    38→
    39→export default function MemoryManager() {
    40→  const { currentProject } = useProjectStore()
    41→  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
    42→  const [searchQuery, setSearchQuery] = useState('')
    43→
    44→  // Data states
    45→  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
    46→  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
    47→  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
    48→  const [isLoading, setIsLoading] = useState(false)
    49→
    50→  // Dialog states
    51→  const [showAddDialog, setShowAddDialog] = useState(false)
    52→  const [newItemType, setNewItemType] = useState('')
    53→  const [newItemContent, setNewItemContent] = useState('')
    54→  const [newItemName, setNewItemName] = useState('')
    55→  const [isSaving, setIsSaving] = useState(false)
    56→
    57→  // Delete dialog states
    58→  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
    59→  const [itemToDelete, setItemToDelete] = useState<{ id: number; type: MemoryTab } | null>(null)
    60→  const [isDeleting, setIsDeleting] = useState(false)
    61→
    62→  // Edit dialog states
    63→  const [showEditDialog, setShowEditDialog] = useState(false)
    64→  const [editItem, setEditItem] = useState<{ id: number; type: string; content: string; memoryType: MemoryTab } | null>(null)
    65→  const [editItemType, setEditItemType] = useState('')
    66→  const [editItemContent, setEditItemContent] = useState('')
    67→  const [isEditing, setIsEditing] = useState(false)
    68→
    69→  const tabs = [
    70→    { id: 'project' as const, label: 'Project Memory', icon: Brain },
    71→    { id: 'global' as const, label: 'Global Memory', icon: Globe },
    72→    { id: 'infrastructure' as const, label: 'Infrastructure', icon: Server },
    73→  ]
    74→
    75→  // Fetch data based on active tab
    76→  useEffect(() => {
    77→    const fetchData = async () => {
    78→      setIsLoading(true)
    79→      try {
    80→        if (activeTab === 'project' && currentProject) {
    81→          const response = await fetch(`${API_BASE}/project/${currentProject.id}`)
    82→          if (response.ok) {
    83→            const data = await response.json()
    84→            setProjectMemory(data)
    85→          }
    86→        } else if (activeTab === 'global') {
    87→          const response = await fetch(`${API_BASE}/global`)
    88→          if (response.ok) {
    89→            const data = await response.json()
    90→            setGlobalMemory(data)
    91→          }
    92→        } else if (activeTab === 'infrastructure') {
    93→          const response = await fetch(`${API_BASE}/infrastructure`)
    94→          if (response.ok) {
    95→            const data = await response.json()
    96→            setInfrastructure(data)
    97→          }
    98→        }
    99→      } catch (error) {
   100→        console.error('Failed to fetch memory items:', error)

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import { useState, useEffect } from 'react'
import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil } from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'
import * as AlertDialog from '@radix-ui/react-alert-dialog'
import { useProjectStore } from '../stores/projectStore'

type MemoryTab = 'project' | 'global' | 'infrastructure'

interface ProjectMemoryItem {
  id: number
  project_id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  created_at: string
}

interface GlobalMemoryItem {
  id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  usage_count: number
  created_at: string
}

interface InfrastructureItem {
  id: number
  name: string
  type: string
  config: Record<string, unknown>
  projects: number[] | null
  created_at: string
  updated_at: string
}

const API_BASE = 'http://localhost:8000/api/memory'

export default function MemoryManager() {
  const { currentProject } = useProjectStore()
  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
  const [searchQuery, setSearchQuery] = useState('')

  // Data states
  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
  const [isLoading, setIsLoading] = useState(false)

  // Dialog states
  const [showAddDialog, setShowAddDialog] = useState(false)
  const [newItemType, setNewItemType] = useState('')
  const [newItemContent, setNewItemContent] = useState('')
  const [newItemName, setNewItemName] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Delete dialog states
  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
  const [itemToDelete, setItemToDelete] = useState<{ id: number; type: MemoryTab } | null>(null)
  const [isDeleting, setIsDeleting] = useState(false)

  // Edit dialog states
  const [showEditDialog, setShowEditDialog] = useState(false)
  const [editItem, setEditItem] = useState<{ id: number; type: string; content: string; memoryType: MemoryTab } | null>(null)
  const [editItemType, setEditItemType] = useState('')
  const [editItemContent, setEditItemContent] = useState('')
  const [isEditing, setIsEditing] = useState(false)

  const tabs = [
    { id: 'project' as const, label: 'Project Memory', icon: Brain },
    { id: 'global' as const, label: 'Global Memory', icon: Globe },
    { id: 'infrastructure' as const, label: 'Infrastructure', icon: Server },
  ]

  // Fetch data based on active tab
  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true)
      try {
        if (activeTab === 'project' && currentProject) {
          const response = await fetch(`${API_BASE}/project/${currentProject.id}`)
          if (response.ok) {
            const data = await response.json()
            setProjectMemory(data)
          }
        } else if (activeTab === 'global') {
          const response = await fetch(`${API_BASE}/global`)
          if (response.ok) {
            const data = await response.json()
            setGlobalMemory(data)
          }
        } else if (activeTab === 'infrastructure') {
          const response = await fetch(`${API_BASE}/infrastructure`)
          if (response.ok) {
            const data = await response.json()
            setInfrastructure(data)
          }
        }
      } catch (error) {
        console.error('Failed to fetch memory items:', error)


Edit

import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil } from 'lucide-react'

import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil, Download } from 'lucide-react'


Error: File has been unexpectedly modified. Read it again before attempting to write it.


Bash

Read first 10 lines of MemoryManager.tsx


import { useState, useEffect } from 'react'
import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil } from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'
import * as AlertDialog from '@radix-ui/react-alert-dialog'
import { useProjectStore } from '../stores/projectStore'

type MemoryTab = 'project' | 'global' | 'infrastructure'

interface ProjectMemoryItem {
  id: number


sed -i "s/import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil } from 'lucide-react'/import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil, Download } from 'lucide-react'/" "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Add Download icon import


Now I need to add the toast store import and export functionality. Let me read the file structure more:


Read top of MemoryManager.tsx


import { useState, useEffect } from 'react'
import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil, Download } from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'
import * as AlertDialog from '@radix-ui/react-alert-dialog'
import { useProjectStore } from '../stores/projectStore'

type MemoryTab = 'project' | 'global' | 'infrastructure'

interface ProjectMemoryItem {
  id: number
  project_id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  created_at: string
}

interface GlobalMemoryItem {
  id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  usage_count: number
  created_at: string
}

interface InfrastructureItem {
  id: number
  name: string
  type: string
  config: Record<string, unknown>
  projects: number[] | null
  created_at: string
  updated_at: string
}

const API_BASE = 'http://localhost:8000/api/memory'

export default function MemoryManager() {
  const { currentProject } = useProjectStore()
  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
  const [searchQuery, setSearchQuery] = useState('')

  // Data states
  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
  const [isLoading, setIsLoading] = useState(false)

  // Dialog states


sed -i "s/import { useProjectStore } from '..\/stores\/projectStore'/import { useProjectStore } from '..\/stores\/projectStore'\nimport { useToastStore } from '..\/stores\/toastStore'/" "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Add toast store import


Now let me find the header section where I need to add the export button:


grep -n "Memory Manager" "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx" | head -5

Find Memory Manager heading


296:
Memory Manager


sed -n '290,310p' "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Read around line 296


const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

      {/* Tabs */}

        {tabs.map((tab) => {
          const Icon = tab.icon
          return (


I need to add the export button and an export handler. Let me look at how project export is implemented to follow the same pattern:


C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx:156:  const handleExportProject = async () => {
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-157-    if (!currentProject) return
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-158-    setIsExporting(true)
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-159-    try {
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-160-      const response = await fetch(`http://localhost:8001/api/projects/${currentProject.id}/export`)
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-161-      if (!response.ok) {
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-162-        throw new Error('Failed to export project')
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-163-      }
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-164-      const blob = await response.blob()
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-165-      const url = window.URL.createObjectURL(blob)
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-166-      const a = document.createElement('a')
--
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx:249:            onClick={handleExportProject}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-250-            disabled={isExporting}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-251-            className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-accent hover:bg-accent/10 rounded-lg transition-colors disabled:opacity-50"
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-252-            title="Export Project Data"
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-253-          >
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-254-            <Download size={16} />
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-255-            <span>{isExporting ? 'Exporting...' : 'Export'}</span>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-256-          </button>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-257-
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-258-          {/* Edit Button and Dialog */}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Dashboard.tsx-259-          <Dialog.Root open={showEditDialog} onOpenChange={setShowEditDialog}>
--
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx:71:  const handleExport = async (format: 'markdown' | 'text') => {
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-72-    if (!currentProject) return
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-73-
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-74-    setIsExporting(true)
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-75-    try {
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-76-      const response = await fetch(
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-77-        `${API_BASE}/projects/${currentProject.id}/changelog/export?format=${format}`
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-78-      )
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-79-      if (!response.ok) {
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-80-        throw new Error('Failed to export changelog')
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-81-      }
--
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx:161:                onClick={() => handleExport('markdown')}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-162-                disabled={isExporting}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-163-                className="w-full px-3 py-2 text-sm text-left hover:bg-secondary rounded-t-lg transition-colors"
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-164-              >
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-165-                Export as Markdown
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-166-              </button>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-167-              <button
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx:168:                onClick={() => handleExport('text')}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-169-                disabled={isExporting}
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-170-                className="w-full px-3 py-2 text-sm text-left hover:bg-secondary rounded-b-lg transition-colors"
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-171-              >
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-172-                Export as Text
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-173-              </button>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-174-            </div>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-175-          </div>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-176-        </div>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-177-      </div>
C:\Users\MikeSwanson\AutoBuilder\My-Auto-Builder\frontend\src\pages\Changelog.tsx-178-


Good, I can see the pattern. Now let me add the export functionality to the MemoryManager. I'll need to:
1. Add state for isExporting
2. Add the handleExportMemory function
3. Add the Export button next to Add Memory Item


grep -n "isEditing, setIsEditing" "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Find isEditing line


68:  const [isEditing, setIsEditing] = useState(false)


sed -i '68 a\  const [isExporting, setIsExporting] = useState(false)' "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Add isExporting state


Now I need to add the toast store usage and the export handler function. Let me find where to add it:


grep -n "const { currentProject }" "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Find currentProject line


41:  const { currentProject } = useProjectStore()


sed -i '41 a\  const { addToast } = useToastStore()' "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Add toast store usage


Now let me add the export handler function. I need to find a good place to add it - after the filterItems function:


grep -n "const filteredInfrastructure" "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/MemoryManager.tsx"

Find filteredInfrastructure line


292:  const filteredInfrastructure = filterItems(infrastructure)


285→      item.name?.toLowerCase().includes(query) ||
   286→      item.type.toLowerCase().includes(query)
   287→    )
   288→  }
   289→
   290→  const filteredProjectMemory = filterItems(projectMemory)
   291→  const filteredGlobalMemory = filterItems(globalMemory)
   292→  const filteredInfrastructure = filterItems(infrastructure)
   293→
   294→  return (
   295→

   296→      {/* Header */}
   297→

   298→
Memory Manager

   299→        <button
   300→          onClick={handleOpenAddDialog}
   301→          className="btn-accent flex items-center gap-2"
   302→        >
   303→          <Plus size={18} />
   304→          Add Memory Item
   305→        </button>
   306→

   307→
   308→      {/* Tabs */}
   309→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

item.name?.toLowerCase().includes(query) ||
      item.type.toLowerCase().includes(query)
    )
  }

  const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

      {/* Tabs */}


Edit

const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  const handleExportMemory = async () => {
    setIsExporting(true)
    try {
      const url = currentProject
        ? `${API_BASE}/export?project_id=${currentProject.id}`
        : `${API_BASE}/export`
      const response = await fetch(url)
      if (!response.ok) {
        throw new Error('Failed to export memory')
      }
      const data = await response.json()
      const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
      const downloadUrl = window.URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = downloadUrl
      a.download = `memory_export_${new Date().toISOString().split('T')[0]}.json`
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      window.URL.revokeObjectURL(downloadUrl)
      addToast({
        title: 'Export Complete',
        message: 'Memory items exported successfully.',
        type: 'success',
      })
    } catch (error) {
      console.error('Failed to export memory:', error)
      addToast({
        title: 'Export Failed',
        message: 'Failed to export memory items.',
        type: 'error',
      })
    } finally {
      setIsExporting(false)
    }
  }

  return (

      {/* Header */}

Memory Manager

          <button
            onClick={handleExportMemory}
            disabled={isExporting}
            className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-accent hover:bg-accent/10 rounded-lg transition-colors disabled:opacity-50"
            title="Export Memory Items"
          >
            <Download size={16} />
            {isExporting ? 'Exporting...' : 'Export'}
          </button>
          <button
            onClick={handleOpenAddDialog}
            className="btn-accent flex items-center gap-2"
          >
            <Plus size={18} />
            Add Memory Item
          </button>


const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  const handleExportMemory = async () => {
    setIsExporting(true)
    try {
      const url = currentProject
        ? `${API_BASE}/export?project_id=${currentProject.id}`
        : `${API_BASE}/export`
      const response = await fetch(url)
      if (!response.ok) {
        throw new Error('Failed to export memory')
      }
      const data = await response.json()
      const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
      const downloadUrl = window.URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = downloadUrl
      a.download = `memory_export_${new Date().toISOString().split('T')[0]}.json`
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      window.URL.revokeObjectURL(downloadUrl)
      addToast({
        title: 'Export Complete',
        message: 'Memory items exported successfully.',
        type: 'success',
      })
    } catch (error) {
      console.error('Failed to export memory:', error)
      addToast({
        title: 'Export Failed',
        message: 'Failed to export memory items.',
        type: 'error',
      })
    } finally {
      setIsExporting(false)
    }
  }

  return (

      {/* Header */}

Memory Manager

          <button
            onClick={handleExportMemory}
            disabled={isExporting}
            className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-accent hover:bg-accent/10 rounded-lg transition-colors disabled:opacity-50"
            title="Export Memory Items"
          >
            <Download size={16} />
            {isExporting ? 'Exporting...' : 'Export'}
          </button>
          <button
            onClick={handleOpenAddDialog}
            className="btn-accent flex items-center gap-2"
          >
            <Plus size={18} />
            Add Memory Item
          </button>


The file keeps getting modified. Let me try a different approach - use a Python script:


1→import { useState, useEffect } from 'react'
     2→import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil, Download } from 'lucide-react'
     3→import * as Dialog from '@radix-ui/react-dialog'
     4→import * as AlertDialog from '@radix-ui/react-alert-dialog'
     5→import { useProjectStore } from '../stores/projectStore'
     6→import { useToastStore } from '../stores/toastStore'
     7→
     8→type MemoryTab = 'project' | 'global' | 'infrastructure'
     9→
    10→interface ProjectMemoryItem {
    11→  id: number
    12→  project_id: number
    13→  type: string
    14→  content: string
    15→  metadata: Record<string, unknown> | null
    16→  created_at: string
    17→}
    18→
    19→interface GlobalMemoryItem {
    20→  id: number
    21→  type: string
    22→  content: string
    23→  metadata: Record<string, unknown> | null
    24→  usage_count: number
    25→  created_at: string
    26→}
    27→
    28→interface InfrastructureItem {
    29→  id: number
    30→  name: string
    31→  type: string
    32→  config: Record<string, unknown>
    33→  projects: number[] | null
    34→  created_at: string
    35→  updated_at: string
    36→}
    37→
    38→const API_BASE = 'http://localhost:8000/api/memory'
    39→
    40→export default function MemoryManager() {
    41→  const { currentProject } = useProjectStore()
    42→  const { addToast } = useToastStore()
    43→  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
    44→  const [searchQuery, setSearchQuery] = useState('')
    45→
    46→  // Data states
    47→  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
    48→  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
    49→  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
    50→  const [isLoading, setIsLoading] = useState(false)
    51→
    52→  // Dialog states
    53→  const [showAddDialog, setShowAddDialog] = useState(false)
    54→  const [newItemType, setNewItemType] = useState('')
    55→  const [newItemContent, setNewItemContent] = useState('')
    56→  const [newItemName, setNewItemName] = useState('')
    57→  const [isSaving, setIsSaving] = useState(false)
    58→
    59→  // Delete dialog states
    60→  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
    61→  const [itemToDelete, setItemToDelete] = useState<{ id: number; type: MemoryTab } | null>(null)
    62→  const [isDeleting, setIsDeleting] = useState(false)
    63→
    64→  // Edit dialog states
    65→  const [showEditDialog, setShowEditDialog] = useState(false)
    66→  const [editItem, setEditItem] = useState<{ id: number; type: string; content: string; memoryType: MemoryTab } | null>(null)
    67→  const [editItemType, setEditItemType] = useState('')
    68→  const [editItemContent, setEditItemContent] = useState('')
    69→  const [isEditing, setIsEditing] = useState(false)
    70→  const [isExporting, setIsExporting] = useState(false)
    71→
    72→  const tabs = [
    73→    { id: 'project' as const, label: 'Project Memory', icon: Brain },
    74→    { id: 'global' as const, label: 'Global Memory', icon: Globe },
    75→    { id: 'infrastructure' as const, label: 'Infrastructure', icon: Server },
    76→  ]
    77→
    78→  // Fetch data based on active tab
    79→  useEffect(() => {
    80→    const fetchData = async () => {
    81→      setIsLoading(true)
    82→      try {
    83→        if (activeTab === 'project' && currentProject) {
    84→          const response = await fetch(`${API_BASE}/project/${currentProject.id}`)
    85→          if (response.ok) {
    86→            const data = await response.json()
    87→            setProjectMemory(data)
    88→          }
    89→        } else if (activeTab === 'global') {
    90→          const response = await fetch(`${API_BASE}/global`)
    91→          if (response.ok) {
    92→            const data = await response.json()
    93→            setGlobalMemory(data)
    94→          }
    95→        } else if (activeTab === 'infrastructure') {
    96→          const response = await fetch(`${API_BASE}/infrastructure`)
    97→          if (response.ok) {
    98→            const data = await response.json()
    99→            setInfrastructure(data)
   100→          }
   101→        }
   102→      } catch (error) {
   103→        console.error('Failed to fetch memory items:', error)
   104→      } finally {
   105→        setIsLoading(false)
   106→      }
   107→    }
   108→    fetchData()
   109→  }, [activeTab, currentProject])
   110→
   111→  const getTypeOptions = () => {
   112→    switch (activeTab) {
   113→      case 'project':
   114→        return ['insight', 'pattern', 'gotcha', 'codebase_map']
   115→      case 'global':
   116→        return ['preference', 'pattern', 'solution']
   117→      case 'infrastructure':
   118→        return ['server', 'docker', 'database', 'deployment']
   119→      default:
   120→        return []
   121→    }
   122→  }
   123→
   124→  const handleOpenAddDialog = () => {
   125→    setNewItemType(getTypeOptions()[0] || '')
   126→    setNewItemContent('')
   127→    setNewItemName('')
   128→    setShowAddDialog(true)
   129→  }
   130→
   131→  const handleAddItem = async () => {
   132→    if (!newItemType || (!newItemContent.trim() && activeTab !== 'infrastructure')) return
   133→    if (activeTab === 'infrastructure' && !newItemName.trim()) return
   134→
   135→    setIsSaving(true)
   136→    try {
   137→      let response: Response
   138→
   139→      if (activeTab === 'project' && currentProject) {
   140→        response = await fetch(`${API_BASE}/project/${currentProject.id}`, {
   141→          method: 'POST',
   142→          headers: { 'Content-Type': 'application/json' },
   143→          body: JSON.stringify({ type: newItemType, content: newItemContent.trim() }),
   144→        })
   145→        if (response.ok) {
   146→          const newItem = await response.json()
   147→          setProjectMemory([...projectMemory, newItem])
   148→        }
   149→      } else if (activeTab === 'global') {
   150→        response = await fetch(`${API_BASE}/global`, {
   151→          method: 'POST',
   152→          headers: { 'Content-Type': 'application/json' },
   153→          body: JSON.stringify({ type: newItemType, content: newItemContent.trim() }),
   154→        })
   155→        if (response.ok) {
   156→          const newItem = await response.json()
   157→          setGlobalMemory([...globalMemory, newItem])
   158→        }
   159→      } else if (activeTab === 'infrastructure') {
   160→        response = await fetch(`${API_BASE}/infrastructure`, {
   161→          method: 'POST',
   162→          headers: { 'Content-Type': 'application/json' },
   163→          body: JSON.stringify({
   164→            name: newItemName.trim(),
   165→            type: newItemType,
   166→            config: { content: newItemContent.trim() }
   167→          }),
   168→        })
   169→        if (response.ok) {
   170→          const newItem = await response.json()
   171→          setInfrastructure([...infrastructure, newItem])
   172→        }
   173→      }
   174→
   175→      setShowAddDialog(false)
   176→    } catch (error) {
   177→      console.error('Failed to add memory item:', error)
   178→    } finally {
   179→      setIsSaving(false)
   180→    }
   181→  }
   182→
   183→  const handleDeleteClick = (id: number, type: MemoryTab) => {
   184→    setItemToDelete({ id, type })
   185→    setShowDeleteDialog(true)
   186→  }
   187→
   188→  const handleDeleteConfirm = async () => {
   189→    if (!itemToDelete) return
   190→
   191→    setIsDeleting(true)
   192→    try {
   193→      let endpoint: string
   194→
   195→      if (itemToDelete.type === 'project' && currentProject) {
   196→        endpoint = `${API_BASE}/project/${currentProject.id}/${itemToDelete.id}`
   197→      } else if (itemToDelete.type === 'global') {
   198→        endpoint = `${API_BASE}/global/${itemToDelete.id}`
   199→      } else {
   200→        endpoint = `${API_BASE}/infrastructure/${itemToDelete.id}`
   201→      }
   202→
   203→      const response = await fetch(endpoint, { method: 'DELETE' })
   204→
   205→      if (response.ok || response.status === 204) {
   206→        if (itemToDelete.type === 'project') {
   207→          setProjectMemory(projectMemory.filter(item => item.id !== itemToDelete.id))
   208→        } else if (itemToDelete.type === 'global') {
   209→          setGlobalMemory(globalMemory.filter(item => item.id !== itemToDelete.id))
   210→        } else {
   211→          setInfrastructure(infrastructure.filter(item => item.id !== itemToDelete.id))
   212→        }
   213→      }
   214→
   215→      setShowDeleteDialog(false)
   216→      setItemToDelete(null)
   217→    } catch (error) {
   218→      console.error('Failed to delete memory item:', error)
   219→    } finally {
   220→      setIsDeleting(false)
   221→    }
   222→  }
   223→
   224→  const handleEditClick = (id: number, type: string, content: string, memoryType: MemoryTab) => {
   225→    setEditItem({ id, type, content, memoryType })
   226→    setEditItemType(type)
   227→    setEditItemContent(content)
   228→    setShowEditDialog(true)
   229→  }
   230→
   231→  const handleEditSave = async () => {
   232→    if (!editItem || !editItemContent.trim()) return
   233→
   234→    setIsEditing(true)
   235→    try {
   236→      let endpoint: string
   237→      let body: Record<string, unknown>
   238→
   239→      if (editItem.memoryType === 'project' && currentProject) {
   240→        endpoint = `${API_BASE}/project/${currentProject.id}/${editItem.id}`
   241→        body = { type: editItemType, content: editItemContent.trim() }
   242→      } else if (editItem.memoryType === 'global') {
   243→        endpoint = `${API_BASE}/global/${editItem.id}`
   244→        body = { type: editItemType, content: editItemContent.trim() }
   245→      } else {
   246→        // Infrastructure uses different update endpoint
   247→        setShowEditDialog(false)
   248→        setEditItem(null)
   249→        return
   250→      }
   251→
   252→      const response = await fetch(endpoint, {
   253→        method: 'PUT',
   254→        headers: { 'Content-Type': 'application/json' },
   255→        body: JSON.stringify(body),
   256→      })
   257→
   258→      if (response.ok) {
   259→        const updatedItem = await response.json()
   260→        if (editItem.memoryType === 'project') {
   261→          setProjectMemory(projectMemory.map(item =>
   262→            item.id === editItem.id ? updatedItem : item
   263→          ))
   264→        } else if (editItem.memoryType === 'global') {
   265→          setGlobalMemory(globalMemory.map(item =>
   266→            item.id === editItem.id ? updatedItem : item
   267→          ))
   268→        }
   269→      }
   270→
   271→      setShowEditDialog(false)
   272→      setEditItem(null)
   273→    } catch (error) {
   274→      console.error('Failed to update memory item:', error)
   275→    } finally {
   276→      setIsEditing(false)
   277→    }
   278→  }
   279→
   280→  const filterItems = <T extends { content?: string; name?: string; type: string }>(items: T[]) => {
   281→    if (!searchQuery) return items
   282→    const query = searchQuery.toLowerCase()
   283→    return items.filter(item =>
   284→      item.content?.toLowerCase().includes(query) ||
   285→      item.name?.toLowerCase().includes(query) ||
   286→      item.type.toLowerCase().includes(query)
   287→    )
   288→  }
   289→
   290→  const filteredProjectMemory = filterItems(projectMemory)
   291→  const filteredGlobalMemory = filterItems(globalMemory)
   292→  const filteredInfrastructure = filterItems(infrastructure)
   293→
   294→  return (
   295→

   296→      {/* Header */}
   297→

   298→
Memory Manager

   299→        <button
   300→          onClick={handleOpenAddDialog}
   301→          className="btn-accent flex items-center gap-2"
   302→        >
   303→          <Plus size={18} />
   304→          Add Memory Item
   305→        </button>
   306→

   307→
   308→      {/* Tabs */}
   309→

   310→        {tabs.map((tab) => {
   311→          const Icon = tab.icon
   312→          return (
   313→            <button
   314→              key={tab.id}
   315→              onClick={() => setActiveTab(tab.id)}
   316→              className={`flex items-center gap-2 px-4 py-2 rounded-md transition-colors ${
   317→                activeTab === tab.id
   318→                  ? 'bg-primary text-primary-foreground'
   319→                  : 'text-muted-foreground hover:text-foreground'
   320→              }`}
   321→            >
   322→              <Icon size={16} />
   323→              {tab.label}
   324→            </button>
   325→          )
   326→        })}
   327→

   328→
   329→      {/* Search */}
   330→

   331→        <Search
   332→          size={18}
   333→          className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
   334→        />
   335→        <input
   336→          type="text"
   337→          value={searchQuery}
   338→          onChange={(e) => setSearchQuery(e.target.value)}
   339→          placeholder="Search memory items..."
   340→          className="w-full pl-10 pr-4 py-2 bg-card border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent"
   341→        />
   342→

   343→
   344→      {/* Content */}
   345→

   346→        {isLoading ? (
   347→
Loading...

   348→        ) : (
   349→          <>
   350→            {activeTab === 'project' && (
   351→

   352→                {filteredProjectMemory.length === 0 ? (
   353→                  <EmptyState
   354→                    title="No Project Memory"
   355→                    description="Memory items from your current project will appear here."
   356→                  />
   357→                ) : (
   358→                  filteredProjectMemory.map(item => (
   359→                    <MemoryCard
   360→                      key={item.id}
   361→                      id={item.id}
   362→                      type={item.type}
   363→                      content={item.content}
   364→                      createdAt={item.created_at}
   365→                      onDelete={() => handleDeleteClick(item.id, 'project')}
   366→                      onEdit={() => handleEditClick(item.id, item.type, item.content, 'project')}
   367→                    />
   368→                  ))
   369→                )}
   370→

   371→            )}
   372→
   373→            {activeTab === 'global' && (
   374→

   375→                {filteredGlobalMemory.length === 0 ? (
   376→                  <EmptyState
   377→                    title="No Global Memory"
   378→                    description="Cross-project patterns and preferences will appear here."
   379→                  />
   380→                ) : (
   381→                  filteredGlobalMemory.map(item => (
   382→                    <MemoryCard
   383→                      key={item.id}
   384→                      id={item.id}
   385→                      type={item.type}
   386→                      content={item.content}
   387→                      createdAt={item.created_at}
   388→                      usageCount={item.usage_count}
   389→                      onDelete={() => handleDeleteClick(item.id, 'global')}
   390→                      onEdit={() => handleEditClick(item.id, item.type, item.content, 'global')}
   391→                    />
   392→                  ))
   393→                )}
   394→

   395→            )}
   396→
   397→            {activeTab === 'infrastructure' && (
   398→

   399→                {filteredInfrastructure.length === 0 ? (
   400→                  <EmptyState
   401→                    title="No Infrastructure Config"
   402→                    description="Server and deployment configurations will appear here."
   403→                  />
   404→                ) : (
   405→                  filteredInfrastructure.map(item => (
   406→                    <InfrastructureCard
   407→                      key={item.id}
   408→                      id={item.id}
   409→                      name={item.name}
   410→                      type={item.type}
   411→                      config={item.config}
   412→                      createdAt={item.created_at}
   413→                      onDelete={() => handleDeleteClick(item.id, 'infrastructure')}
   414→                    />
   415→                  ))
   416→                )}
   417→

   418→            )}
   419→          </>
   420→        )}
   421→

   422→
   423→      {/* Add Memory Dialog */}
   424→      <Dialog.Root open={showAddDialog} onOpenChange={setShowAddDialog}>
   425→        <Dialog.Portal>
   426→          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   427→          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-4 md:p-6 w-[calc(100%-2rem)] max-w-md max-h-[calc(100vh-2rem)] overflow-y-auto z-50 shadow-xl">
   428→

   429→              <Dialog.Title className="text-xl font-semibold text-foreground">
   430→                Add {activeTab === 'project' ? 'Project' : activeTab === 'global' ? 'Global' : 'Infrastructure'} Memory
   431→              </Dialog.Title>
   432→              <Dialog.Close asChild>
   433→                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors" aria-label="Close">
   434→                  <X size={20} />
   435→                </button>
   436→              </Dialog.Close>
   437→

   438→
   439→

   440→              {activeTab === 'infrastructure' && (
   441→

   442→                  Name *
   443→                  <input
   444→                    type="text"
   445→                    value={newItemName}
   446→                    onChange={(e) => setNewItemName(e.target.value)}
   447→                    className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent"
   448→                    placeholder="Enter config name"
   449→                  />
   450→

   451→              )}
   452→
   453→

   454→                Type *
   455→                <select
   456→                  value={newItemType}
   457→                  onChange={(e) => setNewItemType(e.target.value)}
   458→                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground focus:outline-none focus:ring-2 focus:ring-accent"
   459→                >
   460→                  {getTypeOptions().map(type => (
   461→                    <option key={type} value={type}>{type}</option>
   462→                  ))}
   463→                </select>
   464→

   465→
   466→

   467→                Content *
   468→                <textarea
   469→                  value={newItemContent}
   470→                  onChange={(e) => setNewItemContent(e.target.value)}
   471→                  rows={4}
   472→                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent resize-none"
   473→                  placeholder="Enter memory content..."
   474→                />
   475→

   476→

   477→
   478→

   479→              <Dialog.Close asChild>
   480→                <button className="px-4 py-2 text-sm text-secondary-foreground hover:bg-secondary rounded-lg transition-colors">
   481→                  Cancel
   482→                </button>
   483→              </Dialog.Close>
   484→              <button
   485→                onClick={handleAddItem}
   486→                disabled={isSaving || !newItemContent.trim() || (activeTab === 'infrastructure' && !newItemName.trim())}
   487→                className="px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   488→              >
   489→                {isSaving ? 'Saving...' : 'Add Item'}
   490→              </button>
   491→

   492→          </Dialog.Content>
   493→        </Dialog.Portal>
   494→      </Dialog.Root>
   495→
   496→      {/* Delete Confirmation Dialog */}
   497→      <AlertDialog.Root open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
   498→        <AlertDialog.Portal>
   499→          <AlertDialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   500→          <AlertDialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-4 md:p-6 w-[calc(100%-2rem)] max-w-md max-h-[calc(100vh-2rem)] overflow-y-auto z-50 shadow-xl">
   501→            <AlertDialog.Title className="text-xl font-semibold text-foreground">
   502→              Delete Memory Item
   503→            </AlertDialog.Title>
   504→            <AlertDialog.Description className="mt-3 text-muted-foreground">
   505→              Are you sure you want to delete this memory item? This action cannot be undone.
   506→            </AlertDialog.Description>
   507→

   508→              <AlertDialog.Cancel asChild>
   509→                <button className="px-4 py-2 text-sm text-secondary-foreground hover:bg-secondary rounded-lg transition-colors">
   510→                  Cancel
   511→                </button>
   512→              </AlertDialog.Cancel>
   513→              <AlertDialog.Action asChild>
   514→                <button
   515→                  onClick={handleDeleteConfirm}
   516→                  disabled={isDeleting}
   517→                  className="px-4 py-2 text-sm bg-destructive hover:bg-destructive/80 text-white rounded-lg transition-colors disabled:opacity-50"
   518→                >
   519→                  {isDeleting ? 'Deleting...' : 'Delete'}
   520→                </button>
   521→              </AlertDialog.Action>
   522→

   523→          </AlertDialog.Content>
   524→        </AlertDialog.Portal>
   525→      </AlertDialog.Root>
   526→
   527→      {/* Edit Memory Dialog */}
   528→      <Dialog.Root open={showEditDialog} onOpenChange={setShowEditDialog}>
   529→        <Dialog.Portal>
   530→          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   531→          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-4 md:p-6 w-[calc(100%-2rem)] max-w-md max-h-[calc(100vh-2rem)] overflow-y-auto z-50 shadow-xl">
   532→

   533→              <Dialog.Title className="text-xl font-semibold text-foreground">
   534→                Edit Memory Item
   535→              </Dialog.Title>
   536→              <Dialog.Close asChild>
   537→                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors" aria-label="Close">
   538→                  <X size={20} />
   539→                </button>
   540→              </Dialog.Close>
   541→

   542→
   543→

   544→

   545→                Type *
   546→                <select
   547→                  value={editItemType}
   548→                  onChange={(e) => setEditItemType(e.target.value)}
   549→                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground focus:outline-none focus:ring-2 focus:ring-accent"
   550→                >
   551→                  {(editItem?.memoryType === 'project'
   552→                    ? ['insight', 'pattern', 'gotcha', 'codebase_map']
   553→                    : ['preference', 'pattern', 'solution']
   554→                  ).map(type => (
   555→                    <option key={type} value={type}>{type}</option>
   556→                  ))}
   557→                </select>
   558→

   559→
   560→

   561→                Content *
   562→                <textarea
   563→                  value={editItemContent}
   564→                  onChange={(e) => setEditItemContent(e.target.value)}
   565→                  rows={4}
   566→                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent resize-none"
   567→                  placeholder="Enter memory content..."
   568→                />
   569→

   570→

   571→
   572→

   573→              <Dialog.Close asChild>
   574→                <button className="px-4 py-2 text-sm text-secondary-foreground hover:bg-secondary rounded-lg transition-colors">
   575→                  Cancel
   576→                </button>
   577→              </Dialog.Close>
   578→              <button
   579→                onClick={handleEditSave}
   580→                disabled={isEditing || !editItemContent.trim()}
   581→                className="px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   582→              >
   583→                {isEditing ? 'Saving...' : 'Save Changes'}
   584→              </button>
   585→

   586→          </Dialog.Content>
   587→        </Dialog.Portal>
   588→      </Dialog.Root>
   589→

   590→  )
   591→}
   592→
   593→function MemoryCard({
   594→  id: _id,
   595→  type,
   596→  content,
   597→  createdAt,
   598→  usageCount,
   599→  onDelete,
   600→  onEdit,
   601→}: {
   602→  id: number
   603→  type: string
   604→  content: string
   605→  createdAt: string
   606→  usageCount?: number
   607→  onDelete: () => void
   608→  onEdit?: () => void
   609→}) {
   610→  return (
   611→

   612→

   613→

   614→

   615→
   616→              {type}
   617→
   618→            {usageCount !== undefined && (
   619→              Used {usageCount} times
   620→            )}
   621→

   622→
{content}

   623→

   624→            Created: {new Date(createdAt).toLocaleString()}
   625→

   626→

   627→

   628→          {onEdit && (
   629→            <button
   630→              onClick={onEdit}
   631→              className="p-2 text-muted-foreground hover:text-accent hover:bg-accent/10 rounded-lg transition-colors"
   632→              title="Edit"
   633→              aria-label="Edit memory item"
   634→            >
   635→              <Pencil size={16} />
   636→            </button>
   637→          )}
   638→          <button
   639→            onClick={onDelete}
   640→            className="p-2 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
   641→            title="Delete"
   642→            aria-label="Delete memory item"
   643→          >
   644→            <Trash2 size={16} />
   645→          </button>
   646→

   647→

   648→

   649→  )
   650→}
   651→
   652→function InfrastructureCard({
   653→  id: _id,
   654→  name,
   655→  type,
   656→  config,
   657→  createdAt,
   658→  onDelete,
   659→}: {
   660→  id: number
   661→  name: string
   662→  type: string
   663→  config: Record<string, unknown>
   664→  createdAt: string
   665→  onDelete: () => void
   666→}) {
   667→  return (
   668→

   669→

   670→

   671→

   672→
{name}

   673→
   674→              {type}
   675→
   676→

   677→

   678→            {JSON.stringify(config, null, 2)}
   679→

   680→

   681→            Created: {new Date(createdAt).toLocaleString()}
   682→

   683→

   684→        <button
   685→          onClick={onDelete}
   686→          className="p-2 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
   687→          title="Delete"
   688→        >
   689→          <Trash2 size={16} />
   690→        </button>
   691→

   692→

   693→  )
   694→}
   695→
   696→function EmptyState({
   697→  title,
   698→  description,
   699→}: {
   700→  title: string
   701→  description: string
   702→}) {
   703→  return (
   704→

   705→      <Brain size={48} className="text-muted-foreground mx-auto mb-4" />
   706→
{title}

   707→
{description}

   708→

   709→  )
   710→}
   711→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import { useState, useEffect } from 'react'
import { Brain, Globe, Server, Plus, Search, Trash2, X, Pencil, Download } from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'
import * as AlertDialog from '@radix-ui/react-alert-dialog'
import { useProjectStore } from '../stores/projectStore'
import { useToastStore } from '../stores/toastStore'

type MemoryTab = 'project' | 'global' | 'infrastructure'

interface ProjectMemoryItem {
  id: number
  project_id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  created_at: string
}

interface GlobalMemoryItem {
  id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  usage_count: number
  created_at: string
}

interface InfrastructureItem {
  id: number
  name: string
  type: string
  config: Record<string, unknown>
  projects: number[] | null
  created_at: string
  updated_at: string
}

const API_BASE = 'http://localhost:8000/api/memory'

export default function MemoryManager() {
  const { currentProject } = useProjectStore()
  const { addToast } = useToastStore()
  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
  const [searchQuery, setSearchQuery] = useState('')

  // Data states
  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
  const [isLoading, setIsLoading] = useState(false)

  // Dialog states
  const [showAddDialog, setShowAddDialog] = useState(false)
  const [newItemType, setNewItemType] = useState('')
  const [newItemContent, setNewItemContent] = useState('')
  const [newItemName, setNewItemName] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Delete dialog states
  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
  const [itemToDelete, setItemToDelete] = useState<{ id: number; type: MemoryTab } | null>(null)
  const [isDeleting, setIsDeleting] = useState(false)

  // Edit dialog states
  const [showEditDialog, setShowEditDialog] = useState(false)
  const [editItem, setEditItem] = useState<{ id: number; type: string; content: string; memoryType: MemoryTab } | null>(null)
  const [editItemType, setEditItemType] = useState('')
  const [editItemContent, setEditItemContent] = useState('')
  const [isEditing, setIsEditing] = useState(false)
  const [isExporting, setIsExporting] = useState(false)

  const tabs = [
    { id: 'project' as const, label: 'Project Memory', icon: Brain },
    { id: 'global' as const, label: 'Global Memory', icon: Globe },
    { id: 'infrastructure' as const, label: 'Infrastructure', icon: Server },
  ]

  // Fetch data based on active tab
  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true)
      try {
        if (activeTab === 'project' && currentProject) {
          const response = await fetch(`${API_BASE}/project/${currentProject.id}`)
          if (response.ok) {
            const data = await response.json()
            setProjectMemory(data)
          }
        } else if (activeTab === 'global') {
          const response = await fetch(`${API_BASE}/global`)
          if (response.ok) {
            const data = await response.json()
            setGlobalMemory(data)
          }
        } else if (activeTab === 'infrastructure') {
          const response = await fetch(`${API_BASE}/infrastructure`)
          if (response.ok) {
            const data = await response.json()
            setInfrastructure(data)
          }
        }
      } catch (error) {
        console.error('Failed to fetch memory items:', error)
      } finally {
        setIsLoading(false)
      }
    }
    fetchData()
  }, [activeTab, currentProject])

  const getTypeOptions = () => {
    switch (activeTab) {
      case 'project':
        return ['insight', 'pattern', 'gotcha', 'codebase_map']
      case 'global':
        return ['preference', 'pattern', 'solution']
      case 'infrastructure':
        return ['server', 'docker', 'database', 'deployment']
      default:
        return []
    }
  }

  const handleOpenAddDialog = () => {
    setNewItemType(getTypeOptions()[0] || '')
    setNewItemContent('')
    setNewItemName('')
    setShowAddDialog(true)
  }

  const handleAddItem = async () => {
    if (!newItemType || (!newItemContent.trim() && activeTab !== 'infrastructure')) return
    if (activeTab === 'infrastructure' && !newItemName.trim()) return

    setIsSaving(true)
    try {
      let response: Response

      if (activeTab === 'project' && currentProject) {
        response = await fetch(`${API_BASE}/project/${currentProject.id}`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ type: newItemType, content: newItemContent.trim() }),
        })
        if (response.ok) {
          const newItem = await response.json()
          setProjectMemory([...projectMemory, newItem])
        }
      } else if (activeTab === 'global') {
        response = await fetch(`${API_BASE}/global`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ type: newItemType, content: newItemContent.trim() }),
        })
        if (response.ok) {
          const newItem = await response.json()
          setGlobalMemory([...globalMemory, newItem])
        }
      } else if (activeTab === 'infrastructure') {
        response = await fetch(`${API_BASE}/infrastructure`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            name: newItemName.trim(),
            type: newItemType,
            config: { content: newItemContent.trim() }
          }),
        })
        if (response.ok) {
          const newItem = await response.json()
          setInfrastructure([...infrastructure, newItem])
        }
      }

      setShowAddDialog(false)
    } catch (error) {
      console.error('Failed to add memory item:', error)
    } finally {
      setIsSaving(false)
    }
  }

  const handleDeleteClick = (id: number, type: MemoryTab) => {
    setItemToDelete({ id, type })
    setShowDeleteDialog(true)
  }

  const handleDeleteConfirm = async () => {
    if (!itemToDelete) return

    setIsDeleting(true)
    try {
      let endpoint: string

      if (itemToDelete.type === 'project' && currentProject) {
        endpoint = `${API_BASE}/project/${currentProject.id}/${itemToDelete.id}`
      } else if (itemToDelete.type === 'global') {
        endpoint = `${API_BASE}/global/${itemToDelete.id}`
      } else {
        endpoint = `${API_BASE}/infrastructure/${itemToDelete.id}`
      }

      const response = await fetch(endpoint, { method: 'DELETE' })

      if (response.ok || response.status === 204) {
        if (itemToDelete.type === 'project') {
          setProjectMemory(projectMemory.filter(item => item.id !== itemToDelete.id))
        } else if (itemToDelete.type === 'global') {
          setGlobalMemory(globalMemory.filter(item => item.id !== itemToDelete.id))
        } else {
          setInfrastructure(infrastructure.filter(item => item.id !== itemToDelete.id))
        }
      }

      setShowDeleteDialog(false)
      setItemToDelete(null)
    } catch (error) {
      console.error('Failed to delete memory item:', error)
    } finally {
      setIsDeleting(false)
    }
  }

  const handleEditClick = (id: number, type: string, content: string, memoryType: MemoryTab) => {
    setEditItem({ id, type, content, memoryType })
    setEditItemType(type)
    setEditItemContent(content)
    setShowEditDialog(true)
  }

  const handleEditSave = async () => {
    if (!editItem || !editItemContent.trim()) return

    setIsEditing(true)
    try {
      let endpoint: string
      let body: Record<string, unknown>

      if (editItem.memoryType === 'project' && currentProject) {
        endpoint = `${API_BASE}/project/${currentProject.id}/${editItem.id}`
        body = { type: editItemType, content: editItemContent.trim() }
      } else if (editItem.memoryType === 'global') {
        endpoint = `${API_BASE}/global/${editItem.id}`
        body = { type: editItemType, content: editItemContent.trim() }
      } else {
        // Infrastructure uses different update endpoint
        setShowEditDialog(false)
        setEditItem(null)
        return
      }

      const response = await fetch(endpoint, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      })

      if (response.ok) {
        const updatedItem = await response.json()
        if (editItem.memoryType === 'project') {
          setProjectMemory(projectMemory.map(item =>
            item.id === editItem.id ? updatedItem : item
          ))
        } else if (editItem.memoryType === 'global') {
          setGlobalMemory(globalMemory.map(item =>
            item.id === editItem.id ? updatedItem : item
          ))
        }
      }

      setShowEditDialog(false)
      setEditItem(null)
    } catch (error) {
      console.error('Failed to update memory item:', error)
    } finally {
      setIsEditing(false)
    }
  }

  const filterItems = <T extends { content?: string; name?: string; type: string }>(items: T[]) => {
    if (!searchQuery) return items
    const query = searchQuery.toLowerCase()
    return items.filter(item =>
      item.content?.toLowerCase().includes(query) ||
      item.name?.toLowerCase().includes(query) ||
      item.type.toLowerCase().includes(query)
    )
  }

  const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

      {/* Tabs */}

        {tabs.map((tab) => {
          const Icon = tab.icon
          return (
            <button
              key={tab.id}
              onClick={() => setActiveTab(tab.id)}
              className={`flex items-center gap-2 px-4 py-2 rounded-md transition-colors ${
                activeTab === tab.id
                  ? 'bg-primary text-primary-foreground'
                  : 'text-muted-foreground hover:text-foreground'
              }`}
            >
              <Icon size={16} />
              {tab.label}
            </button>
          )
        })}

      {/* Search */}

        <Search
          size={18}
          className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
        />
        <input
          type="text"
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          placeholder="Search memory items..."
          className="w-full pl-10 pr-4 py-2 bg-card border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent"
        />

      {/* Content */}

        {isLoading ? (

Loading...

        ) : (
          <>
            {activeTab === 'project' && (

                {filteredProjectMemory.length === 0 ? (
                  <EmptyState
                    title="No Project Memory"
                    description="Memory items from your current project will appear here."
                  />
                ) : (
                  filteredProjectMemory.map(item => (
                    <MemoryCard
                      key={item.id}
                      id={item.id}
                      type={item.type}
                      content={item.content}
                      createdAt={item.created_at}
                      onDelete={() => handleDeleteClick(item.id, 'project')}
                      onEdit={() => handleEditClick(item.id, item.type, item.content, 'project')}
                    />
                  ))
                )}

            )}

            {activeTab === 'global' && (

                {filteredGlobalMemory.length === 0 ? (
                  <EmptyState
                    title="No Global Memory"
                    description="Cross-project patterns and preferences will appear here."
                  />
                ) : (
                  filteredGlobalMemory.map(item => (
                    <MemoryCard
                      key={item.id}
                      id={item.id}
                      type={item.type}
                      content={item.content}
                      createdAt={item.created_at}
                      usageCount={item.usage_count}
                      onDelete={() => handleDeleteClick(item.id, 'global')}
                      onEdit={() => handleEditClick(item.id, item.type, item.content, 'global')}
                    />
                  ))
                )}

            )}

            {activeTab === 'infrastructure' && (

                {filteredInfrastructure.length === 0 ? (
                  <EmptyState
                    title="No Infrastructure Config"
                    description="Server and deployment configurations will appear here."
                  />
                ) : (
                  filteredInfrastructure.map(item => (
                    <InfrastructureCard
                      key={item.id}
                      id={item.id}
                      name={item.name}
                      type={item.type}
                      config={item.config}
                      createdAt={item.created_at}
                      onDelete={() => handleDeleteClick(item.id, 'infrastructure')}
                    />
                  ))
                )}

            )}
          </>
        )}

      {/* Add Memory Dialog */}
      <Dialog.Root open={showAddDialog} onOpenChange={setShowAddDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-4 md:p-6 w-[calc(100%-2rem)] max-w-md max-h-[calc(100vh-2rem)] overflow-y-auto z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-foreground">
                Add {activeTab === 'project' ? 'Project' : activeTab === 'global' ? 'Global' : 'Infrastructure'} Memory
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors" aria-label="Close">
                  <X size={20} />
                </button>
              </Dialog.Close>

              {activeTab === 'infrastructure' && (

                  Name *
                  <input
                    type="text"
                    value={newItemName}
                    onChange={(e) => setNewItemName(e.target.value)}
                    className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent"
                    placeholder="Enter config name"
                  />

              )}

                Type *
                <select
                  value={newItemType}
                  onChange={(e) => setNewItemType(e.target.value)}
                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground focus:outline-none focus:ring-2 focus:ring-accent"
                >
                  {getTypeOptions().map(type => (
                    <option key={type} value={type}>{type}</option>
                  ))}
                </select>

                Content *
                <textarea
                  value={newItemContent}
                  onChange={(e) => setNewItemContent(e.target.value)}
                  rows={4}
                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent resize-none"
                  placeholder="Enter memory content..."
                />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-secondary-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleAddItem}
                disabled={isSaving || !newItemContent.trim() || (activeTab === 'infrastructure' && !newItemName.trim())}
                className="px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSaving ? 'Saving...' : 'Add Item'}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

      {/* Delete Confirmation Dialog */}
      <AlertDialog.Root open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
        <AlertDialog.Portal>
          <AlertDialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <AlertDialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-4 md:p-6 w-[calc(100%-2rem)] max-w-md max-h-[calc(100vh-2rem)] overflow-y-auto z-50 shadow-xl">
            <AlertDialog.Title className="text-xl font-semibold text-foreground">
              Delete Memory Item
            </AlertDialog.Title>
            <AlertDialog.Description className="mt-3 text-muted-foreground">
              Are you sure you want to delete this memory item? This action cannot be undone.
            </AlertDialog.Description>

              <AlertDialog.Cancel asChild>
                <button className="px-4 py-2 text-sm text-secondary-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </AlertDialog.Cancel>
              <AlertDialog.Action asChild>
                <button
                  onClick={handleDeleteConfirm}
                  disabled={isDeleting}
                  className="px-4 py-2 text-sm bg-destructive hover:bg-destructive/80 text-white rounded-lg transition-colors disabled:opacity-50"
                >
                  {isDeleting ? 'Deleting...' : 'Delete'}
                </button>
              </AlertDialog.Action>

          </AlertDialog.Content>
        </AlertDialog.Portal>
      </AlertDialog.Root>

      {/* Edit Memory Dialog */}
      <Dialog.Root open={showEditDialog} onOpenChange={setShowEditDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-4 md:p-6 w-[calc(100%-2rem)] max-w-md max-h-[calc(100vh-2rem)] overflow-y-auto z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-foreground">
                Edit Memory Item
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors" aria-label="Close">
                  <X size={20} />
                </button>
              </Dialog.Close>

                Type *
                <select
                  value={editItemType}
                  onChange={(e) => setEditItemType(e.target.value)}
                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground focus:outline-none focus:ring-2 focus:ring-accent"
                >
                  {(editItem?.memoryType === 'project'
                    ? ['insight', 'pattern', 'gotcha', 'codebase_map']
                    : ['preference', 'pattern', 'solution']
                  ).map(type => (
                    <option key={type} value={type}>{type}</option>
                  ))}
                </select>

                Content *
                <textarea
                  value={editItemContent}
                  onChange={(e) => setEditItemContent(e.target.value)}
                  rows={4}
                  className="w-full px-3 py-2 bg-background border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent resize-none"
                  placeholder="Enter memory content..."
                />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-secondary-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleEditSave}
                disabled={isEditing || !editItemContent.trim()}
                className="px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isEditing ? 'Saving...' : 'Save Changes'}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

  )
}

function MemoryCard({
  id: _id,
  type,
  content,
  createdAt,
  usageCount,
  onDelete,
  onEdit,
}: {
  id: number
  type: string
  content: string
  createdAt: string
  usageCount?: number
  onDelete: () => void
  onEdit?: () => void
}) {
  return (

              {type}

            {usageCount !== undefined && (
              Used {usageCount} times
            )}

{content}

            Created: {new Date(createdAt).toLocaleString()}

          {onEdit && (
            <button
              onClick={onEdit}
              className="p-2 text-muted-foreground hover:text-accent hover:bg-accent/10 rounded-lg transition-colors"
              title="Edit"
              aria-label="Edit memory item"
            >
              <Pencil size={16} />
            </button>
          )}
          <button
            onClick={onDelete}
            className="p-2 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
            title="Delete"
            aria-label="Delete memory item"
          >
            <Trash2 size={16} />
          </button>

  )
}

function InfrastructureCard({
  id: _id,
  name,
  type,
  config,
  createdAt,
  onDelete,
}: {
  id: number
  name: string
  type: string
  config: Record<string, unknown>
  createdAt: string
  onDelete: () => void
}) {
  return (

{name}

              {type}

            {JSON.stringify(config, null, 2)}

            Created: {new Date(createdAt).toLocaleString()}

        <button
          onClick={onDelete}
          className="p-2 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
          title="Delete"
        >
          <Trash2 size={16} />
        </button>

  )
}

function EmptyState({
  title,
  description,
}: {
  title: string
  description: string
}) {
  return (

      <Brain size={48} className="text-muted-foreground mx-auto mb-4" />

{title}

{description}

  )
}


Good, the file has the imports and state already added. Now I just need to add the export handler and button. Let me make the edit:


const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  const handleExportMemory = async () => {
    setIsExporting(true)
    try {
      const url = currentProject
        ? `${API_BASE}/export?project_id=${currentProject.id}`
        : `${API_BASE}/export`
      const response = await fetch(url)
      if (!response.ok) {
        throw new Error('Failed to export memory')
      }
      const data = await response.json()
      const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
      const downloadUrl = window.URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = downloadUrl
      a.download = `memory_export_${new Date().toISOString().split('T')[0]}.json`
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      window.URL.revokeObjectURL(downloadUrl)
      addToast({
        title: 'Export Complete',
        message: 'Memory items exported successfully.',
        type: 'success',
      })
    } catch (error) {
      console.error('Failed to export memory:', error)
      addToast({
        title: 'Export Failed',
        message: 'Failed to export memory items.',
        type: 'error',
      })
    } finally {
      setIsExporting(false)
    }
  }

  return (

      {/* Header */}

Memory Manager

          <button
            onClick={handleExportMemory}
            disabled={isExporting}
            className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-accent hover:bg-accent/10 rounded-lg transition-colors disabled:opacity-50"
            title="Export Memory Items"
          >
            <Download size={16} />
            {isExporting ? 'Exporting...' : 'Export'}
          </button>
          <button
            onClick={handleOpenAddDialog}
            className="btn-accent flex items-center gap-2"
          >
            <Plus size={18} />
            Add Memory Item
          </button>


Let me try a different approach and write the complete file:


Bash

cd "C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages" && cp MemoryManager.tsx MemoryManager.tsx.bak

Backup MemoryManager.tsx