Skip to main content
Glama
slash_handlers.go8.38 kB
package commands import ( "fmt" "strings" "time" tea "github.com/charmbracelet/bubbletea" "github.com/standardbeagle/brummer/internal/logs" "github.com/standardbeagle/brummer/internal/process" ) // SlashCommandContext contains all the dependencies needed to handle slash commands type SlashCommandContext struct { ProcessManager *process.Manager LogStore *logs.Store UpdateChan chan<- tea.Msg // Current state ShowPattern *string HidePattern *string SearchResults *[]logs.LogEntry CurrentView *string // Callbacks UpdateLogsView func() ClearLogs func(target string) SetProxyURL func(urlStr string) ToggleProxy func() StartAICoder func(providerName string) ShowTerminal func() } // HandleSlashCommand processes slash commands functionally func HandleSlashCommand(ctx *SlashCommandContext, input string) { // Clear previous search results and filters *ctx.SearchResults = nil *ctx.ShowPattern = "" *ctx.HidePattern = "" // Parse the command input = strings.TrimSpace(input) // If the command doesn't start with /, add it if !strings.HasPrefix(input, "/") { input = "/" + input } parts := strings.Fields(input) if len(parts) == 0 { return } command := parts[0] switch command { case "/show": if len(parts) < 2 { return } *ctx.ShowPattern = strings.Join(parts[1:], " ") case "/hide": if len(parts) < 2 { return } *ctx.HidePattern = strings.Join(parts[1:], " ") case "/run": handleRunCommand(ctx, parts) case "/restart": handleRestartCommand(ctx, parts) case "/stop": handleStopCommand(ctx, parts) case "/clear": target := "all" if len(parts) >= 2 { target = parts[1] } ctx.ClearLogs(target) case "/proxy": if len(parts) < 2 { return } urlStr := strings.Join(parts[1:], " ") ctx.SetProxyURL(urlStr) case "/toggle-proxy": ctx.ToggleProxy() case "/ai": if len(parts) < 2 { ctx.LogStore.Add("system", "System", "Error: /ai command requires a provider name", true) return } providerName := parts[1] ctx.StartAICoder(providerName) case "/term": ctx.ShowTerminal() case "/help": *ctx.CurrentView = "help" default: // Unknown command - show error ctx.LogStore.Add("system", "System", fmt.Sprintf("❌ Unknown command: %s", command), true) ctx.LogStore.Add("system", "System", "Available commands: /run, /restart, /stop, /clear, /show, /hide, /proxy, /toggle-proxy, /ai, /term, /help", false) } } func handleRunCommand(ctx *SlashCommandContext, parts []string) { if len(parts) < 2 { ctx.LogStore.Add("system", "System", "Error: /run command requires a script name", true) return } scriptName := parts[1] // Execute the script errorHandler := NewStandardErrorHandler(ctx.LogStore, ctx.UpdateChan) SafeGoroutine( fmt.Sprintf("start script '%s'", scriptName), func() error { _, err := ctx.ProcessManager.StartScript(scriptName) if err == nil { ctx.UpdateChan <- processUpdateMsg{} } return err }, func(err error) { errorCtx := ScriptStartContext(scriptName, "Slash Command", ctx.LogStore, ctx.UpdateChan) errorHandler.HandleError(err, errorCtx) }, ) // Switch to logs view immediately *ctx.CurrentView = "logs" } func handleRestartCommand(ctx *SlashCommandContext, parts []string) { processName := "all" if len(parts) >= 2 { processName = parts[1] } if processName == "all" { // Restart all running processes SafeGoroutineNoError( "restart all processes", func() { processes := ctx.ProcessManager.GetAllProcesses() restarted := 0 for _, proc := range processes { if proc.GetStatus() == process.StatusRunning { // Stop the process and wait for termination timeout := 5 * time.Second if err := ctx.ProcessManager.StopProcessAndWait(proc.ID, timeout); err != nil { ctx.LogStore.Add("system", "System", fmt.Sprintf("Error stopping process %s: %v", proc.Name, err), true) continue } // Start it again _, err := ctx.ProcessManager.StartScript(proc.Name) if err != nil { ctx.LogStore.Add("system", "System", fmt.Sprintf("Error restarting script %s: %v", proc.Name, err), true) } else { restarted++ } } } ctx.LogStore.Add("system", "System", fmt.Sprintf("🔄 Restarted %d processes", restarted), false) ctx.UpdateChan <- processUpdateMsg{} }, func(err error) { ctx.LogStore.Add("system", "System", fmt.Sprintf("Critical error during restart all: %v", err), true) ctx.UpdateChan <- logUpdateMsg{} }, ) } else { // Restart specific process SafeGoroutineNoError( fmt.Sprintf("restart process '%s'", processName), func() { // Find the process var targetProc *process.Process for _, proc := range ctx.ProcessManager.GetAllProcesses() { if proc.Name == processName && proc.GetStatus() == process.StatusRunning { targetProc = proc break } } if targetProc == nil { ctx.LogStore.Add("system", "System", fmt.Sprintf("Process '%s' is not running", processName), true) ctx.UpdateChan <- logUpdateMsg{} return } // Stop and restart the process timeout := 5 * time.Second if err := ctx.ProcessManager.StopProcessAndWait(targetProc.ID, timeout); err != nil { errorMsg := fmt.Sprintf("Error stopping process '%s' (ID: %s) during restart: %v", processName, targetProc.ID, err) ctx.LogStore.Add("system", "System", errorMsg, true) ctx.UpdateChan <- logUpdateMsg{} return } _, err := ctx.ProcessManager.StartScript(processName) if err != nil { errorMsg := fmt.Sprintf("Error restarting script '%s' after successful stop: %v", processName, err) ctx.LogStore.Add("system", "System", errorMsg, true) } else { ctx.LogStore.Add("system", "System", fmt.Sprintf("🔄 Restarted process: %s", processName), false) } ctx.UpdateChan <- processUpdateMsg{} }, func(err error) { ctx.LogStore.Add("system", "System", fmt.Sprintf("Critical error during restart of '%s': %v", processName, err), true) ctx.UpdateChan <- logUpdateMsg{} }, ) } *ctx.CurrentView = "processes" } func handleStopCommand(ctx *SlashCommandContext, parts []string) { processName := "all" if len(parts) >= 2 { processName = parts[1] } if processName == "all" { // Stop all running processes SafeGoroutineNoError( "stop all processes", func() { processes := ctx.ProcessManager.GetAllProcesses() stopped := 0 for _, proc := range processes { if proc.GetStatus() == process.StatusRunning { if err := ctx.ProcessManager.StopProcess(proc.ID); err != nil { ctx.LogStore.Add("system", "System", fmt.Sprintf("Error stopping process %s: %v", proc.Name, err), true) } else { stopped++ } } } ctx.LogStore.Add("system", "System", fmt.Sprintf("⏹️ Stopped %d processes", stopped), false) ctx.UpdateChan <- processUpdateMsg{} }, func(err error) { ctx.LogStore.Add("system", "System", fmt.Sprintf("Critical error during stop all: %v", err), true) ctx.UpdateChan <- logUpdateMsg{} }, ) } else { // Stop specific process SafeGoroutineNoError( fmt.Sprintf("stop process '%s'", processName), func() { // Find the process var targetProc *process.Process for _, proc := range ctx.ProcessManager.GetAllProcesses() { if proc.Name == processName && proc.GetStatus() == process.StatusRunning { targetProc = proc break } } if targetProc == nil { ctx.LogStore.Add("system", "System", fmt.Sprintf("Process '%s' is not running", processName), true) ctx.UpdateChan <- logUpdateMsg{} return } if err := ctx.ProcessManager.StopProcess(targetProc.ID); err != nil { ctx.LogStore.Add("system", "System", fmt.Sprintf("Error stopping process %s: %v", processName, err), true) } else { ctx.LogStore.Add("system", "System", fmt.Sprintf("⏹️ Stopped process: %s", processName), false) } ctx.UpdateChan <- processUpdateMsg{} }, func(err error) { ctx.LogStore.Add("system", "System", fmt.Sprintf("Critical error during stop of '%s': %v", processName, err), true) ctx.UpdateChan <- logUpdateMsg{} }, ) } *ctx.CurrentView = "processes" } // Message types used for updates type logUpdateMsg struct{} type processUpdateMsg struct{}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server