Merge pull request #7 from VictorVargas/fix/stream-tool-call-visibility

fix(agent): RunStream never surfaced tool calls to callers
This commit is contained in:
Victor Hugo Vargas Servin 2026-07-10 00:10:39 -07:00 committed by GitHub
commit eea51e30d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 4 deletions

View file

@ -205,6 +205,19 @@ func (l *Loop) RunStream(ctx context.Context, input string, history ...llm.Messa
Content: result.Content,
})
}
// Surface which tools were actually called, and with
// what arguments, to the caller — a dedicated chunk,
// separate from the content-streaming gate below, since
// that gate exists to hide raw provider deltas during a
// tool-call round, not to hide the fact that a call
// happened at all. Without this, callers (e.g. a UI
// wanting to show "used tool X" or track which files a
// write/edit touched) have no way to observe tool
// calls unless they also happen to be the Approver.
if !yield(llm.StreamChunk{ToolCalls: chunk.ToolCalls}, nil) {
return
}
}
// A trailing usage-only chunk (no Delta/ReasoningDelta, per

View file

@ -669,11 +669,17 @@ func TestRun_Stream_WithToolCalls(t *testing.T) {
chunks = append(chunks, chunk)
}
if len(chunks) != 1 {
t.Errorf("expected 1 chunk (only the 'done' chunk), got %d", len(chunks))
// One chunk surfacing the tool call itself (so callers can observe
// which tools ran and with what arguments), then the final "done"
// content chunk.
if len(chunks) != 2 {
t.Fatalf("expected 2 chunks (tool call + 'done'), got %d: %+v", len(chunks), chunks)
}
if chunks[0].Delta != "done" {
t.Errorf("expected 'done', got %q", chunks[0].Delta)
if len(chunks[0].ToolCalls) != 1 || chunks[0].ToolCalls[0].Name != "greet" {
t.Errorf("expected the first chunk to surface the 'greet' tool call, got %+v", chunks[0].ToolCalls)
}
if chunks[1].Delta != "done" {
t.Errorf("expected 'done', got %q", chunks[1].Delta)
}
}