# 📋 Próxima Sesión - Frontend Dashboard & Primer Agente **Objetivo**: Implementar Frontend Dashboard y desplegar primer agente Claude Code funcional **Tiempo estimado**: 2-3 horas **Sesión anterior**: `past-sessions/2026-01-19-backend-api-implementation.md` --- ## ✅ PRE-REQUISITOS (Verificar antes de empezar) ```bash # 1. Backend funcionando curl -s https://api.fuq.tv/api/health | grep "ok" # Debe retornar: "status":"ok" # 2. Base de datos accesible export KUBECONFIG=~/.kube/aiworker-config kubectl exec -n control-plane mariadb-0 -- mariadb -uaiworker -pAiWorker2026_UserPass! aiworker -e "SELECT COUNT(*) FROM projects;" # Debe mostrar conteo de proyectos # 3. Cluster operativo kubectl get nodes # 6 nodos Ready # 4. Registry accesible curl -s -H "Authorization: token 159a5de2a16d15f33e388b55b1276e431dbca3f3" \ "https://git.fuq.tv/api/v1/packages/admin?type=container" | grep aiworker-backend # Debe mostrar paquete ``` **Si algo falla**: Revisar `TROUBLESHOOTING.md` o última sesión en `past-sessions/` --- ## 🎯 PASO 1: Crear Frontend Base con Bun (45 min) ### 1.1 Crear estructura de frontend ```bash cd /Users/hectorros/projects/teamSquadAiWorker mkdir -p frontend/{src,public} cd frontend # Inicializar proyecto Bun bun init -y ``` ### 1.2 Instalar dependencias ```bash # React + TypeScript bun add react react-dom bun add -d @types/react @types/react-dom # Routing bun add react-router-dom # UI Components (elegir uno) # Opción A: Shadcn/UI + Tailwind bun add -d tailwindcss postcss autoprefixer bunx tailwindcss init -p # Opción B: MUI bun add @mui/material @emotion/react @emotion/styled # API Client bun add axios # Auth bun add lucia ``` ### 1.3 Crear componentes básicos **Estructura necesaria**: ``` frontend/src/ ├── index.html # HTML entry point ├── main.tsx # React root ├── App.tsx # Main app component ├── components/ │ ├── Layout.tsx │ ├── ProjectList.tsx │ ├── TaskList.tsx │ └── AgentStatus.tsx ├── api/ │ └── client.ts # Axios client para backend └── types/ └── index.ts # TypeScript types ``` ### 1.4 Configurar Bun.serve() para frontend **Crear** `frontend/server.ts`: ```typescript import index from './src/index.html' Bun.serve({ port: 3001, routes: { '/': index, '/api/*': { GET: async (req) => { // Proxy to backend const path = new URL(req.url).pathname.replace(/^\/api/, '') return fetch(`https://api.fuq.tv/api${path}`) } } }, development: { hmr: true, console: true } }) ``` ### 1.5 Probar localmente ```bash bun run server.ts # Open http://localhost:3001 ``` **Debe mostrar**: - Dashboard básico - Lista de proyectos (conectado a API) - Sin auth por ahora (agregar en siguiente paso) --- ## 🎯 PASO 2: Implementar Autenticación Básica (30 min) ### 2.1 Configurar Lucia Auth **Referencia**: https://github.com/lucia-auth/lucia **Crear** `frontend/src/lib/auth.ts`: ```typescript import { Lucia } from "lucia" import { BunSQLiteAdapter } from "@lucia-auth/adapter-sqlite" // Por ahora: SQLite local // Después: Migrar a MariaDB del cluster const adapter = new BunSQLiteAdapter(db) export const lucia = new Lucia(adapter, { sessionCookie: { attributes: { secure: process.env.NODE_ENV === "production" } } }) ``` ### 2.2 Crear páginas de auth ``` frontend/src/pages/ ├── Login.tsx ├── Register.tsx └── Dashboard.tsx ``` **Features mínimas**: - Login con email/password - Registro de nuevos usuarios - Logout - Protected routes (redirect si no autenticado) ### 2.3 Integrar con backend **Backend debe tener** (agregar si no existe): ``` POST /api/auth/register POST /api/auth/login POST /api/auth/logout GET /api/auth/me ``` **Nota**: Si estos endpoints no existen, agregarlos al backend en esta sesión. --- ## 🎯 PASO 3: Build y Deploy de Frontend (30 min) ### 3.1 Crear Dockerfile para frontend **Crear** `frontend/Dockerfile`: ```dockerfile FROM oven/bun:1.3.6 WORKDIR /app COPY package.json bun.lockb ./ RUN bun install --frozen-lockfile COPY . . RUN bun build src/main.tsx --outdir ./dist --target browser EXPOSE 3001 CMD ["bun", "run", "server.ts"] ``` ### 3.2 Crear repo en Gitea ```bash cd frontend # Inicializar git git init git add . git commit -m "Initial frontend implementation - React dashboard with project/task views - Lucia auth integration - API client for backend - Bun.serve() with HMR Co-Authored-By: Claude Sonnet 4.5 (1M context) " # Crear repo en Gitea (via API o UI) curl -X POST https://git.fuq.tv/api/v1/user/repos \ -H "Authorization: token 159a5de2a16d15f33e388b55b1276e431dbca3f3" \ -H "Content-Type: application/json" \ -d '{"name":"aiworker-frontend","description":"AiWorker Frontend Dashboard","private":false,"auto_init":false}' # Agregar remote y push git remote add origin https://git.fuq.tv/admin/aiworker-frontend.git git push -u origin main ``` ### 3.3 Crear workflow de CI/CD **Crear** `.gitea/workflows/build.yml`: ```yaml name: Build and Push Frontend on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Build Docker image run: docker build -t git.fuq.tv/admin/aiworker-frontend:${{ gitea.sha }} . - name: Tag as latest run: docker tag git.fuq.tv/admin/aiworker-frontend:${{ gitea.sha }} git.fuq.tv/admin/aiworker-frontend:latest - name: Login to registry run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.fuq.tv -u admin --password-stdin - name: Push images run: | docker push git.fuq.tv/admin/aiworker-frontend:${{ gitea.sha }} docker push git.fuq.tv/admin/aiworker-frontend:latest ``` ### 3.4 Deploy en K8s **Crear** `k8s/frontend/`: ``` k8s/frontend/ ├── deployment.yaml ├── service.yaml └── ingress.yaml ``` **deployment.yaml**: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace: control-plane spec: replicas: 2 selector: matchLabels: app: frontend template: spec: imagePullSecrets: - name: gitea-registry containers: - name: frontend image: git.fuq.tv/admin/aiworker-frontend:latest ports: - containerPort: 3001 env: - name: BACKEND_URL value: http://backend.control-plane.svc.cluster.local:3000 ``` **ingress.yaml**: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: frontend namespace: control-plane annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - app.fuq.tv secretName: frontend-tls rules: - host: app.fuq.tv http: paths: - path: / pathType: Prefix backend: service: name: frontend port: number: 3001 ``` **Deploy**: ```bash kubectl apply -f k8s/frontend/ kubectl get pods -n control-plane -l app=frontend kubectl get ingress -n control-plane frontend ``` **Verificar**: ```bash curl -I https://app.fuq.tv # HTTP/2 200 ``` --- ## 🎯 PASO 4: Primer Agente Claude Code (45 min) ### 4.1 Entender arquitectura de agentes **Referencia**: `docs/05-agents/`, `AGENT-GUIDE.md` **Agente Claude Code es**: - Un pod en K8s namespace `agents` - Corre `claude-code` CLI conectado vía MCP - Tiene acceso al código vía Git clone - Reporta progreso al backend vía MCP tools ### 4.2 Crear Dockerfile del agente **Crear** `agents/Dockerfile`: ```dockerfile FROM node:20-alpine # Instalar claude-code CLI RUN npm install -g @anthropic/claude-code # Instalar herramientas de desarrollo RUN apk add --no-cache git bash curl # Configurar MCP COPY mcp-config.json /root/.config/claude-code/config.json WORKDIR /workspace CMD ["claude-code", "--mcp-server", "$BACKEND_MCP_URL"] ``` ### 4.3 Crear configuración MCP **Crear** `agents/mcp-config.json`: ```json { "mcpServers": { "aiworker": { "url": "http://backend.control-plane.svc.cluster.local:3100", "tools": [ "get_next_task", "update_task_status", "create_branch", "create_pull_request" ] } } } ``` ### 4.4 Crear deployment del agente **Crear** `k8s/agents/agent-deployment.yaml`: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: claude-agent namespace: agents spec: replicas: 1 # Empezar con 1 agente selector: matchLabels: app: claude-agent template: metadata: labels: app: claude-agent spec: containers: - name: agent image: git.fuq.tv/admin/aiworker-agent:latest env: - name: ANTHROPIC_API_KEY valueFrom: secretKeyRef: name: agent-secrets key: anthropic-api-key - name: BACKEND_MCP_URL value: http://backend.control-plane.svc.cluster.local:3100 - name: GITEA_URL value: https://git.fuq.tv - name: GITEA_TOKEN valueFrom: secretKeyRef: name: agent-secrets key: gitea-token - name: AGENT_ID valueFrom: fieldRef: fieldPath: metadata.name ``` ### 4.5 Crear secret para agente ```bash kubectl create secret generic agent-secrets -n agents \ --from-literal=anthropic-api-key='' \ --from-literal=gitea-token='159a5de2a16d15f33e388b55b1276e431dbca3f3' ``` ### 4.6 Desplegar agente ```bash # Crear namespace kubectl create namespace agents # Agregar registry secret kubectl create secret docker-registry gitea-registry -n agents \ --docker-server=git.fuq.tv \ --docker-username=admin \ --docker-password=7401126cfb56ab2aebba17755bdc968c20768c27 # Deploy kubectl apply -f k8s/agents/ kubectl get pods -n agents kubectl logs -f -n agents deployment/claude-agent ``` ### 4.7 Verificar agente registrado ```bash # El agente debe auto-registrarse al iniciar curl -s https://api.fuq.tv/api/agents | jq # Debe mostrar agente con status "idle" ``` --- ## 🎯 PASO 5: Test End-to-End del Flujo Completo (30 min) ### 5.1 Crear tarea de prueba ```bash # 1. Crear proyecto PROJECT_ID=$(curl -s -X POST https://api.fuq.tv/api/projects \ -H "Content-Type: application/json" \ -d '{ "name": "test-agent-flow", "description": "Test de flujo completo con agente", "giteaOwner": "admin", "giteaRepoName": "test-agent-flow" }' | jq -r '.data.id') echo "Project ID: $PROJECT_ID" # 2. Crear tarea TASK_ID=$(curl -s -X POST https://api.fuq.tv/api/tasks \ -H "Content-Type: application/json" \ -d "{ \"projectId\": \"$PROJECT_ID\", \"title\": \"Add hello world endpoint\", \"description\": \"Create a simple GET /hello endpoint that returns 'Hello World'\", \"priority\": \"high\" }" | jq -r '.data.id') echo "Task ID: $TASK_ID" ``` ### 5.2 Monitorear logs del agente ```bash # Terminal 1: Logs del agente kubectl logs -f -n agents deployment/claude-agent # Terminal 2: Ver estado de la tarea watch -n 2 "curl -s https://api.fuq.tv/api/tasks/$TASK_ID | jq '.data.state'" ``` ### 5.3 Verificar flujo completo **Debe ocurrir**: 1. Agente obtiene tarea con `get_next_task` 2. Estado cambia: `backlog` → `in_progress` 3. Agente crea branch con `create_branch` 4. Agente implementa código 5. Agente crea PR con `create_pull_request` 6. Estado cambia: `in_progress` → `ready_to_test` 7. PR visible en Gitea **Verificar PR**: ```bash # Ver PRs en Gitea curl -s -H "Authorization: token 159a5de2a16d15f33e388b55b1276e431dbca3f3" \ "https://git.fuq.tv/api/v1/repos/admin/test-agent-flow/pulls" | jq ``` ### 5.4 Revisar dashboard ```bash # Abrir dashboard open https://app.fuq.tv # Debe mostrar: # - Proyecto "test-agent-flow" # - Tarea "Add hello world endpoint" con estado "ready_to_test" # - PR link visible # - Agente con status "idle" (completó tarea) ``` --- ## 🎯 PASO 6: Webhooks de Gitea (OPCIONAL, 15 min) Si hay tiempo, configurar webhooks para notificaciones. ### 6.1 Crear endpoint de webhook en backend **Agregar** a `backend/src/api/routes/webhooks.ts`: ```typescript export async function handleGiteaWebhook(req: Request) { const event = req.headers.get('X-Gitea-Event') const payload = await req.json() switch (event) { case 'pull_request': // Notificar frontend vía WebSocket break case 'push': // Trigger preview deploy break } } ``` ### 6.2 Configurar webhook en Gitea ```bash # Via API curl -X POST https://git.fuq.tv/api/v1/repos/admin/test-agent-flow/hooks \ -H "Authorization: token 159a5de2a16d15f33e388b55b1276e431dbca3f3" \ -H "Content-Type: application/json" \ -d '{ "type": "gitea", "config": { "url": "https://api.fuq.tv/api/webhooks/gitea", "content_type": "json" }, "events": ["push", "pull_request"], "active": true }' ``` --- ## 📝 NOTAS IMPORTANTES ### Frontend con Bun - **Bun.serve()** tiene soporte nativo para React/JSX - HTML imports automáticos: `import index from './index.html'` - HMR funciona out-of-the-box con `development: { hmr: true }` - No necesitas Vite/Webpack ### Agentes Claude Code - **MCP es clave**: Los agentes se comunican exclusivamente vía MCP - **Sin API REST**: Agentes NO llaman directamente a `/api/`, usan herramientas MCP - **Auto-registro**: Agente debe llamar `POST /api/agents` al iniciar - **Heartbeat**: Cada 30s llamar `POST /api/agents/:id/heartbeat` ### Auth y Sesiones - Lucia Auth usa cookies HTTPOnly para sesiones - En desarrollo: cookies inseguras (HTTP) - En producción: cookies secure (HTTPS) - Considerar migrar SQLite → MariaDB para auth --- ## 🐛 TROUBLESHOOTING ### Si frontend no conecta con backend ```bash # Verificar que backend esté accesible desde frontend pod kubectl exec -n control-plane deployment/frontend -- \ curl http://backend.control-plane.svc.cluster.local:3000/api/health ``` ### Si agente no registra ```bash # Ver logs del agente kubectl logs -n agents deployment/claude-agent --tail=50 # Verificar connectivity a backend kubectl exec -n agents deployment/claude-agent -- \ curl http://backend.control-plane.svc.cluster.local:3000/api/health ``` ### Si CI/CD falla ```bash # Ver runner logs kubectl logs -n gitea-actions deployment/gitea-runner -c runner --tail=100 # Restart runner si está stuck kubectl rollout restart deployment/gitea-runner -n gitea-actions ``` --- ## ✅ CHECKLIST DE SESIÓN Al final de la sesión, verificar: - [ ] Frontend deployado en https://app.fuq.tv - [ ] Login/Register funcionando - [ ] Dashboard muestra proyectos y tareas - [ ] Agente corriendo en namespace `agents` - [ ] Agente registrado en DB (visible en API) - [ ] Flujo completo probado: Tarea → Agente → PR - [ ] Código commitado en 2 repos (frontend, agents) - [ ] Builds exitosos en Gitea Actions - [ ] Imágenes en registry - [ ] Documentación de sesión creada en `past-sessions/` --- ## 🎉 META **Completado hasta ahora**: Infraestructura HA + Backend API + MCP Server **Esta sesión**: Frontend Dashboard + Primer Agente Funcional **Próximo hito**: Preview Environments + Agents Pool + Monitoring **¡Casi llegamos al MVP funcional! 🚀**