> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Progresso Live dos Agents

> Display em tempo real do status de cada agent durante execução paralela: progresso, conclusoes, erros e replanejamentos — tudo visivel no terminal.

Quando o dispatcher executa múltiplos agents em paralelo, o terminal exibe um **painel de progresso em tempo real** que mostra o estado de cada agent individualmente. Isso elimina a incerteza de "sera que ainda está rodando?" sem precisar consultar logs.

## O Que Você Ve

Durante a execução paralela, o terminal renderiza um display multi-linha atualizado a cada **100ms**:

```text theme={"system"}
⋮ [claude-sonnet-4-6] [14s] [████████░░░░░░░░░░░░] 2/4 agents (50%)
  ✓ [file]   Read all .go files in pkg/coder/engine/ ─ concluido (2.1s)
  ⋯ [search] Find references to handleRead and... ─ executando...
  ✗ [shell]  Run lint on modified files ─ falhou (1.3s) exit code 1
  ○ [coder]  Refactor read/write separation ─ pendente
```

### Elementos do Display

| Elemento            | Descrição                                               |
| ------------------- | ------------------------------------------------------- |
| Spinner (`⋮ ⋯ ⋰ ⋱`) | Animacao rotativa confirmando que o processo está ativo |
| `[modelo]`          | Provedor/modelo LLM em uso pelos workers                |
| `[tempo]`           | Tempo total decorrido desde o início do dispatch        |
| Barra de progresso  | Representacao visual da porcentagem concluida           |
| `N/M agents (X%)`   | Contagem e porcentagem de agents finalizados            |

### Icones de Status por Agent

| Icone | Status     | Descrição                                                |
| ----- | ---------- | -------------------------------------------------------- |
| `○`   | Pendente   | Agent aguardando slot no semaforo (max workers atingido) |
| `⋯`   | Executando | Agent em execução ativa (spinner animado)                |
| `✓`   | Concluido  | Agent finalizou com sucesso (mostra duracao)             |
| `✗`   | Falhou     | Agent finalizou com erro (mostra duracao + mensagem)     |

***

## Arquitetura Interna

O sistema de progresso live usa **3 goroutines independentes** comunicando via estado compartilhado protegido por mutex:

```text theme={"system"}
┌─────────────────────────┐
│  Worker Goroutines (N×) │   Goroutines do dispatcher
│  executeAgent()         │   Cada agent roda isolado
│                         │
│  Ao iniciar/terminar    │──── envia AgentEvent ────┐
└─────────────────────────┘                          │
                                                     ▼
                                        ┌────────────────────────┐
                                        │  Goroutine Consumer    │
                                        │  for evt := range      │
                                        │      progressCh        │
                                        │                        │
                                        │  MarkStarted()         │
                                        │  MarkCompleted()       │──── escreve ────┐
                                        │  MarkFailed()          │   (com mutex)   │
                                        └────────────────────────┘                 │
                                                                                   ▼
                                                                   ┌──────────────────────┐
┌─────────────────────────┐                                        │  AgentProgressState  │
│  Timer Goroutine        │                                        │  (thread-safe)       │
│  Ticker a cada 100ms    │──── le estado ────────────────────────►│                      │
│                         │     e renderiza                        │  Agents[0]: Running  │
│  FormatDispatchProgress │◄──── snapshot com mutex ───────────────│  Agents[1]: Complete │
│  ()                     │                                        │  Agents[2]: Failed   │
└─────────────────────────┘                                        │  Agents[3]: Pending  │
                                                                   └──────────────────────┘
```

### Fluxo Detalhado

<Steps>
  <Step title="Inicializacao">
    O `agent_mode.go` cria um `AgentProgressState` com N slots (um por agent) e um channel `progressCh` com buffer `N×2`.
  </Step>

  <Step title="Goroutine Consumer">
    Uma goroutine dedicada consome eventos do `progressCh` e atualiza o estado compartilhado via métodos `Mark*()` protegidos por mutex.
  </Step>

  <Step title="Timer Display">
    O `turnTimer` inicia com um callback que, a cada 100ms:

    1. Limpa as linhas anteriores do terminal (`ClearLines`)
    2. Le o `AgentProgressState` (adquirindo o mutex)
    3. Renderiza o display multi-linha atualizado
  </Step>

  <Step title="Dispatch com Eventos">
    O `DispatchWithProgress()` executa os agents e envia `AgentEvent` no channel conforme cada agent inicia e termina.
  </Step>

  <Step title="Finalizacao">
    Após todos os agents terminarem, o timer para, o display e limpo, e os resultados finais são renderizados como cards do timeline.
  </Step>
</Steps>

***

## Tipos de Evento

O dispatcher emite tres tipos de evento via o channel de progresso:

