Objetivo: Resolver el problema de sesiones trabadas en móvil
Prioridad: Alta (afecta tu uso principal)
Fecha: Mayo 14, 2026
Eliminar la necesidad de hacer STOP + "?" para continuar respuestas.
La IA debe:
- ✅ Continuar respondiendo sin trabarse
- ✅ Mostrar errores solo cuando realmente hay problema
- ✅ Auto-recuperarse si se traba
- ✅ No perder contexto
Próxima vez que uses CodeNomad desde el móvil:
-
Antes de empezar:
- Abre CodeNomad en móvil - Haz pregunta que se vaya a trabar - Ten lista la cámara para screenshot -
Cuando se trabe:
- NO presiones STOP todavía - Toma screenshot de la pantalla - Anota la hora exacta -
Presiona STOP:
- Toma screenshot del ERROR que aparece - Lee el mensaje completo - Si puedes, copia el texto -
Intenta reenviar pregunta:
- Toma screenshot del ERROR - Compara si es el mismo error -
Envía "?" para recuperar:
- Confirma que continúa - Toma screenshot de la respuesta continuando -
Mándame:
- Screenshots
- Hora exacta del incidente
- Texto de los errores (si pudiste copiar)
Con la hora exacta que me des:
# Revisar logs en ese momento
grep "2026-05-14 HH:MM" ~/.config/codenomad/logs/opencode-*.log
# Buscar errores
grep -i "error\|fail\|timeout" ~/.config/codenomad/logs/opencode-*.log | tail -50
# Ver logs del servidor CodeNomad
journalctl --user -S "2026-05-14 HH:MM" | grep -i "codenomad\|error"Basado en los errores, buscaré:
-
Dónde se genera el error
cd /home/dark/Project/codenomad grep -r "TEXTO_DEL_ERROR" packages/
-
Cómo se maneja la cancelación
grep -r "abort\|cancel.*request" packages/server/src/ grep -r "abort\|cancel.*request" packages/ui/src/
-
Estado de la sesión
grep -r "session.*status\|status.*working" packages/ui/src/stores/
Basado en lo encontrado, implementaré una de estas soluciones:
Si el problema es: Stream se traba pero sesión está viva
// packages/ui/src/stores/session-state.ts o similar
// Detector de stream trabado
let lastMessageTime = Date.now()
createEffect(() => {
// Cada vez que llega un mensaje
if (session.status === 'working') {
lastMessageTime = Date.now()
}
})
// Watchdog que revisa cada 10 segundos
setInterval(() => {
if (session.status === 'working') {
const stuckTime = Date.now() - lastMessageTime
if (stuckTime > 30000) {
// Trabado por 30 segundos, auto-recuperar
console.warn('[AUTO-RECOVERY] Session stuck, recovering...')
// Enviar señal de recuperación (equivalente a enviar "?")
recoverStuckSession()
}
}
}, 10000)
function recoverStuckSession() {
// Limpia estado de error
clearSessionErrors()
// Envía señal mínima para desbloquear
// (internamente, no visible para usuario)
sendRecoveryPing()
}Si el problema es: Abort/Cancel tira error
// packages/server/src/workspaces/instance.ts o similar
async function cancelRequest(requestId: string) {
try {
await opencode.cancel(requestId)
logger.debug('Request cancelled successfully', { requestId })
} catch (error) {
// Cancelación puede fallar si request ya terminó
// Esto es NORMAL, no es error crítico
logger.debug('Cancel failed (request may have completed)', {
requestId,
error: error.message
})
// NO lanzar error a UI
// return silently
}
}Si el problema es: Errores se muestran cuando no deberían
// packages/ui/src/stores/session-state.ts
function setSessionError(error: Error) {
// Filtrar errores que no son realmente problemas
const ignorableErrors = [
'AbortError',
'Request cancelled',
'Stream closed'
]
if (ignorableErrors.some(msg => error.message.includes(msg))) {
// No mostrar estos errores al usuario
logger.debug('Ignorable error:', error.message)
return
}
// Solo mostrar errores reales
sessionErrors.set(error)
}Mientras investigamos causa raíz:
// packages/ui/src/components/SessionView.tsx
{session.status === 'working' && isStuck && (
<div class="stuck-banner">
<p>La respuesta parece detenida</p>
<button onClick={handleRecover} class="recover-btn">
Continuar
</button>
</div>
)}
function handleRecover() {
// Limpia errores
clearErrors()
// Envía señal de recuperación
// (equivalente a lo que hace "?")
recoverSession()
}-
Build del fix:
cd /home/dark/Project/codenomad npm run build # O si es solo UI npm run build:ui
-
Restart CodeNomad:
# Detener el actual pkill -f codenomad-dev # Iniciar con el fix npx @neuralnomads/codenomad-dev --host 0.0.0.0 --https-port 9898 --password 3467 --launch
-
Testear desde móvil:
- Hacer pregunta que antes se trababa
- Ver si sigue trabándose
- Si se traba, ver si auto-recupera
- Verificar que no hay errores molestos
-
Documentar resultados:
- ¿Se sigue trabando?
- ¿Auto-recuperó?
- ¿Hay errores?
- ¿Mejor que antes?
-
Screenshot del error al presionar STOP
- Texto completo del mensaje
- Color del error (rojo/amarillo)
- Ubicación en pantalla
-
Screenshot del error al reenviar
- ¿Es el mismo mensaje?
- ¿Diferente?
-
Hora exacta cuando se traba
- Formato: "14:23:45" (para buscar en logs)
-
Browser que usas en móvil
- Chrome? Firefox? Safari? Brave?
- Versión si la sabes
-
Cuánto tarda en trabarse
- ¿10 segundos? ¿30? ¿1 minuto?
- ¿Siempre el mismo tiempo?
-
Tipo de pregunta que se traba
- ¿Preguntas largas/complejas?
- ¿Cualquier pregunta?
- ¿Patrón específico?
- Console del browser (si puedes acceder)
- En móvil es difícil, pero si puedes:
- Menú → More Tools → Developer Tools
- Pestaña Console
- Screenshot de errores en rojo
1. Cuando aparezca error
2. Presiona botones de screenshot de tu móvil
- Android: Power + Volume Down
- iOS: Power + Volume Up (o Home)
3. Guarda las imágenes
4. Mándamelas por donde sea más fácil
1. Mantén presionado el mensaje de error
2. Selecciona "Copiar" si aparece
3. Pega en notas/mensaje
4. Mándame el texto
1. Graba pantalla del móvil mientras usas CodeNomad
2. Captura el momento cuando se traba
3. Captura los errores
4. Me mandas el video (puedo ver todo)
Mientras trabajo en el fix permanente, puedes usar:
Modificar heartbeat para detectar trabados más rápido:
# Editar el código del servidor
nano /home/dark/Project/codenomad/packages/server/src/server/routes/events.ts
# Cambiar línea 50-53 de:
const heartbeat = setInterval(() => {
const ping = { ts: Date.now() }
reply.raw.write(`event: codenomad.client.ping\ndata: ${JSON.stringify(ping)}\n\n`)
}, 15000)
# A:
const heartbeat = setInterval(() => {
const ping = { ts: Date.now() }
reply.raw.write(`event: codenomad.client.ping\ndata: ${JSON.stringify(ping)}\n\n`)
}, 5000) // Ping cada 5s en lugar de 15s
# Guardar y rebuildActivar más logs para diagnosticar:
# Al iniciar CodeNomad
export LOG_LEVEL=trace
npx @neuralnomads/codenomad-dev --host 0.0.0.0 --https-port 9898 --password 3467 --launchPara respuestas muy largas/importantes:
- Acceder desde desktop via VPN
- Más estable para esos casos
- Volver a móvil para uso normal
| Causa Probable | Solución | Dificultad | ETA |
|---|---|---|---|
| Stream trabado | Auto-recovery watchdog | Media | 2 horas |
| Abort error | Ignorar error de cancel | Fácil | 30 min |
| Estado UI desync | Limpiar errores en send | Fácil | 30 min |
| OpenCode timeout | Timeout en requests | Media | 2 horas |
| VPN/Network | Heartbeat más frecuente | Fácil | 15 min |
El fix será exitoso cuando:
- ✅ Respuestas largas completan sin trabarse
- ✅ Si se traba, auto-recupera sin intervención
- ✅ No hay errores molestos (solo errores reales)
- ✅ No necesitas hacer STOP + "?"
- ✅ Contexto siempre se preserva
- Capturar screenshots de errores
- Obtener hora exacta de incidente
- Revisar logs del servidor
- Identificar causa raíz
- Implementar fix
- Testing del fix
- Commit y push
- Reportar a upstream (opcional)
Actualiza aquí:
[ ] DONE - Fecha: _____
[ ] Screenshots capturados: _____
[ ] Errores identificados: _____
[ ] Fix implementado: _____
[ ] Testing exitoso: _____
Tu parte (cuando vuelvas a usar CodeNomad):
- Abre CodeNomad en móvil
- Haz una pregunta
- Cuando se trabe:
- Screenshot de la pantalla
- Anota hora: ::____
- Presiona STOP
- Screenshot del error
- Mándame las imágenes + hora
Mi parte (cuando me mandes la info):
- Revisar logs en esa hora
- Buscar causa en código
- Implementar fix
- Rebuild y restart
- Pedirte que testees
Mándame por cualquier medio:
- Screenshots
- Hora del incidente
- Cualquier observación adicional
Te responderé con:
- Análisis de los logs
- Causa identificada
- Fix propuesto
- Instrucciones para testear
BUG-REPORT-MOBILE-SESSION-ERRORS.md- Análisis detalladoMOBILE-WEB-TROUBLESHOOTING.md- Guía completapackages/server/src/server/routes/events.ts- SSE implementationpackages/ui/src/stores/- Session state management
¡Estoy listo para resolver esto en cuanto tengas los screenshots! 🚀
El bug tiene solución, solo necesitamos ver los errores exactos para saber qué path seguir.