|
4 | 4 | "context" |
5 | 5 | "encoding/json" |
6 | 6 | "fmt" |
| 7 | + "io" |
7 | 8 | "log/slog" |
8 | 9 | "os" |
9 | 10 | "os/exec" |
@@ -111,39 +112,56 @@ func (c *ClaudeCLI) Prompt(ctx context.Context, sessionID string, text string) ( |
111 | 112 | cmd.Stdin = strings.NewReader(text) |
112 | 113 | cmd.Env = os.Environ() |
113 | 114 |
|
| 115 | + // Capture stdout via pipe so we can track the process for cancellation |
| 116 | + stdout, err := cmd.StdoutPipe() |
| 117 | + if err != nil { |
| 118 | + return &PromptResult{StopReason: StopFailed, Summary: fmt.Sprintf("stdout pipe: %v", err)}, nil |
| 119 | + } |
| 120 | + |
114 | 121 | slog.Info("claude CLI executing", |
115 | 122 | "session_id", sessionID, |
116 | 123 | "model", c.model, |
117 | 124 | "perm_mode", c.permMode, |
118 | 125 | "prompt_len", len(text), |
119 | 126 | ) |
120 | 127 |
|
121 | | - // Track the process for cancellation |
| 128 | + if err := cmd.Start(); err != nil { |
| 129 | + return &PromptResult{StopReason: StopFailed, Summary: fmt.Sprintf("start: %v", err)}, nil |
| 130 | + } |
| 131 | + |
| 132 | + // Track the process for cancellation AFTER start |
122 | 133 | c.mu.Lock() |
123 | | - c.proc = nil |
| 134 | + c.proc = cmd.Process |
124 | 135 | c.mu.Unlock() |
125 | 136 |
|
126 | | - // Capture stdout and stderr |
127 | | - output, err := cmd.Output() |
| 137 | + // Read all output |
| 138 | + output, readErr := io.ReadAll(stdout) |
| 139 | + |
| 140 | + // Wait for process to finish |
| 141 | + waitErr := cmd.Wait() |
128 | 142 |
|
129 | 143 | c.mu.Lock() |
130 | 144 | c.proc = nil |
131 | 145 | c.mu.Unlock() |
132 | 146 |
|
133 | | - if err != nil { |
134 | | - // Get stderr from the ExitError |
| 147 | + if readErr != nil { |
| 148 | + slog.Error("claude CLI read failed", "session_id", sessionID, "error", readErr) |
| 149 | + return &PromptResult{StopReason: StopFailed, Summary: fmt.Sprintf("read: %v", readErr)}, nil |
| 150 | + } |
| 151 | + |
| 152 | + if waitErr != nil { |
135 | 153 | var stderr string |
136 | | - if exitErr, ok := err.(*exec.ExitError); ok { |
| 154 | + if exitErr, ok := waitErr.(*exec.ExitError); ok { |
137 | 155 | stderr = string(exitErr.Stderr) |
138 | 156 | } |
139 | 157 | slog.Error("claude CLI failed", |
140 | 158 | "session_id", sessionID, |
141 | | - "error", err, |
| 159 | + "error", waitErr, |
142 | 160 | "stderr", stderr, |
143 | 161 | ) |
144 | 162 | return &PromptResult{ |
145 | 163 | StopReason: StopFailed, |
146 | | - Summary: fmt.Sprintf("claude CLI error: %v\n%s", err, stderr), |
| 164 | + Summary: fmt.Sprintf("claude CLI error: %v\n%s", waitErr, stderr), |
147 | 165 | }, nil |
148 | 166 | } |
149 | 167 |
|
|
0 commit comments