```go theme={"system"}
type AgentEventType int

const (
    AgentEventStarted   AgentEventType = iota  // agent comecou a executar
    AgentEventCompleted                        // agent finalizou com sucesso
    AgentEventFailed                           // agent finalizou com erro
)
```

Cada evento carrega contexto completo:

```go theme={"system"}
type AgentEvent struct {
    Type     AgentEventType
    CallID   string         // ID único do agent call (ac-1, ac-2...)
    Agent    AgentType      // tipo do agent (file, coder, shell...)
    Task     string         // descrição da tarefa
    Duration time.Duration  // tempo de execução (apenas em Completed/Failed)
    Error    error          // erro (apenas em Failed)
    Index    int            // posicao no batch (0-based)
    Total    int            // total de agents no batch
}
```

***

## Thread Safety

O `AgentProgressState` e acessado concorrentemente por duas goroutines:

1. **Consumer goroutine** — escreve (via `MarkStarted`, `MarkCompleted`, `MarkFailed`)
2. **Timer goroutine** — le (via `FormatDispatchProgress`)

A sincronizacao e feita por um `sync.Mutex` interno:

```go theme={"system"}
type AgentProgressState struct {
    mu        sync.Mutex
    Total     int
    Agents    []AgentSlot
    StartTime time.Time
}
```

Cada método publico adquire o mutex antes de ler ou escrever. O `FormatDispatchProgress` também adquire o mutex e faz um snapshot completo do estado antes de formatar a string de saida.

<Warning>O channel `progressCh` usa buffer de `N×2` (onde N = número de agents) para evitar que workers bloqueiem ao enviar eventos caso o consumer esteja momentaneamente ocupado.</Warning>

***

## Renderizacao do Terminal

O display multi-linha usa **escape sequences ANSI** para atualizar o terminal in-place:

| Operação       | Escape Sequence     | Descrição                                |
| -------------- | ------------------- | ---------------------------------------- |
| Limpar linha   | `\r\033[K`          | Retorna ao início e apaga a linha        |
| Subir N linhas | `\033[A\033[K` (×N) | Move cursor para cima e limpa cada linha |

A cada tick do timer (100ms), o callback:

1. Emite `ClearLines(prevLines)` para apagar o display anterior
2. Chama `FormatDispatchProgress()` que retorna a string multi-linha atualizada
3. Imprime a nova string
4. Atualiza `prevLines` para o próximo ciclo

<Info>A latência máxima entre um evento de mudanca e sua exibicao no terminal e de **100ms** — imperceptivel para o usuário.</Info>

***

## Interação com Policy Prompts

Quando um worker precisa de aprovação de segurança (policy "ask"), o sistema:

1. **Pausa o timer** — o display de progresso para de atualizar
2. **Exibe o prompt de segurança** — com contexto do agent
3. **Após resposta** — resume o timer e o display continua atualizando

Isso evita que o spinner e o prompt de segurança se sobreponham no terminal.

***

## Spinner labels per-call (DescribeCall)

A linha do spinner usa o método `DescribeCall(args)` de cada plugin quando disponível, surfaceando o **alvo concreto** da operação em vez de uma label genérica. Comparação:

| Plugin        | Antes                         | Depois                                  |
| ------------- | ----------------------------- | --------------------------------------- |
| `@read`       | `EXECUTANDO: @read read`      | `Reading: main.go`                      |
| `@search`     | `EXECUTANDO: @search search`  | `Searching: golang errgroup`            |
| `@webfetch`   | `EXECUTANDO: @webfetch fetch` | `Fetching: https://api.example.com/...` |
| `@coder exec` | `EXECUTANDO: @coder exec`     | `Executing: go test ./...`              |

Plugins legados que não implementam `DescriberWithInput` continuam mostrando o fallback `EXECUTANDO: <tool> <subcmd>` (locale-resolved, vira `RUNNING:` em en).

Os tools de ação/multimodais (`@send`, `@moa`, `@osv`, `@session`, `@speak`, `@image`, `@skill`) implementam `DescribeCall`, então a caixa mostra um label conciso (ex.: `🎨 Gerando imagem: a watercolor fox`) em vez da descrição longa do tool.

### Spinner animado durante a execução

Tools que esperam I/O de rede (`@moa`, `@image`, `@speak`, `@webfetch`, `@websearch`, `@osv`, `@send`…) exibiam uma caixa estática — sensação de travado. Agora o loop do agente roda o **spinner braille animado** (`⠋⠙⠹…`) **enquanto o tool executa**, com o label do `DescribeCall`. Comportamento:

* **Tool bloqueante** (rede): o spinner anima até o retorno.
* **Tool que faz stream** (ex.: `@coder exec`): o spinner para na **primeira linha** de saída e o output flui normal (sem conflito com o repaint por carriage-return).
* Fora de TTY (gateway/daemon), o spinner é suprimido automaticamente.

***

## Indicador de fila de mensagens (mid-turn)

