Files
agents_and_robots/dev/issues/0012-threads.md
T
egutierrez 2756557498 chore: renombrar issues a formato 4 dígitos (NNNN)
Se estandariza la numeración de todos los issues de 3 dígitos a 4 dígitos
(e.g. 005 → 0005, 010 → 0010) para mantener consistencia con la convención
definida en create_issue.md. Se actualiza el README con los nuevos nombres
y links. No hay cambios de contenido en los issues, solo renombrado.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:39:33 +00:00

90 lines
3.1 KiB
Markdown

# Task 011 — Matrix Thread Support
## Objetivo
Permitir que los agentes mantengan conversaciones en threads de Matrix (`m.thread`),
de forma que cada interaccion con un usuario pueda vivir en un hilo separado
en lugar de la timeline principal del room.
## Contexto
Matrix soporta threads via `m.relates_to` con `rel_type: "m.thread"`.
Un thread siempre referencia un **evento raiz** y opcionalmente incluye
`m.in_reply_to` como fallback para clientes sin soporte de threads.
```json
{
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$rootEventId",
"is_falling_back": true,
"m.in_reply_to": {
"event_id": "$lastEventInThread"
}
}
}
```
## Prerequisito
- Task: Reply simple (`m.in_reply_to`) ya implementado.
## Plan de implementacion
### 1. Detectar threads entrantes en el Listener
- En `shell/matrix/listener.go`, al parsear el evento, extraer `m.relates_to`
- Si `rel_type == "m.thread"`, capturar `event_id` como `ThreadRootID`
- Propagar `ThreadRootID` en `MessageContext`
### 2. Extender MessageContext
- `pkg/decision/types.go`: anadir `ThreadRootID string` (el evento raiz del thread)
- Esto es dato puro, no rompe la arquitectura
### 3. Extender ReplyAction
- `pkg/decision/types.go`: anadir `ThreadRootID string` a `ReplyAction`
- El runner usara esto para decidir si enviar como thread o como mensaje normal
### 4. SendThreadMarkdown en Client
- `shell/matrix/client.go`: nuevo metodo `SendThreadMarkdown(ctx, roomID, threadRootID, inReplyTo, markdown)`
- Construye el `m.relates_to` con `rel_type: "m.thread"` + fallback `m.in_reply_to`
### 5. Actualizar effects/Runner
- `shell/effects/runner.go`: si `ReplyAction.ThreadRootID != ""`, usar `SendThreadMarkdown`
- Actualizar interfaz `MatrixSender` con el nuevo metodo
### 6. Propagacion en runtime.go
- Cuando el mensaje entrante ya esta en un thread (`msgCtx.ThreadRootID != ""`),
las respuestas del bot deben continuar en ese thread
- Cuando el usuario inicia una conversacion nueva, decidir segun config si crear thread o no
### 7. Configuracion por agente
- `internal/config/schema.go`: anadir opcion `matrix.threads.enabled: bool` y
`matrix.threads.auto_thread: bool` (crear thread automatico por cada conversacion nueva)
- Default: `enabled: true`, `auto_thread: false`
### 8. Memory por thread
- La window de conversacion deberia poder ser por thread en vez de por room
- Si `ThreadRootID != ""`, usar `threadRootID` como key de la window en vez de `roomID`
- Esto permite conversaciones paralelas en threads distintos sin mezclarse
### 9. Tests
- Unit tests para `SendThreadMarkdown` (verificar estructura JSON)
- Test de integracion: listener detecta thread entrante y propaga ThreadRootID
- Test: respuesta dentro de thread mantiene el thread root correcto
## Notas
- `is_falling_back: true` siempre debe estar cuando se usa thread + in_reply_to fallback
- El `event_id` de `m.relates_to` (nivel top) siempre apunta al root del thread, nunca cambia
- El `m.in_reply_to` dentro del thread apunta al ultimo mensaje respondido
- Clientes sin soporte de threads ven el fallback como un reply normal