handlePlanCommand parses /plan, arms pendingPlanFirst (+ optionally pendingPlanDryRun), and tells the caller which mode to enter (if any). Returning planRouteAgent or planRouteCoder means command_handler should panic with the matching sentinel error after this returns.
(userInput string)
| 41 | // Returning planRouteAgent or planRouteCoder means command_handler |
| 42 | // should panic with the matching sentinel error after this returns. |
| 43 | func (cli *ChatCLI) handlePlanCommand(userInput string) planCommandRoute { |
| 44 | cli.pendingPlanFirst = true |
| 45 | cli.pendingPlanDryRun = false |
| 46 | |
| 47 | rest := strings.TrimSpace(strings.TrimPrefix(userInput, "/plan")) |
| 48 | if rest == "" { |
| 49 | fmt.Println(colorize(" "+i18n.T("plan.armed"), ColorGreen)) |
| 50 | return planRouteNone |
| 51 | } |
| 52 | |
| 53 | // /plan preview|dry <task> → generate plan, show it, don't execute. |
| 54 | // Runs under agent mode so the dispatcher/registry are available, but |
| 55 | // AgentMode.Run returns before the ReAct loop (see planDryRunHandled). |
| 56 | if strings.HasPrefix(rest, "preview ") || rest == "preview" || |
| 57 | strings.HasPrefix(rest, "dry ") || rest == "dry" { |
| 58 | var task string |
| 59 | switch { |
| 60 | case strings.HasPrefix(rest, "preview"): |
| 61 | task = strings.TrimSpace(strings.TrimPrefix(rest, "preview")) |
| 62 | default: |
| 63 | task = strings.TrimSpace(strings.TrimPrefix(rest, "dry")) |
| 64 | } |
| 65 | if task == "" { |
| 66 | // Without a task there's nothing to plan; keep the arm + hint. |
| 67 | fmt.Println(colorize(" "+i18n.T("plan.preview_usage"), ColorYellow)) |
| 68 | cli.pendingPlanFirst = false |
| 69 | return planRouteNone |
| 70 | } |
| 71 | cli.pendingPlanDryRun = true |
| 72 | cli.pendingAction = "agent" |
| 73 | return planRouteAgent |
| 74 | } |
| 75 | |
| 76 | // /plan coder <task> → coder mode with plan-first armed |
| 77 | if strings.HasPrefix(rest, "coder ") || rest == "coder" { |
| 78 | task := strings.TrimSpace(strings.TrimPrefix(rest, "coder")) |
| 79 | if task == "" { |
| 80 | fmt.Println(colorize(" "+i18n.T("plan.armed"), ColorGreen)) |
| 81 | return planRouteNone |
| 82 | } |
| 83 | cli.pendingAction = "coder" |
| 84 | return planRouteCoder |
| 85 | } |
| 86 | |
| 87 | // /plan <task> (or /plan agent <task>) → default: agent mode |
| 88 | cli.pendingAction = "agent" |
| 89 | return planRouteAgent |
| 90 | } |
no test coverage detected