diff --git a/.docs/0-requirements/033-create-setting-page.md b/.docs/0-requirements/033-create-setting-page.md new file mode 100644 index 0000000..df9d0b5 --- /dev/null +++ b/.docs/0-requirements/033-create-setting-page.md @@ -0,0 +1,2 @@ +As an admin user, I need to setup the setting page for the agents that I have created. I need to build the frontend for this. Backend will come later since I need to have a feel of UI/UX. Also, I think in the left menu at the bottom, it would be a menu item with named "Settings", and when I click that button, the setting page will appear. + diff --git a/.docs/1-implementation-plans/033-create-setting-page-plan.md b/.docs/1-implementation-plans/033-create-setting-page-plan.md new file mode 100644 index 0000000..7364223 --- /dev/null +++ b/.docs/1-implementation-plans/033-create-setting-page-plan.md @@ -0,0 +1,338 @@ +# Implementation Plan: Settings Page + +**Status**: Ready for Implementation +**Requirement**: [033-create-setting-page.md](../.docs/0-requirements/033-create-setting-page.md) +**Type**: Frontend-First Feature + +--- + +## Overview + +Create a Settings page for admin users to configure agents. This is a **frontend-first feature** - build the UI/UX first to validate the design, then implement backend functionality in a future iteration. + +**Key Requirements:** +- Add "Settings" menu item at the bottom of the left navigation menu +- Create Settings page UI with agent configuration options +- Focus on UI/UX polish before backend integration +- Design for future backend integration + +--- + +## 1. Frontend Tasks (NextJS + Shadcn UI) + +**Owner**: Frontend Agent - See [frontend.agent.md](../.github/agents/frontend.agent.md) + +### Task 1.1: Add Settings Navigation Item +**File**: `frontend/components/sidebar.tsx` (or equivalent navigation component) + +- Add "Settings" menu item at the bottom of the left sidebar/menu +- Use Shadcn UI icon for settings (e.g., `Settings` icon from lucide-react) +- Add click handler to navigate to `/settings` route +- Ensure visual distinction from other menu items (e.g., separator line above it) + +**Acceptance Criteria:** +- Settings menu item appears at bottom of left navigation +- Clicking navigates to settings page +- Icon and label are visually clear + +### Task 1.2: Create Settings Page Route +**Files**: +- `frontend/app/settings/page.tsx` (main settings page) +- `frontend/app/settings/layout.tsx` (optional layout wrapper) + +- Create new route at `/settings` +- Implement page layout with proper title and breadcrumb +- Add responsive design for mobile/tablet/desktop + +**Acceptance Criteria:** +- Route accessible via `/settings` +- Page renders with proper layout +- Responsive design works across devices + +### Task 1.3: Design Settings Page UI Components +**Files**: +- `frontend/components/settings/agent-settings-list.tsx` +- `frontend/components/settings/agent-settings-card.tsx` +- `frontend/components/settings/agent-settings-form.tsx` + +**Components to Create:** + +#### `AgentSettingsList` +- Display list of agents with configuration options +- Use Shadcn UI Card components for each agent +- Show agent name, description, and status +- Add expand/collapse functionality for each agent + +#### `AgentSettingsCard` +- Card component for individual agent settings +- Display agent metadata (name, type, status) +- Show configuration options based on agent type +- Use Shadcn UI Form components + +#### `AgentSettingsForm` +- Form component for editing agent configuration +- Fields might include: + - Agent name + - Description + - Enabled/disabled toggle + - Model selection (LLM provider) + - Temperature/parameters + - Tools enabled/disabled + - Custom prompts or instructions +- Use Shadcn UI Form, Input, Textarea, Switch, Select components +- Add validation (frontend-only for now) +- Save button (mock functionality for now) + +**Acceptance Criteria:** +- Agent list displays all available agents +- Each agent card shows relevant configuration options +- Form is user-friendly and follows Shadcn UI patterns +- Mock data used for initial development + +### Task 1.4: Create Mock Data Service +**File**: `frontend/services/settings-mock.ts` + +- Create mock data for agent configurations +- Include various agent types (chat, canvas, insurance, etc.) +- Define TypeScript interfaces for settings data structure +- Simulate API responses for testing UI + +**Mock Data Structure:** +```typescript +interface AgentSettings { + id: string; + name: string; + type: string; + description: string; + enabled: boolean; + configuration: { + model?: string; + temperature?: number; + maxTokens?: number; + tools?: string[]; + customInstructions?: string; + }; +} +``` + +**Acceptance Criteria:** +- Mock service returns realistic agent settings data +- Data structure aligns with future backend API design +- Easy to swap with real API later + +### Task 1.5: Add State Management +**Files**: +- `frontend/stores/settings-store.ts` (if using Zustand/similar) +- Or use React hooks in components + +- Manage settings page state (selected agent, form values, etc.) +- Handle form changes and validation +- Prepare for future API integration + +**Acceptance Criteria:** +- Settings state properly managed +- Form changes reflected in UI +- State structure supports future backend integration + +### Task 1.6: Implement UI/UX Polish +**Files**: Various component files + +- Add loading states (skeleton components) +- Add empty states (no agents configured) +- Add success/error toast notifications (mock for now) +- Ensure proper spacing, typography, and colors (Shadcn UI theme) +- Add hover states and transitions +- Test keyboard navigation and accessibility + +**Acceptance Criteria:** +- UI feels polished and professional +- Loading states provide good UX +- Accessible via keyboard +- Follows Shadcn UI design patterns + +--- + +## 2. Backend Tasks (Future Iteration) + +**Owner**: Backend Agent - See [backend.agent.md](../.github/agents/backend.agent.md) + +**Note**: Backend implementation is deferred to a future iteration after UI/UX is validated. + +### Future Task 2.1: Create Settings Database Schema +- Define agent_settings table structure +- Add migration for settings storage +- Link settings to agents and users + +### Future Task 2.2: Create Settings API Endpoints +- `GET /api/settings/agents` - List agent settings +- `GET /api/settings/agents/{agent_id}` - Get specific agent settings +- `PUT /api/settings/agents/{agent_id}` - Update agent settings +- Add authentication/authorization (admin only) + +### Future Task 2.3: Implement Settings Service +- Create `settings_service.py` +- Implement CRUD operations for agent settings +- Add validation logic +- Integrate with agent registry + +### Future Task 2.4: Update Agent Initialization +- Modify agents to load settings from database +- Apply settings to agent configuration +- Handle settings updates dynamically + +--- + +## 3. Integration Points (Future) + +**When backend is ready:** + +### Frontend Integration Changes +**File**: `frontend/services/settings-api.ts` + +- Replace mock service with real API client +- Update TypeScript interfaces to match backend models +- Add error handling for API calls +- Implement optimistic updates + +### Testing Integration +- Test full flow: UI → API → Database → Agent +- Verify settings are applied to agents correctly +- Test edge cases (invalid settings, concurrent updates) + +--- + +## 4. TypeScript Types + +**File**: `frontend/types/settings.ts` + +```typescript +export interface AgentSettings { + id: string; + name: string; + type: AgentType; + description: string; + enabled: boolean; + configuration: AgentConfiguration; + createdAt: string; + updatedAt: string; +} + +export interface AgentConfiguration { + model?: string; + provider?: 'ollama' | 'openai' | 'azure' | 'gemini'; + temperature?: number; + maxTokens?: number; + tools?: string[]; + customInstructions?: string; + // Add more fields as needed +} + +export type AgentType = 'chat' | 'canvas' | 'insurance' | 'salary_viewer' | 'a2ui'; +``` + +--- + +## 5. Dependencies + +### Task Order (Frontend): +1. Add Settings navigation item (Task 1.1) +2. Create Settings page route (Task 1.2) +3. Create mock data service (Task 1.4) +4. Design and implement UI components (Task 1.3) +5. Add state management (Task 1.5) +6. Polish UI/UX (Task 1.6) + +### External Dependencies: +- Shadcn UI components (already installed) +- React Hook Form (if not already installed) +- Lucide React icons (for settings icon) + +--- + +## 6. Testing Strategy + +### Frontend Testing (Current Phase): +- Manual testing of UI interactions +- Verify responsive design on different screen sizes +- Test keyboard navigation +- Validate form validation logic +- Verify mock data displays correctly + +### Integration Testing (Future Phase): +- API endpoint tests +- End-to-end tests for settings flow +- Agent configuration application tests + +--- + +## 7. Success Criteria + +**Current Phase (Frontend-only):** +- ✅ Settings menu item appears in left navigation +- ✅ Settings page accessible and renders properly +- ✅ Agent settings list displays mock data +- ✅ Settings form allows editing (mock save) +- ✅ UI is polished and follows Shadcn UI patterns +- ✅ Responsive design works on all devices +- ✅ Code is well-structured for future backend integration + +**Future Phase (With Backend):** +- Settings persist to database +- Settings apply to agent behavior +- Only admin users can access settings +- Real-time validation and error handling + +--- + +## 8. Notes + +- **Frontend-First Approach**: Build and refine UI/UX before implementing backend +- **Mock Data**: Use realistic mock data to test UI flows +- **Future-Proof**: Structure code to easily integrate with backend API later +- **Admin Only**: Plan for admin-only access (implement in backend phase) +- **Agent Types**: Consider different settings for different agent types +- **Extensibility**: Design settings structure to support new configuration options + +--- + +## 9. Related Files + +### Frontend Files to Create/Modify: +- Navigation component (add Settings item) +- `frontend/app/settings/page.tsx` +- `frontend/components/settings/agent-settings-list.tsx` +- `frontend/components/settings/agent-settings-card.tsx` +- `frontend/components/settings/agent-settings-form.tsx` +- `frontend/services/settings-mock.ts` +- `frontend/types/settings.ts` +- `frontend/stores/settings-store.ts` (optional) + +### Backend Files (Future): +- `backend/api/routers/settings.py` +- `backend/services/settings_service.py` +- `backend/database/models.py` (add settings model) +- `backend/database/migrations/` (new migration) + +--- + +## 10. Handoff Instructions + +### For Frontend Agent: +1. Start with Task 1.1 (navigation item) +2. Use Shadcn UI components throughout +3. Follow existing patterns in the codebase +4. Create comprehensive mock data +5. Focus on UI/UX polish +6. Structure code for easy backend integration + +### For Backend Agent (Future): +1. Review frontend implementation first +2. Design API contract based on frontend needs +3. Implement database schema +4. Create API endpoints +5. Integrate with agent registry +6. Update agent initialization logic + +--- + +**Ready for Implementation**: Frontend Agent can start with Task 1.1 diff --git a/.github/agents/a-custom-agent.agent.md b/.github/agents/a-custom-agent.agent.md new file mode 100644 index 0000000..82ea150 --- /dev/null +++ b/.github/agents/a-custom-agent.agent.md @@ -0,0 +1,5 @@ +--- +description: 'Describe what this custom agent does and when to use it.' +tools: [] +--- +Define what this custom agent accomplishes for the user, when to use it, and the edges it won't cross. Specify its ideal inputs/outputs, the tools it may call, and how it reports progress or asks for help. \ No newline at end of file diff --git a/frontend/app/settings/page.tsx b/frontend/app/settings/page.tsx new file mode 100644 index 0000000..9fd0c2b --- /dev/null +++ b/frontend/app/settings/page.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { Settings as SettingsIcon } from 'lucide-react'; +import { AgentSettingsList } from '@/components/settings/agent-settings-list'; + +/** + * Settings Page + * + * Admin page for configuring agent settings + */ +export default function SettingsPage() { + return ( +
+ {/* Header */} +
+
+
+
+ +
+
+

