HandleCommand dispatches a slash command. Returns true to exit the REPL.
(ctx context.Context, userInput string)
| 63 | |
| 64 | // HandleCommand dispatches a slash command. Returns true to exit the REPL. |
| 65 | func (ch *CommandHandler) HandleCommand(ctx context.Context, userInput string) bool { |
| 66 | // Track command usage for memory pattern detection. |
| 67 | if strings.HasPrefix(userInput, "/") && ch.cli.memoryStore != nil { |
| 68 | cmd := strings.Fields(userInput)[0] |
| 69 | if mgr := ch.cli.memoryStore.Manager(); mgr != nil { |
| 70 | mgr.Profile.RecordCommand(cmd) |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | // Command palette. A bare "/" (or "/menu") opens the categorized root |
| 75 | // listing; a bare, pickable command (e.g. "/model", "/config") opens |
| 76 | // scoped to its own subcommands/flags/values. We only flag the request |
| 77 | // here: the executor runs the overlay in place once this handler returns, |
| 78 | // because go-prompt has already released raw mode by the time it calls the |
| 79 | // executor — no panic-based unwind is required. |
| 80 | if target, ok := ch.cli.paletteTrigger(userInput); ok { |
| 81 | ch.cli.paletteTarget = target |
| 82 | ch.cli.paletteRequested = true |
| 83 | return false |
| 84 | } |
| 85 | |
| 86 | // Mode-switch commands raise a sentinel to unwind out of the go-prompt |
| 87 | // loop (a plain return cannot escape it), so they stay as explicit cases |
| 88 | // rather than table entries. |
| 89 | switch { |
| 90 | case strings.HasPrefix(userInput, "/agent"): |
| 91 | // /agent pode ser gerenciamento de personas OU iniciar modo agente |
| 92 | if !ch.handleAgentPersonaSubcommand(userInput) { |
| 93 | // Não é um subcomando, inicia modo agente. |
| 94 | // Smart-routing: if the query looks conversational, the |
| 95 | // default "hint" mode prints a tip and falls through; |
| 96 | // "auto" mode redirects to chat and we return here without |
| 97 | // spinning up the ReAct loop. |
| 98 | task := strings.TrimSpace(strings.TrimPrefix(userInput, "/agent")) |
| 99 | if ch.cli.maybeReroute(ctx, "/agent", task) { |
| 100 | return false |
| 101 | } |
| 102 | ch.cli.pendingAction = "agent" |
| 103 | panic(errAgentModeRequest) |
| 104 | } |
| 105 | return false |
| 106 | case strings.HasPrefix(userInput, "/run"): |
| 107 | // /run inicia o modo agente (com ou sem persona ativa) |
| 108 | ch.cli.pendingAction = "agent" |
| 109 | panic(errAgentModeRequest) |
| 110 | case strings.HasPrefix(userInput, "/coder"): |
| 111 | ch.cli.pendingAction = "coder" |
| 112 | panic(errCoderModeRequest) |
| 113 | case userInput == "/plan" || strings.HasPrefix(userInput, "/plan "): |
| 114 | switch ch.cli.handlePlanCommand(userInput) { |
| 115 | case planRouteAgent: |
| 116 | panic(errAgentModeRequest) |
| 117 | case planRouteCoder: |
| 118 | panic(errCoderModeRequest) |
| 119 | } |
| 120 | return false |
| 121 | case userInput == "/reload": |
| 122 | // Handled here (not in the route table) so the per-command ctx flows |
nothing calls this directly
no test coverage detected