Skip to content

feat(streaming): surface native web-search activity per chunk#290

Merged
Kamilbenkirane merged 1 commit into
mainfrom
feat/text-stream-tool-activity
Jun 19, 2026
Merged

feat(streaming): surface native web-search activity per chunk#290
Kamilbenkirane merged 1 commit into
mainfrom
feat/text-stream-tool-activity

Conversation

@Kamilbenkirane

Copy link
Copy Markdown
Member

Adds a per-chunk tool_activity signal so consumers can render native web-search progress while it happens, instead of only seeing the final Grounding on the output. Mirrors exactly how reasoning is threaded onto TextChunk (base stub + per-provider overrides + kwargs threading).

What

  • types.py: ToolActivity(BaseModel){tool_name, status} + ToolActivityStatus(StrEnum){started, completed}.
  • TextChunk gains tool_activity: ToolActivity | None.
  • base Stream._parse_chunk parses + threads it, keeping activity-only chunks (added to the all-None guard).
  • OpenResponses (OpenAI + xAI): response.web_search_call.in_progress → started, .completed → completed.
  • Anthropic: server_tool_use(web_search) → started, web_search_tool_result → completed.

Streaming-only by design — final results already live on TextOutput.grounding, so no output aggregation.

Scope / excluded (with reason)

  • Gemini — grounding is terminal-only; no in-stream signal exists. Tracked in Switch Gemini text generation from generateContent to the Interactions API #289 (Interactions API).
  • Moonshot / DeepSeek / Mistral / Groq / Perplexity — no clean in-stream native-search signal: Moonshot $web_search is a client round-trip, DeepSeek/Mistral have no native API search, Groq's streaming emission is undocumented, Perplexity-reasoning is bespoke. Per-provider follow-ups if needed.

Note

Touches streaming/typing semantics — flagging per CONTRIBUTING.md (maintainer approval).

Verification

ruff + ruff format + mypy clean; full unit suite passes with coverage ≥80% (pre-push hook). No dedicated tests added — the new parsers follow the existing reasoning _parse_chunk_* pattern.

Add a live tool_activity signal on TextChunk so consumers can render
web-search progress while it happens, instead of only seeing the final
grounding on the output.

- types: ToolActivity model + ToolActivityStatus (started/completed)
- TextChunk gains tool_activity; base Stream._parse_chunk parses and
  threads it like reasoning, and keeps activity-only chunks
- OpenResponses (OpenAI + xAI): web_search_call.in_progress -> started,
  .completed -> completed
- Anthropic: server_tool_use(web_search) -> started,
  web_search_tool_result -> completed

Streaming-only by design: final results already live on
TextOutput.grounding. Gemini has no in-stream signal (terminal-only).
@Kamilbenkirane Kamilbenkirane merged commit 31573ad into main Jun 19, 2026
11 checks passed
@claude

claude Bot commented Jun 19, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant