2756557498
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>
90 lines
3.1 KiB
Markdown
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
|