# Refatoração Frontend — SSE Tool Call Events

## O que mudou

A API SSE de chat agora emite **3 novos tipos de evento** que permitem ao frontend mostrar o que a IA está fazendo em tempo real: quais ferramentas está chamando, quanto tempo levou, e o resultado resumido.

### Eventos SSE (antes → depois)

| Antes | Depois |
|---|---|
| `chunk` | `chunk` (igual) |
| `done` (`messageId`, `sessionId`, `tokenCount`) | `done` (`sessionId`) |
| `error` (`code`, `message`) | `error` (`message`) |
| — | **`tool_call_start`** (`tool`) |
| — | **`tool_call_end`** (`tool`, `durationMs`, `resultSummary`) |
| — | **`thinking`** (`message`) |

### Exemplo de stream com tool calling

```
data: {"type":"tool_call_start","tool":"searchFunctions"}

data: {"type":"tool_call_end","tool":"searchFunctions","durationMs":23,"resultSummary":"5 results: sub_401000, ..."}

data: {"type":"tool_call_start","tool":"getFunctionAssembly"}

data: {"type":"tool_call_end","tool":"getFunctionAssembly","durationMs":15,"resultSummary":"sub_401000 at 0x00401000"}

data: {"type":"chunk","content":"A função"}

data: {"type":"chunk","content":" sub_401000..."}

data: {"type":"done","sessionId":"550e8400-..."}
```

## Passo a passo da refatoração

### 1. Adicionar estado `toolStatus`

No hook `useChatSession`, adicione um novo estado para rastrear o status da tool em execução:

```typescript
// Antes
const [streamingContent, setStreamingContent] = useState('');
const [isStreaming, setIsStreaming] = useState(false);

// Depois
const [streamingContent, setStreamingContent] = useState('');
const [isStreaming, setIsStreaming] = useState(false);
const [toolStatus, setToolStatus] = useState<string | null>(null);
```

### 2. Atualizar o parser de eventos SSE

Substitua o bloco `if/else` por um `switch` que trate todos os tipos de evento:

```typescript
// Antes
if (event.type === 'chunk') {
  fullContent += event.content;
  setStreamingContent(fullContent);
} else if (event.type === 'done') {
  setIsStreaming(false);
  await loadMessages(activeSessionId);
} else if (event.type === 'error') {
  setIsStreaming(false);
  throw new Error(event.message);
}

// Depois
switch (event.type) {
  case 'chunk':
    fullContent += event.content;
    setStreamingContent(fullContent);
    break;
  case 'tool_call_start':
    setToolStatus(`Calling ${event.tool}...`);
    break;
  case 'tool_call_end':
    setToolStatus(
      `${event.tool} completed (${event.durationMs}ms): ${event.resultSummary}`
    );
    break;
  case 'thinking':
    setToolStatus(event.message);
    break;
  case 'done':
    setIsStreaming(false);
    setToolStatus(null);
    await loadMessages(activeSessionId);
    break;
  case 'error':
    setIsStreaming(false);
    setToolStatus(null);
    throw new Error(event.message);
}
```

### 3. Exibir indicador de tool status na UI

Adicione um elemento visual que mostre o `toolStatus` enquanto a IA está processando. Posicione-o entre as mensagens do histórico e o streaming content:

```tsx
// No componente ChatWindow, entre as mensagens do histórico e o streaming:

{toolStatus && (
  <div className="tool-status">
    <span className="spinner" /> {toolStatus}
  </div>
)}

{isStreaming && (
  <MessageBubble role="ASSISTANT" content={streamingContent} isStreaming />
)}
```

Prop do componente:

```typescript
// Adicione toolStatus nas props:
function ChatWindow({
  messages,
  streamingContent,
  isStreaming,
  toolStatus,          // ← nova prop
  onSend,
  onCancel,
}: {
  messages: ChatMessage[];
  streamingContent: string;
  isStreaming: boolean;
  toolStatus: string | null;  // ← nova
  onSend: (content: string) => void;
  onCancel: () => void;
})
```

### 4. Resetar toolStatus ao cancelar

```typescript
const cancelStream = () => {
  abortRef.current?.abort();
  setIsStreaming(false);
  setToolStatus(null);  // ← adicionar
};
```

### 5. (Opcional) Atualizar tipagem do evento `done`

Se seu frontend tinha tipagem para o evento `done` com campos `messageId` e `tokenCount`, atualize para:

```typescript
// Antes
interface DoneEvent {
  type: 'done';
  messageId: string;
  sessionId: string;
  tokenCount: number;
}

// Depois
interface DoneEvent {
  type: 'done';
  sessionId: string;
}
```

## Resumo: o que o frontend vê em cada cenário

### Cenário 1: Pergunta simples (sem tools)
```
chunk: "Olá!"
chunk: " Como posso ajudar?"
done:  sessionId="..."
```
Comportamento: igual ao atual, sem `toolStatus` visível.

### Cenário 2: Pergunta que requer tools
```
tool_call_start: tool="searchFunctions"
                 UI mostra: "Calling searchFunctions..."

tool_call_end:   tool="searchFunctions" durationMs=23 resultSummary="5 results: sub_401000, ..."
                 UI mostra: "searchFunctions completed (23ms): 5 results: sub_401000, ..."

tool_call_start: tool="getFunctionAssembly"
                 UI mostra: "Calling getFunctionAssembly..."

tool_call_end:   tool="getFunctionAssembly" durationMs=15 resultSummary="sub_401000 at 0x00401000"
                 UI mostra: "getFunctionAssembly completed (15ms): sub_401000 at 0x00401000"

chunk: "A função"
chunk: " sub_401000..."
done:  sessionId="..."
                 toolStatus limpo, streaming content aparece
```

## CSS sugerido para `.tool-status`

```css
.tool-status {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin: 4px 0;
  font-size: 13px;
  color: #6b7280;
  background: #f3f4f6;
  border-radius: 8px;
  border-left: 3px solid #3b82f6;
}

.tool-status .spinner {
  width: 14px;
  height: 14px;
  border: 2px solid #e5e7eb;
  border-top-color: #3b82f6;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
```