Settings

+

+ Configure agent settings and behavior +

+
+
+
+
+ + {/* Main Content */} +
+
+
+ {/* Section Header */} +
+

Agent Configuration

+

+ Manage agent settings including models, parameters, and behavior customization +

+
+ + {/* Agent Settings List */} + +
+
+
+
+ ); +} diff --git a/frontend/components/Sidebar.tsx b/frontend/components/Sidebar.tsx index cc6cd03..a7c9c46 100644 --- a/frontend/components/Sidebar.tsx +++ b/frontend/components/Sidebar.tsx @@ -1,7 +1,8 @@ 'use client'; -import { Plus, MessageSquare, PanelLeftClose, PanelLeftOpen, Search, Sparkles, X } from 'lucide-react'; +import { Plus, MessageSquare, PanelLeftClose, PanelLeftOpen, Search, Sparkles, X, Settings } from 'lucide-react'; import Image from 'next/image'; +import Link from 'next/link'; import { Button } from '@/components/ui/button'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Separator } from '@/components/ui/separator'; @@ -11,6 +12,7 @@ import { ChatHistory } from './ChatHistory'; import { useIsMobile } from '@/hooks/useMediaQuery'; import { useHorizontalSwipe } from '@/hooks/useSwipeGesture'; import { useEffect } from 'react'; +import { usePathname } from 'next/navigation'; interface SidebarProps { threads: Thread[]; @@ -43,6 +45,7 @@ export function Sidebar({ onCloseMobile, }: SidebarProps) { const isMobile = useIsMobile(); + const pathname = usePathname(); // Swipe gesture for mobile drawer const swipeHandlers = useHorizontalSwipe( @@ -182,6 +185,22 @@ export function Sidebar({ )} + + {/* Settings Link - Mobile */} +
+ + + +
); @@ -327,6 +346,43 @@ export function Sidebar({ )} )} + + {/* Settings Link - Desktop */} + {!isCollapsed && ( +
+ + + +
+ )} + + {/* Settings Link - Collapsed Desktop */} + {isCollapsed && ( +
+ + + +
+ )} ); } diff --git a/frontend/components/settings/agent-settings-card.tsx b/frontend/components/settings/agent-settings-card.tsx new file mode 100644 index 0000000..3959cf6 --- /dev/null +++ b/frontend/components/settings/agent-settings-card.tsx @@ -0,0 +1,119 @@ +'use client'; + +import { useState } from 'react'; +import { AgentSettings } from '@/types/settings'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Switch } from '@/components/ui/switch'; +import { ChevronDown, ChevronUp, Bot } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { AgentSettingsForm } from './agent-settings-form'; +import { useSettingsStore } from '@/stores/settingsStore'; + +interface AgentSettingsCardProps { + agent: AgentSettings; +} + +/** + * AgentSettingsCard Component + * + * Displays an individual agent's settings with expand/collapse functionality + */ +export function AgentSettingsCard({ agent }: AgentSettingsCardProps) { + const [isExpanded, setIsExpanded] = useState(false); + const updateAgent = useSettingsStore((state) => state.updateAgent); + + const handleToggleEnabled = async (enabled: boolean) => { + await updateAgent(agent.id, { enabled }); + }; + + const getAgentTypeColor = (type: string): string => { + const colors: Record = { + chat: 'bg-blue-100 text-blue-800', + canvas: 'bg-purple-100 text-purple-800', + insurance: 'bg-green-100 text-green-800', + salary_viewer: 'bg-yellow-100 text-yellow-800', + a2ui: 'bg-pink-100 text-pink-800', + custom: 'bg-gray-100 text-gray-800', + }; + return colors[type] || colors.custom; + }; + + return ( + + +
+
+
+ +
+
+
+ {agent.name} + + {agent.type} + + {agent.enabled ? ( + + Enabled + + ) : ( + + Disabled + + )} +
+ + {agent.description} + +
+ Model: {agent.configuration.model || 'Not set'} + + Provider: {agent.configuration.provider || 'Not set'} +
+
+
+
+
+ +
+ +
+
+
+ + {isExpanded && ( + +
+ setIsExpanded(false)} /> +
+
+ )} +
+ ); +} diff --git a/frontend/components/settings/agent-settings-form.tsx b/frontend/components/settings/agent-settings-form.tsx new file mode 100644 index 0000000..e4e092d --- /dev/null +++ b/frontend/components/settings/agent-settings-form.tsx @@ -0,0 +1,249 @@ +'use client'; + +import { useState } from 'react'; +import { AgentSettings, AgentSettingsFormData } from '@/types/settings'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { AVAILABLE_MODELS } from '@/services/settings-mock'; +import { useSettingsStore } from '@/stores/settingsStore'; +import { Save, X } from 'lucide-react'; + +interface AgentSettingsFormProps { + agent: AgentSettings; + onClose?: () => void; +} + +/** + * AgentSettingsForm Component + * + * Form for editing agent configuration settings + */ +export function AgentSettingsForm({ agent, onClose }: AgentSettingsFormProps) { + const updateAgent = useSettingsStore((state) => state.updateAgent); + const [isSubmitting, setIsSubmitting] = useState(false); + + const [formData, setFormData] = useState({ + name: agent.name, + description: agent.description, + enabled: agent.enabled, + model: agent.configuration.model, + provider: agent.configuration.provider, + temperature: agent.configuration.temperature, + maxTokens: agent.configuration.maxTokens, + customInstructions: agent.configuration.customInstructions, + systemPrompt: agent.configuration.systemPrompt, + }); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSubmitting(true); + + try { + await updateAgent(agent.id, { + name: formData.name, + description: formData.description, + enabled: formData.enabled, + configuration: { + ...agent.configuration, + model: formData.model, + provider: formData.provider, + temperature: formData.temperature, + maxTokens: formData.maxTokens, + customInstructions: formData.customInstructions, + systemPrompt: formData.systemPrompt, + }, + }); + + if (onClose) { + onClose(); + } + } catch (error) { + console.error('Failed to update agent:', error); + } finally { + setIsSubmitting(false); + } + }; + + const handleReset = () => { + setFormData({ + name: agent.name, + description: agent.description, + enabled: agent.enabled, + model: agent.configuration.model, + provider: agent.configuration.provider, + temperature: agent.configuration.temperature, + maxTokens: agent.configuration.maxTokens, + customInstructions: agent.configuration.customInstructions, + systemPrompt: agent.configuration.systemPrompt, + }); + }; + + const availableModels = formData.provider + ? AVAILABLE_MODELS[formData.provider] || [] + : []; + + return ( +
+
+ {/* Agent Name */} +
+ + setFormData({ ...formData, name: e.target.value })} + placeholder="Enter agent name" + required + /> +
+ + {/* Provider */} +
+ + +
+ + {/* Model */} +
+ + +
+ + {/* Temperature */} +
+ + setFormData({ + ...formData, + temperature: parseFloat(e.target.value) + })} + /> +
+ + {/* Max Tokens */} +
+ + setFormData({ + ...formData, + maxTokens: parseInt(e.target.value) + })} + /> +
+
+ + {/* Description */} +
+ +