feat: mensajes progresivos en Matrix con ProgressReporter
Implementa la Fase 2 del issue 0036: mensajes de progreso en tiempo real que muestran al usuario que herramientas esta usando el agente claude-code. - SendMarkdownGetID en shell/matrix/client.go: envia mensaje y retorna el event ID para editarlo despues - EditMessage en shell/matrix/client.go: edita un mensaje existente usando m.replace (m.relates_to con rel_type=m.replace) - ProgressReporter en shell/effects/progress.go (NEW): recibe streaming events y actualiza un mensaje unico en Matrix mostrando el progreso (e.g. "🔧 Bash: ls -la" → "🔧 Read: file.go" → "✅ Completado") - Rate limiter integrado: max 1 edit/segundo para no saturar el homeserver - Conectado en devagents/handler.go: cuando provider=claude-code y streaming+show_tool_progress habilitados, crea ProgressReporter y pasa StreamFunc al CompletionRequest - MatrixSender interface actualizada con los nuevos metodos - 10 tests nuevos para ProgressReporter, todos los existentes pasan Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -286,6 +286,51 @@ func (c *Client) SendMarkdown(ctx context.Context, roomID, markdown string) erro
|
||||
return err
|
||||
}
|
||||
|
||||
// SendMarkdownGetID sends a formatted (Markdown) message to a room and returns
|
||||
// the event ID of the sent message. Useful for later editing via EditMessage.
|
||||
func (c *Client) SendMarkdownGetID(ctx context.Context, roomID, markdown string) (string, error) {
|
||||
html := mdToHTML(markdown)
|
||||
content := &event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: markdown,
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: html,
|
||||
}
|
||||
resp, err := c.raw.SendMessageEvent(ctx, id.RoomID(roomID), event.EventMessage, content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.EventID.String(), nil
|
||||
}
|
||||
|
||||
// EditMessage edits a previously sent message in a room using m.replace relation.
|
||||
// originalEventID is the event ID of the message to replace.
|
||||
// The new content is rendered from markdown.
|
||||
func (c *Client) EditMessage(ctx context.Context, roomID, originalEventID, markdown string) error {
|
||||
html := mdToHTML(markdown)
|
||||
|
||||
// Matrix spec: m.new_content holds the replacement, m.relates_to with
|
||||
// rel_type=m.replace points to the original event.
|
||||
content := &event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: "* " + markdown, // per spec: prefix with "* " for fallback
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: "* " + html,
|
||||
RelatesTo: &event.RelatesTo{
|
||||
Type: event.RelReplace,
|
||||
EventID: id.EventID(originalEventID),
|
||||
},
|
||||
NewContent: &event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: markdown,
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: html,
|
||||
},
|
||||
}
|
||||
_, err := c.raw.SendMessageEvent(ctx, id.RoomID(roomID), event.EventMessage, content)
|
||||
return err
|
||||
}
|
||||
|
||||
// mdToHTML converts a Markdown string to HTML using goldmark with full extensions.
|
||||
var mdParser = goldmark.New(
|
||||
goldmark.WithExtensions(
|
||||
|
||||
Reference in New Issue
Block a user