feat: renderizar Markdown a HTML en mensajes Matrix con goldmark
Se reemplaza SendText por SendMarkdown en todos los puntos donde el agente envía respuestas: runtime.go (comandos built-in y tareas orquestadas), effects/runner.go (acciones Reply) y tools/matrix.go (matrix_send tool). shell/matrix/client.go ahora usa goldmark para convertir Markdown a HTML real en el campo FormattedBody del evento Matrix, cumpliendo con la spec de Matrix para mensajes formateados. El Body conserva el markdown raw como fallback. Se añade dependencia github.com/yuin/goldmark v1.7.16. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+3
-3
@@ -391,7 +391,7 @@ func (a *Agent) handleTaskEvent(ctx context.Context, msg bus.AgentMessage) {
|
||||
}
|
||||
|
||||
// Send reply to Matrix room
|
||||
if sendErr := a.matrix.SendText(ctx, roomID, reply); sendErr != nil {
|
||||
if sendErr := a.matrix.SendMarkdown(ctx, roomID, reply); sendErr != nil {
|
||||
a.logger.Error("failed to send orchestrated reply to Matrix", "err", sendErr)
|
||||
}
|
||||
|
||||
@@ -453,13 +453,13 @@ func (a *Agent) handleEvent(ctx context.Context, msgCtx decision.MessageContext,
|
||||
if handler, ok := a.commands[cmdName]; ok {
|
||||
a.logger.Info("command_executed", "command", cmdName)
|
||||
reply := handler(ctx, msgCtx)
|
||||
_ = a.matrix.SendText(ctx, roomID, reply)
|
||||
_ = a.matrix.SendMarkdown(ctx, roomID, reply)
|
||||
return
|
||||
}
|
||||
|
||||
// Unknown command — never falls through to rules or LLM
|
||||
a.logger.Info("command_unknown", "command", msgCtx.Command)
|
||||
_ = a.matrix.SendText(ctx, roomID,
|
||||
_ = a.matrix.SendMarkdown(ctx, roomID,
|
||||
fmt.Sprintf("Comando desconocido: !%s. Usa !help para ver comandos disponibles.", msgCtx.Command))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ require (
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
github.com/yuin/goldmark v1.7.16 // indirect
|
||||
go.mau.fi/util v0.8.1 // indirect
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
|
||||
@@ -110,6 +110,8 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
|
||||
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
|
||||
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
go.mau.fi/util v0.8.1 h1:Ga43cz6esQBYqcjZ/onRoVnYWoUwjWbsxVeJg2jOTSo=
|
||||
go.mau.fi/util v0.8.1/go.mod h1:T1u/rD2rzidVrBLyaUdPpZiJdP/rsyi+aTzn0D+Q6wc=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
|
||||
@@ -22,6 +22,7 @@ type Result struct {
|
||||
// MatrixSender is satisfied by shell/matrix.Client.
|
||||
type MatrixSender interface {
|
||||
SendText(ctx context.Context, roomID, text string) error
|
||||
SendMarkdown(ctx context.Context, roomID, markdown string) error
|
||||
SendTyping(ctx context.Context, roomID string, typing bool) error
|
||||
}
|
||||
|
||||
@@ -65,7 +66,7 @@ func (r *Runner) executeOne(ctx context.Context, roomID string, a decision.Actio
|
||||
if a.Reply.ThreadID != "" {
|
||||
target = a.Reply.ThreadID
|
||||
}
|
||||
err := r.matrix.SendText(ctx, target, a.Reply.Content)
|
||||
err := r.matrix.SendMarkdown(ctx, target, a.Reply.Content)
|
||||
return Result{Action: a, Output: a.Reply.Content, Err: err}
|
||||
|
||||
case decision.ActionKindSSH:
|
||||
|
||||
+15
-1
@@ -3,6 +3,7 @@ package matrix
|
||||
|
||||
import (
|
||||
"context"
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"maunium.net/go/mautrix"
|
||||
"maunium.net/go/mautrix/crypto"
|
||||
"maunium.net/go/mautrix/crypto/cryptohelper"
|
||||
@@ -269,17 +271,29 @@ func (c *Client) SendText(ctx context.Context, roomID, text string) error {
|
||||
}
|
||||
|
||||
// SendMarkdown sends a formatted (Markdown) message to a room.
|
||||
// Body contains the raw markdown (plaintext fallback per Matrix spec).
|
||||
// FormattedBody contains the HTML rendered by goldmark.
|
||||
func (c *Client) SendMarkdown(ctx context.Context, roomID, markdown string) error {
|
||||
html := mdToHTML(markdown)
|
||||
content := event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: markdown,
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: markdown, // mautrix can render markdown -> HTML if needed
|
||||
FormattedBody: html,
|
||||
}
|
||||
_, err := c.raw.SendMessageEvent(ctx, id.RoomID(roomID), event.EventMessage, content)
|
||||
return err
|
||||
}
|
||||
|
||||
// mdToHTML converts a Markdown string to HTML using goldmark.
|
||||
func mdToHTML(md string) string {
|
||||
var buf bytes.Buffer
|
||||
if err := goldmark.Convert([]byte(md), &buf); err != nil {
|
||||
return md // fallback to raw markdown on error
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// SendReaction sends a reaction to an event.
|
||||
func (c *Client) SendReaction(ctx context.Context, roomID, eventID, reaction string) error {
|
||||
_, err := c.raw.SendReaction(ctx, id.RoomID(roomID), id.EventID(eventID), reaction)
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ import (
|
||||
// Satisfied by shell/matrix.Client.
|
||||
type MatrixSender interface {
|
||||
SendText(ctx context.Context, roomID, text string) error
|
||||
SendMarkdown(ctx context.Context, roomID, markdown string) error
|
||||
}
|
||||
|
||||
// NewMatrixSend creates a matrix_send tool that sends a message to a Matrix room.
|
||||
@@ -29,7 +30,7 @@ func NewMatrixSend(sender MatrixSender) Tool {
|
||||
return Result{Err: fmt.Errorf("matrix_send: room_id and message are required")}
|
||||
}
|
||||
|
||||
if err := sender.SendText(ctx, roomID, message); err != nil {
|
||||
if err := sender.SendMarkdown(ctx, roomID, message); err != nil {
|
||||
return Result{Err: fmt.Errorf("matrix_send: %w", err)}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user