130 lines
4.0 KiB
Go
130 lines
4.0 KiB
Go
package command
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// Command represents a slash command.
|
|
type Command struct {
|
|
Name string
|
|
Aliases []string
|
|
Description string
|
|
Usage string
|
|
Handler func(ctx *Context, args []string) Result
|
|
}
|
|
|
|
// Context provides commands with read access to application state.
|
|
type Context struct {
|
|
Model string
|
|
ModelList []string
|
|
AgentProfile string
|
|
AgentList []string
|
|
ToolCount int
|
|
ServerCount int
|
|
ServerNames []string
|
|
Skills []SkillInfo
|
|
LoadedFile string
|
|
ICEEnabled bool
|
|
ICEConversations int
|
|
ICESessionID string
|
|
// Token stats
|
|
SessionEvalTotal int
|
|
SessionPromptTotal int
|
|
SessionTurnCount int
|
|
NumCtx int
|
|
CurrentModel string
|
|
// File changes
|
|
FileChanges map[string]int // path → modification count
|
|
}
|
|
|
|
// SkillInfo is a read-only view of a skill for command display.
|
|
type SkillInfo struct {
|
|
Name string
|
|
Description string
|
|
Active bool
|
|
}
|
|
|
|
// Result is returned by command handlers to describe what to do.
|
|
type Result struct {
|
|
Text string // Display text (shown as system message)
|
|
Action Action // Side effect for the TUI to execute
|
|
Data string // Optional payload (e.g. file path, model name)
|
|
Error string // Error text (takes priority over Text)
|
|
}
|
|
|
|
// Action describes a side effect the TUI should perform.
|
|
type Action int
|
|
|
|
const (
|
|
ActionNone Action = iota
|
|
ActionShowHelp // Show help overlay
|
|
ActionClear // Clear conversation history
|
|
ActionQuit // Exit the application
|
|
ActionLoadContext // Load markdown context (Data = path)
|
|
ActionUnloadContext // Remove loaded context
|
|
ActionActivateSkill // Activate skill (Data = name)
|
|
ActionDeactivateSkill // Deactivate skill (Data = name)
|
|
ActionSwitchModel // Switch model (Data = model name)
|
|
ActionSwitchAgent // Switch agent profile (Data = agent name)
|
|
ActionShowSessions // Open sessions picker
|
|
ActionShowModelPicker // Open model picker overlay
|
|
ActionCommit // Generate commit message and commit
|
|
ActionSendPrompt // Send Data as a message to the agent
|
|
ActionExport // Export conversation (Data = path)
|
|
ActionImport // Import conversation (Data = path)
|
|
)
|
|
|
|
// Registry holds all registered slash commands.
|
|
type Registry struct {
|
|
commands map[string]*Command // name/alias → command
|
|
all []*Command // ordered list
|
|
}
|
|
|
|
// NewRegistry creates an empty command registry.
|
|
func NewRegistry() *Registry {
|
|
return &Registry{
|
|
commands: make(map[string]*Command),
|
|
}
|
|
}
|
|
|
|
// Register adds a command to the registry.
|
|
func (r *Registry) Register(cmd *Command) {
|
|
r.all = append(r.all, cmd)
|
|
r.commands[cmd.Name] = cmd
|
|
for _, alias := range cmd.Aliases {
|
|
r.commands[alias] = cmd
|
|
}
|
|
}
|
|
|
|
// Execute dispatches a slash command by name and returns the result.
|
|
func (r *Registry) Execute(ctx *Context, name string, args []string) Result {
|
|
cmd, ok := r.commands[name]
|
|
if !ok {
|
|
return Result{Error: fmt.Sprintf("unknown command: /%s — type /help for available commands", name)}
|
|
}
|
|
return cmd.Handler(ctx, args)
|
|
}
|
|
|
|
// All returns all registered commands in registration order.
|
|
func (r *Registry) All() []*Command {
|
|
return r.all
|
|
}
|
|
|
|
// Match returns commands whose name starts with the given prefix.
|
|
func (r *Registry) Match(prefix string) []*Command {
|
|
var matches []*Command
|
|
seen := make(map[string]bool)
|
|
for _, cmd := range r.all {
|
|
if strings.HasPrefix(cmd.Name, prefix) && !seen[cmd.Name] {
|
|
matches = append(matches, cmd)
|
|
seen[cmd.Name] = true
|
|
}
|
|
}
|
|
sort.Slice(matches, func(i, j int) bool {
|
|
return matches[i].Name < matches[j].Name
|
|
})
|
|
return matches
|
|
}
|