story-kit: create 147_bug_activity_indicator_still_only_shows_thinking_despite_bug_140_fix

This commit is contained in:
Dave
2026-02-24 13:59:21 +00:00
parent 41d86d29d0
commit 1116e4a882

View File

@@ -6,17 +6,50 @@ name: "Activity indicator still only shows Thinking despite bug 140 fix"
## Description
Bug 140 fixed the frontend display condition but activity labels still never appear. The likely root cause is that Claude Code stream-json PTY output does not emit raw Anthropic API format events (content_block_start with type tool_use) inside stream_event wrappers. The handle_stream_event function in server/src/llm/providers/claude_code.rs line 486 only matches content_block_start, which is the Anthropic streaming API format. Claude Code CLI stream-json may use a different event structure for tool calls.
Bug 140 fixed the frontend display condition but activity labels still never appear. The full data path has been traced and the suspected failure point identified.
Investigation needed:
1. Add temporary logging in process_json_event (line 327) to dump all event types received from the PTY
2. Determine the actual event format Claude Code uses for tool calls in stream-json mode
3. Add matching for that format in handle_stream_event or process_json_event to fire activity_tx
## End-to-End Data Path
Key files:
- server/src/llm/providers/claude_code.rs line 327: process_json_event
- server/src/llm/providers/claude_code.rs line 486: handle_stream_event
- server/src/http/ws.rs line 251: activity callback wiring
### 1. Frontend display (FIXED by bug 140)
- `frontend/src/components/Chat.tsx` line 686: `{loading && (activityStatus != null || !streamingContent) && (`
- `frontend/src/components/Chat.tsx` line 697: `{activityStatus ?? "Thinking..."}`
- `frontend/src/components/Chat.tsx` line 204: `setActivityStatus(formatToolActivity(toolName))` — called by `onActivity` callback
### 2. WebSocket client receives event
- `frontend/src/api/client.ts` line 350: `if (data.type === "tool_activity") this.onActivity?.(data.tool_name)`
### 3. Server sends ToolActivity over WebSocket (WIRED CORRECTLY)
- `server/src/http/ws.rs` line 251-254: activity callback sends `WsResponse::ToolActivity { tool_name }`
- This callback is passed to `chat::chat()` as the `on_activity` closure
### 4. chat::chat passes callback to Claude Code provider
- `server/src/llm/chat.rs`: passes `on_activity` through to `claude_code::chat_stream`
- `server/src/llm/providers/claude_code.rs` line 47: `mut on_activity: A` parameter
- `server/src/llm/providers/claude_code.rs` line 70: creates internal `activity_tx` channel
- `server/src/llm/providers/claude_code.rs` line 94: drains channel and calls `on_activity(&name)`
### 5. PTY event processing (SUSPECTED FAILURE POINT)
- `server/src/llm/providers/claude_code.rs` line 327: `process_json_event()` dispatches parsed JSON
- Line 348-353: matches `"stream_event"` type → extracts inner `event` → calls `handle_stream_event()`
- `server/src/llm/providers/claude_code.rs` line 486: `handle_stream_event()` matches on event type
- Line 494-500: matches `"content_block_start"` with `content_block.type == "tool_use"` → sends to `activity_tx`
### 6. The problem
`handle_stream_event` only matches `content_block_start` — this is the **raw Anthropic streaming API format**. But Claude Code's `--output-format stream-json` may NOT emit raw Anthropic events wrapped in `stream_event`. It likely uses its own event types for tool calls (e.g. `tool_use_begin`, `tool_use`, or similar).
The existing `process_json_event` also matches `"assistant"` (line 355) and `"user"` (line 363) event types from stream-json, but these are complete messages — they arrive after the tool call is done, not when it starts. So there's no event being caught at tool-call-start time.
## Investigation Steps
1. Add logging in `process_json_event` (line 334) to print every `event_type` received from the PTY during a chat session with tool use
2. Identify which event type Claude Code emits when it starts a tool call
3. Add matching for that event type to fire `activity_tx.send(tool_name)`
## Key Files
- `server/src/llm/providers/claude_code.rs` line 327: `process_json_event` — event dispatcher
- `server/src/llm/providers/claude_code.rs` line 486: `handle_stream_event` — only handles Anthropic API format
- `server/src/http/ws.rs` line 251: activity callback wiring to WebSocket
- `frontend/src/components/Chat.tsx` line 203: `onActivity` handler that sets display state
## How to Reproduce
@@ -27,7 +60,7 @@ Key files:
## Actual Result
Indicator always shows Thinking and never changes to tool activity labels like Reading file or Executing command
Indicator always shows "Thinking..." and never changes to tool activity labels like "Reading file..." or "Executing command..."
## Expected Result
@@ -35,4 +68,6 @@ Indicator should cycle through tool activity labels as the agent calls tools
## Acceptance Criteria
- [ ] Bug is fixed and verified
- [ ] Activity indicator shows tool names (e.g. "Reading file...", "Executing command...") when the web UI agent calls tools
- [ ] Indicator still falls back to "Thinking..." when no tool activity is in progress
- [ ] Works for all tool types (Read, Write, Bash, Glob, Grep, etc.)