feat: respuestas como reply de Matrix + presencia online/offline
Añade soporte para que las respuestas de los bots sean replies nativos de Matrix (m.in_reply_to) en lugar de mensajes sueltos. Los clientes Matrix mostrarán el mensaje original citado. Cambios: - EventID en MessageContext para capturar el ID del evento entrante - InReplyTo en ReplyAction para indicar a qué evento responder - SendReplyMarkdown en el cliente Matrix (shell/matrix/client.go) - Runner usa SendReplyMarkdown cuando InReplyTo está presente - runtime.go pasa InReplyTo en todas las respuestas LLM y comandos - SetPresence online al arrancar, offline al apagar (graceful) No se tocan: herramientas, TUI, configuración de agentes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ type Result struct {
|
||||
type MatrixSender interface {
|
||||
SendText(ctx context.Context, roomID, text string) error
|
||||
SendMarkdown(ctx context.Context, roomID, markdown string) error
|
||||
SendReplyMarkdown(ctx context.Context, roomID, inReplyTo, markdown string) error
|
||||
SendTyping(ctx context.Context, roomID string, typing bool) error
|
||||
}
|
||||
|
||||
@@ -66,7 +67,12 @@ func (r *Runner) executeOne(ctx context.Context, roomID string, a decision.Actio
|
||||
if a.Reply.ThreadID != "" {
|
||||
target = a.Reply.ThreadID
|
||||
}
|
||||
err := r.matrix.SendMarkdown(ctx, target, a.Reply.Content)
|
||||
var err error
|
||||
if a.Reply.InReplyTo != "" {
|
||||
err = r.matrix.SendReplyMarkdown(ctx, target, a.Reply.InReplyTo, a.Reply.Content)
|
||||
} else {
|
||||
err = r.matrix.SendMarkdown(ctx, target, a.Reply.Content)
|
||||
}
|
||||
return Result{Action: a, Output: a.Reply.Content, Err: err}
|
||||
|
||||
case decision.ActionKindSSH:
|
||||
|
||||
@@ -305,6 +305,21 @@ func mdToHTML(md string) string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// SendReplyMarkdown sends a formatted message as a reply to a specific event.
|
||||
// It sets m.in_reply_to so Matrix clients show the original message as a quote.
|
||||
func (c *Client) SendReplyMarkdown(ctx context.Context, roomID, inReplyTo, markdown string) error {
|
||||
html := mdToHTML(markdown)
|
||||
content := event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: markdown,
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: html,
|
||||
RelatesTo: (&event.RelatesTo{}).SetReplyTo(id.EventID(inReplyTo)),
|
||||
}
|
||||
_, err := c.raw.SendMessageEvent(ctx, id.RoomID(roomID), event.EventMessage, content)
|
||||
return err
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -448,6 +463,11 @@ func truncateKey(key string) string {
|
||||
return key
|
||||
}
|
||||
|
||||
// SetPresence sets the bot's presence status (online, unavailable, offline).
|
||||
func (c *Client) SetPresence(ctx context.Context, status event.Presence) error {
|
||||
return c.raw.SetPresence(ctx, status)
|
||||
}
|
||||
|
||||
// Raw returns the underlying mautrix.Client for advanced use.
|
||||
func (c *Client) Raw() *mautrix.Client {
|
||||
return c.raw
|
||||
|
||||
@@ -134,6 +134,7 @@ func (l *Listener) Run(ctx context.Context) error {
|
||||
isDM,
|
||||
opts,
|
||||
)
|
||||
msgCtx.EventID = evt.ID.String()
|
||||
|
||||
l.logger.Debug("message parsed",
|
||||
"sender", msgCtx.SenderID,
|
||||
|
||||
Reference in New Issue
Block a user