runSingleCommand executes one command from a non-script block, handling cd changes, dangerous-command confirmation, and interactive detection.
(ctx context.Context, block agent.CommandBlock, renderer *agent.UIRenderer, i int, cmd string, allOutput *strings.Builder, lastError *string)
| 800 | // runSingleCommand executes one command from a non-script block, handling |
| 801 | // cd changes, dangerous-command confirmation, and interactive detection. |
| 802 | func (a *AgentMode) runSingleCommand(ctx context.Context, block agent.CommandBlock, renderer *agent.UIRenderer, i int, cmd string, allOutput *strings.Builder, lastError *string) { |
| 803 | if cmd == "" { |
| 804 | return |
| 805 | } |
| 806 | |
| 807 | trimmed := strings.TrimSpace(cmd) |
| 808 | |
| 809 | if strings.HasPrefix(trimmed, "cd ") || trimmed == "cd" { |
| 810 | a.runChangeDir(trimmed, allOutput, lastError) |
| 811 | return |
| 812 | } |
| 813 | |
| 814 | if a.validator.IsDangerous(trimmed) { |
| 815 | confirmPrompt := i18n.T("agent.status.dangerous_command_confirm") |
| 816 | confirm := a.getCriticalInput(confirmPrompt) |
| 817 | if confirm != "sim, quero executar conscientemente" { |
| 818 | outText := i18n.T("agent.status.dangerous_command_aborted") + "\n" |
| 819 | fmt.Print(renderer.Colorize(outText, agent.ColorYellow)) |
| 820 | allOutput.WriteString(outText) |
| 821 | return |
| 822 | } |
| 823 | fmt.Println(renderer.Colorize(i18n.T("agent.status.dangerous_command_confirmed"), agent.ColorYellow)) |
| 824 | } |
| 825 | |
| 826 | header := i18n.T("agent.status.executing_command_n", i+1, len(block.Commands), trimmed) + "\n" |
| 827 | fmt.Print(header) |
| 828 | allOutput.WriteString(header) |
| 829 | |
| 830 | isInteractive := false |
| 831 | if strings.HasSuffix(trimmed, " --interactive") { |
| 832 | trimmed = strings.TrimSuffix(trimmed, " --interactive") |
| 833 | isInteractive = true |
| 834 | } else if strings.Contains(trimmed, "#interactive") { |
| 835 | trimmed = strings.ReplaceAll(trimmed, "#interactive", "") |
| 836 | trimmed = strings.TrimSpace(trimmed) |
| 837 | isInteractive = true |
| 838 | } else { |
| 839 | isInteractive = a.validator.IsLikelyInteractive(trimmed) |
| 840 | } |
| 841 | |
| 842 | if !isInteractive && mightBeInteractive(trimmed, block.ContextInfo) { |
| 843 | isInteractive = a.askUserIfInteractive(trimmed, block.ContextInfo) |
| 844 | } |
| 845 | |
| 846 | if isInteractive { |
| 847 | outText := i18n.T("agent.status.interactive_mode") + "\n" |
| 848 | fmt.Print(renderer.Colorize(outText, agent.ColorGray)) |
| 849 | allOutput.WriteString(outText) |
| 850 | |
| 851 | time.Sleep(1 * time.Second) |
| 852 | |
| 853 | result, err := a.executor.Execute(ctx, trimmed, true) |
| 854 | |
| 855 | if err != nil { |
| 856 | errMsg := fmt.Sprintf("❌ Erro: %v\n", err) |
| 857 | fmt.Print(errMsg) |
| 858 | allOutput.WriteString(errMsg) |
| 859 | *lastError = err.Error() |
no test coverage detected