Files
Memoh/internal/command/registry.go
zhangxx 8c4e9e218e Merge pull request #323 from mx1700/feat/stop-command
feat: add /stop command to abort agent generation on external channels
2026-04-08 01:25:09 +08:00

95 lines
2.2 KiB
Go

package command
import (
"context"
"fmt"
"strings"
)
// CommandContext carries execution context for a sub-command.
type CommandContext struct {
Ctx context.Context
BotID string
Role string // "owner", "admin", "member", or "" (guest)
Args []string
}
// SubCommand describes a single sub-command within a resource group.
type SubCommand struct {
Name string
Usage string
IsWrite bool
Handler func(cc CommandContext) (string, error)
}
// CommandGroup groups sub-commands under a resource name.
type CommandGroup struct {
Name string
Description string
DefaultAction string
commands map[string]SubCommand
order []string // preserves registration order for help output
}
func newCommandGroup(name, description string) *CommandGroup {
return &CommandGroup{
Name: name,
Description: description,
commands: make(map[string]SubCommand),
}
}
func (g *CommandGroup) Register(sub SubCommand) {
g.commands[sub.Name] = sub
g.order = append(g.order, sub.Name)
}
// Usage returns the usage text for this resource group.
func (g *CommandGroup) Usage() string {
var b strings.Builder
fmt.Fprintf(&b, "/%s - %s\n", g.Name, g.Description)
for _, name := range g.order {
sub := g.commands[name]
perm := ""
if sub.IsWrite {
perm = " [owner]"
}
fmt.Fprintf(&b, "- %s%s\n", sub.Usage, perm)
}
return b.String()
}
// Registry holds all registered command groups.
type Registry struct {
groups map[string]*CommandGroup
order []string
}
func newRegistry() *Registry {
return &Registry{
groups: make(map[string]*CommandGroup),
}
}
func (r *Registry) RegisterGroup(group *CommandGroup) {
r.groups[group.Name] = group
r.order = append(r.order, group.Name)
}
// GlobalHelp returns the top-level help text listing all commands.
func (r *Registry) GlobalHelp() string {
var b strings.Builder
b.WriteString("Available commands:\n\n")
b.WriteString("/help - Show this help message\n")
b.WriteString("/new - Start a new conversation (resets session context)\n")
b.WriteString("/stop - Stop the current generation\n\n")
for i, name := range r.order {
if i > 0 {
b.WriteByte('\n')
}
group := r.groups[name]
b.WriteString(group.Usage())
}
return strings.TrimRight(b.String(), "\n")
}