PrintToolCallWithConfirmation prints a tool call and prompts for confirmation
(ctx context.Context, toolCall tools.ToolCall, rd io.Reader)
| 89 | |
| 90 | // PrintToolCallWithConfirmation prints a tool call and prompts for confirmation |
| 91 | func (p *Printer) PrintToolCallWithConfirmation(ctx context.Context, toolCall tools.ToolCall, rd io.Reader) ConfirmationResult { |
| 92 | p.Printf("\n%s\n", bold("🛠️ Tool call requires confirmation 🛠️")) |
| 93 | p.PrintToolCall(toolCall) |
| 94 | p.Printf("\n%s", bold("Can I run this tool? ([y]es/[a]ll/[n]o): ")) |
| 95 | |
| 96 | if !isatty.IsTerminal(os.Stdout.Fd()) { |
| 97 | return ConfirmationReject |
| 98 | } |
| 99 | |
| 100 | // Try single-character input from stdin in raw mode (no Enter required) |
| 101 | fd := int(os.Stdin.Fd()) |
| 102 | if oldState, err := term.MakeRaw(fd); err == nil { |
| 103 | defer func() { |
| 104 | if err := term.Restore(fd, oldState); err != nil { |
| 105 | p.Printf("\nFailed to restore terminal state: %v\n", err) |
| 106 | } |
| 107 | }() |
| 108 | buf := make([]byte, 1) |
| 109 | for { |
| 110 | if _, err := os.Stdin.Read(buf); err != nil { |
| 111 | break |
| 112 | } |
| 113 | switch buf[0] { |
| 114 | case 'y', 'Y': |
| 115 | p.Print(bold("Yes 👍")) |
| 116 | return ConfirmationApprove |
| 117 | case 'a', 'A': |
| 118 | p.Print(bold("Yes to all 👍")) |
| 119 | return ConfirmationApproveSession |
| 120 | case 'n', 'N': |
| 121 | p.Print(bold("No 👎")) |
| 122 | return ConfirmationReject |
| 123 | case 3: // Ctrl+C |
| 124 | return ConfirmationAbort |
| 125 | case '\r', '\n': |
| 126 | // ignore |
| 127 | default: |
| 128 | // ignore other keys |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | // Fallback: line-based scanner (requires Enter) |
| 134 | text, err := input.ReadLine(ctx, rd) |
| 135 | if err != nil { |
| 136 | return ConfirmationReject |
| 137 | } |
| 138 | |
| 139 | switch text { |
| 140 | case "y": |
| 141 | return ConfirmationApprove |
| 142 | case "a": |
| 143 | return ConfirmationApproveSession |
| 144 | case "n": |
| 145 | return ConfirmationReject |
| 146 | default: |
| 147 | // Default to reject for invalid input |
| 148 | return ConfirmationReject |
no test coverage detected