(msg tea.Msg)
| 249 | } |
| 250 | |
| 251 | func (m harness) Update(msg tea.Msg) (tea.Model, tea.Cmd) { |
| 252 | switch msg := msg.(type) { |
| 253 | case tea.WindowSizeMsg: |
| 254 | m.width = msg.Width |
| 255 | m.height = msg.Height |
| 256 | m.layout() |
| 257 | // Re-wrap the conversation scrollback to the new viewport width. |
| 258 | // Without this, lines wrapped at the old width stay that way after |
| 259 | // a resize — fine when the terminal grew, ugly when it shrank. |
| 260 | m.setConversationContent() |
| 261 | // Re-wrap the debug panel/modal to the new size. Cheap and matters |
| 262 | // most for detail mode, where lines were wrapped at the old width. |
| 263 | if debug.Enabled() { |
| 264 | m.refreshDebugContent() |
| 265 | } |
| 266 | if m.followBottom { |
| 267 | m.viewport.GotoBottom() |
| 268 | } |
| 269 | return m, nil |
| 270 | |
| 271 | case DebugToggleMsg: |
| 272 | m.layout() |
| 273 | if !debug.Enabled() { |
| 274 | // Panel was just turned off — return focus to input and reset |
| 275 | // detail mode so it's not lingering when we re-enable later. |
| 276 | m.debugFocus = false |
| 277 | m.debugMode = debugList |
| 278 | m.input.Focus() |
| 279 | } |
| 280 | m.refreshDebugContent() |
| 281 | if m.followBottom { |
| 282 | m.viewport.GotoBottom() |
| 283 | } |
| 284 | return m, nil |
| 285 | |
| 286 | case DebugRefreshMsg: |
| 287 | if debug.Enabled() { |
| 288 | m.refreshDebugContent() |
| 289 | } |
| 290 | return m, nil |
| 291 | |
| 292 | case MCPStatusMsg: |
| 293 | switch msg.Status { |
| 294 | case mcp.ProgressBegin: |
| 295 | if msg.Total == 0 { |
| 296 | return m, nil |
| 297 | } |
| 298 | m.mcpLoading = true |
| 299 | m.mcpTotal = msg.Total |
| 300 | m.mcpDone = 0 |
| 301 | m.mcpFailed = 0 |
| 302 | m.mcpCurrent = "" |
| 303 | // Kick the spinner so the loading line animates. |
| 304 | return m, m.spinner.Tick |
| 305 | case mcp.ProgressConnecting: |
| 306 | m.mcpCurrent = msg.Server |
| 307 | case mcp.ProgressConnected: |
| 308 | m.mcpDone++ |
no test coverage detected