startProcessingLifecycle suppresses the foreground animation (so it never fights go-prompt's prefix), starts the prompt-prefix spinner goroutine, and flips the executing flag. The returned stopSpinner closure is safe to call multiple times and must be invoked once the LLM acknowledges the request so
()
| 76 | // call multiple times and must be invoked once the LLM acknowledges the |
| 77 | // request so the prefix stops animating before we render output. |
| 78 | func (cli *ChatCLI) startProcessingLifecycle() func() { |
| 79 | cli.animation.SetSuppressed(true) |
| 80 | |
| 81 | spinnerDone := make(chan struct{}) |
| 82 | var spinnerStopped atomic.Bool |
| 83 | stopSpinner := func() { |
| 84 | if spinnerStopped.CompareAndSwap(false, true) { |
| 85 | close(spinnerDone) |
| 86 | atomic.StoreInt32(&cli.prefixSpinnerIdx, 0) |
| 87 | } |
| 88 | } |
| 89 | if runtime.GOOS != "windows" { |
| 90 | go cli.runPrefixSpinner(spinnerDone) |
| 91 | } |
| 92 | cli.isExecuting.Store(true) |
| 93 | return stopSpinner |
| 94 | } |
| 95 | |
| 96 | // runPrefixSpinner ticks the prefix-spinner counter and forces a prompt |
| 97 | // redraw at ~4 Hz until spinnerDone closes. Exits cleanly on shutdown. |