Durante o turn do agente o spinner exibe `(N na fila)` quando há mensagens enfileiradas pelo usuário. O contador soma:

* Mensagens completadas (Enter pressionado) ainda não drenadas pro `messageQueue`
* Mensagens que já caíram no `messageQueue` aguardando o próximo turn

Resultado: pressionar Enter durante o stream do LLM atualiza o indicador **imediatamente** em vez de esperar o turn fechar.

```text theme={"system"}
⠋ claude-opus [1m12s] | Processando... (1 na fila)
```

Funciona tanto em `/agent` quanto em `/coder` (antes só funcionava em `/agent`).

***

## Ciclo de Vida Completo

```text theme={"system"}
[Antes do dispatch]
╭── 🚀 MULTI-AGENT DISPATCH
│  Dispatching 4 agents
╰────────────────────────

╭── 🤖 [file] #1
│  Read all .go files in pkg/coder/engine/
╰────────────────────────

╭── 🤖 [search] #2
│  Find references to handleRead and handleWrite
╰────────────────────────

[Durante o dispatch — atualizado a cada 100ms]
⋮ [claude-sonnet-4-6] [3s] [░░░░░░░░░░░░░░░░░░░░] 0/4 agents (0%)
  ⋯ [file]   Read all .go files in pkg/coder/... ─ executando...
  ⋯ [search] Find references to handleRead... ─ executando...
  ○ [shell]  Run lint on modified files ─ pendente
  ○ [coder]  Refactor read/write separation ─ pendente

... 5 segundos depois ...

⋰ [claude-sonnet-4-6] [8s] [██████████░░░░░░░░░░] 2/4 agents (50%)
  ✓ [file]   Read all .go files in pkg/coder/... ─ concluido (2.1s)
  ✓ [search] Find references to handleRead... ─ concluido (4.8s)
  ⋯ [shell]  Run lint on modified files ─ executando...
  ⋯ [coder]  Refactor read/write separation ─ executando...

... finalizado ...

[Após o dispatch — cards de resultado]
╭── ✅ [file] OK (2.1s, 3 tool calls)
│  Files read: engine.go, reader.go, writer.go
╰────────────────────────

╭── ✅ [search] OK (4.8s, 5 tool calls)
│  Found 12 references across 4 files
╰────────────────────────

╭── ❌ [shell] FAILED
│  exit code 1: unused variable 'tmp' in engine.go:42
╰────────────────────────

╭── ✅ [coder] OK (12.3s, 8 tool calls, 3 em paralelo)
│  Refactored read/write into separate files
╰────────────────────────

╭── 📊 RESUMO
│  3/4 agents concluidos | 16 tool calls executadas | 3 goroutines paralelas | 14.1s total
╰────────────────────────
```

***

## Componentes de Código

| Componente                      | Arquivo                           | Responsabilidade                            |
| ------------------------------- | --------------------------------- | ------------------------------------------- |
| `AgentEvent` / `AgentEventType` | `cli/agent/workers/types.go`      | Tipos de evento de progresso                |
| `DispatchWithProgress()`        | `cli/agent/workers/dispatcher.go` | Dispatcher que emite eventos via channel    |
| `AgentProgressState`            | `cli/metrics/display.go`          | Estado thread-safe de cada agent            |
| `FormatDispatchProgress()`      | `cli/metrics/display.go`          | Renderizacao do display multi-linha         |
| `ClearLines()`                  | `cli/metrics/display.go`          | Limpeza de linhas do terminal               |
| Integração                      | `cli/agent_mode.go`               | Orquestracao do consumer + timer + dispatch |

***

## Comparacao: Antes vs Depois

<Tabs>
  <Tab title="Antes (Spinner Estatico)">
    ```text theme={"system"}
    ⋮ [claude-sonnet-4-6] [32s] Aguardando 4 agents...

    (Nenhuma informação sobre:
     - Qual agent está rodando
     - Qual já terminou
     - Se houve erro
     - Quanto falta)
    ```

    O usuário só sabia que algo estava acontecendo pelo spinner girando. Para confirmar que os agents estavam de fato rodando, precisava abrir os logs do ChatCLI em outro terminal.
  </Tab>

  <Tab title="Depois (Progresso Live)">
    ```text theme={"system"}
    ⋰ [claude-sonnet-4-6] [14s] [████████░░░░░░░░░░░░] 2/4 agents (50%)
      ✓ [file]   Read all .go files... ─ concluido (2.1s)
      ✓ [search] Find references... ─ concluido (4.8s)
      ⋯ [shell]  Run lint... ─ executando...
      ○ [coder]  Refactor read/write... ─ pendente
    ```

    O usuário ve em tempo real:

    * Barra de progresso com porcentagem
    * Status individual de cada agent
    * Duracao de cada agent concluido
    * Erros imediatos com mensagem
    * Tempo total decorrido
  </Tab>
</Tabs>
