feat: formato markdown en salida de comandos built-in

Mejora la salida de !help, !tools, !status e !info para usar markdown
nativo: encabezados en negrita, listas con bullet points, código inline
con backticks. Aprovecha el rendering HTML que ya hace el bot para que
los clientes Matrix muestren la información formateada correctamente.

No se cambia lógica de comandos, solo formato de texto de salida.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 15:46:13 +00:00
parent 76ff9394d0
commit d95ae173de
+21 -21
View File
@@ -25,7 +25,7 @@ func (a *Agent) registerBuiltinCommands() {
// cmdHelp lists all available commands (built-in + agent-specific).
func (a *Agent) cmdHelp(_ context.Context, _ decision.MessageContext) string {
var b strings.Builder
b.WriteString("Comandos disponibles:\n\n")
b.WriteString("**Comandos disponibles:**\n\n")
// Built-in commands
for _, spec := range command.Builtins() {
@@ -37,7 +37,7 @@ func (a *Agent) cmdHelp(_ context.Context, _ decision.MessageContext) string {
// Agent-specific commands (registered via RegisterCommand)
if len(a.customSpecs) > 0 {
b.WriteString("\nComandos del agente:\n")
b.WriteString("\n**Comandos del agente:**\n\n")
for _, spec := range a.customSpecs {
if spec.Hidden {
continue
@@ -59,7 +59,7 @@ func writeSpec(b *strings.Builder, spec command.Spec) {
if usage == "" {
usage = "!" + spec.Name
}
fmt.Fprintf(b, " %s%s — %s\n", usage, aliases, spec.Description)
fmt.Fprintf(b, "- `%s`%s — %s\n", usage, aliases, spec.Description)
}
// cmdTools lists all tools registered in the agent's tool registry.
@@ -70,31 +70,31 @@ func (a *Agent) cmdTools(_ context.Context, _ decision.MessageContext) string {
}
var b strings.Builder
fmt.Fprintf(&b, "Tools disponibles (%d):\n\n", len(names))
fmt.Fprintf(&b, "**Tools disponibles (%d):**\n\n", len(names))
for _, name := range names {
t, _ := a.toolReg.Get(name)
fmt.Fprintf(&b, " %s — %s\n", t.Def.Name, t.Def.Description)
fmt.Fprintf(&b, "- **%s** — %s\n", t.Def.Name, t.Def.Description)
for _, p := range t.Def.Parameters {
req := ""
if p.Required {
req = " (requerido)"
req = " *(requerido)*"
}
fmt.Fprintf(&b, " %s: %s%s\n", p.Name, p.Description, req)
fmt.Fprintf(&b, " - `%s`: %s%s\n", p.Name, p.Description, req)
}
}
b.WriteString("\nUso: !tool <nombre> [key=value ...]")
b.WriteString("\nUso: `!tool <nombre> [key=value ...]`")
return b.String()
}
// cmdTool executes a tool directly with key=value args.
func (a *Agent) cmdTool(ctx context.Context, msgCtx decision.MessageContext) string {
if len(msgCtx.Args) == 0 {
return "Uso: !tool <nombre> [key=value ...]\nUsa !tools para ver tools disponibles."
return "Uso: `!tool <nombre> [key=value ...]`\nUsa `!tools` para ver tools disponibles."
}
toolName := msgCtx.Args[0]
if _, ok := a.toolReg.Get(toolName); !ok {
return fmt.Sprintf("Tool %q no encontrada. Usa !tools para ver tools disponibles.", toolName)
return fmt.Sprintf("Tool %q no encontrada. Usa `!tools` para ver tools disponibles.", toolName)
}
// Parse remaining args as key=value
@@ -128,16 +128,16 @@ func (a *Agent) cmdStatus(_ context.Context, _ decision.MessageContext) string {
a.windowsMu.RUnlock()
var b strings.Builder
fmt.Fprintf(&b, "Estado de %s:\n", a.cfg.Agent.Name)
fmt.Fprintf(&b, " Uptime: %s\n", uptime)
fmt.Fprintf(&b, " Rooms activos: %d\n", roomCount)
fmt.Fprintf(&b, " Window size: %d\n", a.windowSize)
fmt.Fprintf(&b, " Tools: %d\n", a.toolReg.Len())
fmt.Fprintf(&b, "**Estado de %s:**\n\n", a.cfg.Agent.Name)
fmt.Fprintf(&b, "- **Uptime:** %s\n", uptime)
fmt.Fprintf(&b, "- **Rooms activos:** %d\n", roomCount)
fmt.Fprintf(&b, "- **Window size:** %d\n", a.windowSize)
fmt.Fprintf(&b, "- **Tools:** %d\n", a.toolReg.Len())
if a.llm != nil {
fmt.Fprintf(&b, " LLM: %s/%s\n", a.cfg.LLM.Primary.Provider, a.cfg.LLM.Primary.Model)
fmt.Fprintf(&b, "- **LLM:** %s/%s\n", a.cfg.LLM.Primary.Provider, a.cfg.LLM.Primary.Model)
} else {
b.WriteString(" LLM: no configurado\n")
b.WriteString("- **LLM:** no configurado\n")
}
return b.String()
@@ -146,12 +146,12 @@ func (a *Agent) cmdStatus(_ context.Context, _ decision.MessageContext) string {
// cmdInfo shows agent name, version, and description.
func (a *Agent) cmdInfo(_ context.Context, _ decision.MessageContext) string {
var b strings.Builder
fmt.Fprintf(&b, "Nombre: %s\n", a.cfg.Agent.Name)
fmt.Fprintf(&b, "ID: %s\n", a.cfg.Agent.ID)
fmt.Fprintf(&b, "- **Nombre:** %s\n", a.cfg.Agent.Name)
fmt.Fprintf(&b, "- **ID:** %s\n", a.cfg.Agent.ID)
if a.cfg.Agent.Version != "" {
fmt.Fprintf(&b, "Version: %s\n", a.cfg.Agent.Version)
fmt.Fprintf(&b, "- **Version:** %s\n", a.cfg.Agent.Version)
}
fmt.Fprintf(&b, "Descripcion: %s\n", a.cfg.Agent.Description)
fmt.Fprintf(&b, "- **Descripcion:** %s\n", a.cfg.Agent.Description)
return b.String()
}