# Captain Claude Mobile v2 - Estado del Proyecto **Fecha:** 2026-01-17 **Estado:** BACKEND ACTUALIZADO / PENDIENTE COMPILAR APK --- ## Cambios Realizados (17 Ene 2026) ### Backend reescrito con patrón LLMChat Se aplicó el patrón de streaming de [LLMChat](https://github.com/c0sogi/LLMChat): 1. **Queue para desacoplar receiver/sender** - `asyncio.Queue` para mensajes entrantes - `ws_receiver()` y `ws_sender()` corren en paralelo con `asyncio.gather()` 2. **ChatBuffer** - Contexto por conexión - Mantiene estado: `websocket`, `username`, `queue`, `done`, `conversation_id` - `done` event para interrumpir streaming 3. **Mensaje `init` al conectar** - Envía lista de conversaciones al conectar - Frontend recibe estado inicial sin llamada REST adicional 4. **Soporte para interrumpir streaming** - Cliente envía `{"type": "stop"}` - Backend termina proceso Claude y envía `{"type": "interrupted"}` 5. **Nuevos tipos de mensaje** - `init` - Estado inicial con conversaciones - `text_start` - Inicio de bloque de texto - `tool_input` - Input completo del tool - `interrupted` - Generación interrumpida - `conversation_loaded` - Conversación cargada via WS --- ## Configuración Actual | Componente | Puerto | Notas | |------------|--------|-------| | **captain-api-v2** | **3030** | Backend con patrón LLMChat | **Credenciales:** `admin` / `admin` **Servicio:** `captain-api-v2.service` (systemd) --- ## Archivos Modificados ``` apps/captain-mobile-v2/ ├── backend/ │ ├── captain_api_v2.py # Backend reescrito │ └── captain-api-v2.service # Puerto 3031 ├── flutter/lib/ │ ├── config/api_config.dart # Puerto 3031 │ ├── services/chat_service.dart # Nuevos eventos │ └── providers/chat_provider.dart # Manejo de init, interrupted, etc. └── ESTADO_PROYECTO.md # Este archivo ``` --- ## Próximos Pasos ### 1. Instalar servicio systemd (requiere sudo) ```bash sudo cp captain-api-v2.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable captain-api-v2 sudo systemctl start captain-api-v2 ``` ### 2. Compilar APK ```bash cd /home/architect/captain-claude/apps/captain-mobile-v2/flutter /home/architect/flutter/bin/flutter build apk --release ``` ### 3. Subir a Nextcloud ```bash scp -i ~/.ssh/tzzr build/app/outputs/flutter-apk/app-release.apk \ root@72.62.1.113:"/var/www/nextcloud/data/tzzrdeck/files/documentos adjuntos/captain-mobile-v2.apk" ssh -i ~/.ssh/tzzr root@72.62.1.113 \ "chown www-data:www-data '/var/www/nextcloud/data/tzzrdeck/files/documentos adjuntos/captain-mobile-v2.apk' && \ cd /var/www/nextcloud && sudo -u www-data php occ files:scan tzzrdeck" ``` --- ## Probar Backend Manualmente ```bash # Health check curl http://localhost:3031/health # Login TOKEN=$(curl -s -X POST http://localhost:3031/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin"}' | jq -r '.token') # Listar conversaciones curl -H "Authorization: Bearer $TOKEN" http://localhost:3031/conversations ``` --- ## Arquitectura WebSocket (LLMChat pattern) ``` ┌─────────────────┐ WebSocket ┌─────────────────┐ │ Flutter Client │ ◄───────────────► │ FastAPI Server │ │ │ /ws/chat │ │ └─────────────────┘ └────────┬────────┘ │ ┌──────────────────────────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ws_receiver() ws_sender() ChatBuffer - Recibe JSON - Procesa queue - websocket - stop → buffer.done.set() - Llama Claude - username - ping → pong - Stream chunks - queue - Otros → queue.put() - Guarda en DB - done event ``` --- ## Flujo de Mensajes ### Conexión ``` Cliente Servidor │ │ │──── {"token": "xxx"} ─────────►│ │ │ │◄─── {"type": "init", │ │ "user": "admin", │ │ "conversations": [...]} │ ``` ### Chat ``` Cliente Servidor │ │ │──── {"type": "message", │ │ "content": "Hola"} ──────►│ │ │ │◄─── {"type": "start"} ─────────│ │◄─── {"type": "thinking"} ──────│ │◄─── {"type": "delta", ...} ────│ (múltiples) │◄─── {"type": "done", ...} ─────│ ``` ### Interrumpir ``` Cliente Servidor │ │ │──── {"type": "stop"} ─────────►│ │ │ │◄─── {"type": "interrupted", │ │ "content": "..."} ────────│ ```