refactor: extraer campo sender en Agent para desacoplar envio de mensajes
Añade un campo `sender effects.MatrixSender` al struct Agent que reemplaza las llamadas directas a `a.matrix` para enviar mensajes (sendReply, typing, SendMarkdown en handleTaskEvent). En produccion, sender apunta al mismo *matrix.Client. Esto permite inyectar un spy en tests sin requerir una conexion real a Matrix. El campo `a.matrix` se mantiene para operaciones que no son de envio (SetPresence, Raw, etc.). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+8
-8
@@ -29,8 +29,8 @@ func (a *Agent) handleEvent(ctx context.Context, msgCtx decision.MessageContext,
|
||||
a.roomCtx.Set(roomID)
|
||||
|
||||
if a.cfg.Personality.Behavior.TypingIndicator {
|
||||
_ = a.matrix.SendTyping(ctx, roomID, true)
|
||||
defer a.matrix.SendTyping(ctx, roomID, false)
|
||||
_ = a.sender.SendTyping(ctx, roomID, true)
|
||||
defer a.sender.SendTyping(ctx, roomID, false)
|
||||
}
|
||||
|
||||
// ── Command flow ─────────────────────────────────────────────────
|
||||
@@ -233,8 +233,8 @@ func (a *Agent) handleTaskEvent(ctx context.Context, msg bus.AgentMessage) {
|
||||
a.roomCtx.Set(roomID)
|
||||
|
||||
if a.cfg.Personality.Behavior.TypingIndicator {
|
||||
_ = a.matrix.SendTyping(ctx, roomID, true)
|
||||
defer a.matrix.SendTyping(ctx, roomID, false)
|
||||
_ = a.sender.SendTyping(ctx, roomID, true)
|
||||
defer a.sender.SendTyping(ctx, roomID, false)
|
||||
}
|
||||
|
||||
// Build a synthetic MessageContext from the task
|
||||
@@ -261,7 +261,7 @@ func (a *Agent) handleTaskEvent(ctx context.Context, msg bus.AgentMessage) {
|
||||
if rejected {
|
||||
a.logger.Warn("orchestrated task rejected by sanitizer",
|
||||
"task_id", task.TaskID, "sender", task.OriginalSender)
|
||||
_ = a.matrix.SendMarkdown(ctx, roomID, "El mensaje fue rechazado por el filtro de seguridad.")
|
||||
_ = a.sender.SendMarkdown(ctx, roomID, "El mensaje fue rechazado por el filtro de seguridad.")
|
||||
return
|
||||
}
|
||||
msgCtx.Content = sanitized
|
||||
@@ -294,7 +294,7 @@ func (a *Agent) handleTaskEvent(ctx context.Context, msg bus.AgentMessage) {
|
||||
}
|
||||
|
||||
// Send reply to Matrix room
|
||||
if sendErr := a.matrix.SendMarkdown(ctx, roomID, reply); sendErr != nil {
|
||||
if sendErr := a.sender.SendMarkdown(ctx, roomID, reply); sendErr != nil {
|
||||
a.logger.Error("failed to send orchestrated reply to Matrix", "err", sendErr)
|
||||
}
|
||||
|
||||
@@ -321,9 +321,9 @@ func (a *Agent) handleTaskEvent(ctx context.Context, msg bus.AgentMessage) {
|
||||
// If threadID is non-empty, the reply is sent as part of that thread.
|
||||
func (a *Agent) sendReply(ctx context.Context, roomID, eventID, threadID, markdown string) error {
|
||||
if threadID != "" {
|
||||
return a.matrix.SendThreadMarkdown(ctx, roomID, threadID, eventID, markdown)
|
||||
return a.sender.SendThreadMarkdown(ctx, roomID, threadID, eventID, markdown)
|
||||
}
|
||||
return a.matrix.SendReplyMarkdown(ctx, roomID, eventID, markdown)
|
||||
return a.sender.SendReplyMarkdown(ctx, roomID, eventID, markdown)
|
||||
}
|
||||
|
||||
// parseSeverity converts a config string to sanitize.Severity.
|
||||
|
||||
@@ -49,6 +49,7 @@ type Agent struct {
|
||||
rules []decision.Rule
|
||||
llm coretypes.CompleteFunc // nil when no LLM configured (simple_bot)
|
||||
matrix *matrix.Client
|
||||
sender effects.MatrixSender // used by sendReply; same object as matrix in production
|
||||
runner *effects.Runner
|
||||
listener *matrix.Listener
|
||||
toolReg *tools.Registry
|
||||
@@ -157,6 +158,7 @@ func New(cfg *config.AgentConfig, rules []decision.Rule, agentACL acl.ACL, logge
|
||||
rules: rules,
|
||||
llm: llmFunc,
|
||||
matrix: matrixClient,
|
||||
sender: matrixClient,
|
||||
runner: runner,
|
||||
toolReg: toolReg,
|
||||
logger: logger,
|
||||
|
||||
Reference in New Issue
Block a user