diff --git a/docs/thinking.md b/docs/thinking.md index bfe94ffda0..a10c8024e9 100644 --- a/docs/thinking.md +++ b/docs/thinking.md @@ -38,6 +38,9 @@ agent = Agent(model, model_settings=settings) ... ``` +!!! note "Raw reasoning without summaries" + Some OpenAI-compatible APIs (such as LM Studio, vLLM, or OpenRouter with gpt-oss models) may return raw reasoning content without reasoning summaries. In this case, [`ThinkingPart.content`][pydantic_ai.messages.ThinkingPart.content] will be empty, but the raw reasoning is available in `provider_details['raw_content']`. Following [OpenAI's guidance](https://cookbook.openai.com/examples/responses_api/reasoning_items) that raw reasoning should not be shown directly to users, we store it in `provider_details` rather than in the main `content` field. + ## Anthropic To enable thinking, use the [`AnthropicModelSettings.anthropic_thinking`][pydantic_ai.models.anthropic.AnthropicModelSettings.anthropic_thinking] [model setting](agents.md#model-run-settings). diff --git a/pydantic_ai_slim/pydantic_ai/_parts_manager.py b/pydantic_ai_slim/pydantic_ai/_parts_manager.py index 1a044d1cbf..5dfc53630d 100644 --- a/pydantic_ai_slim/pydantic_ai/_parts_manager.py +++ b/pydantic_ai_slim/pydantic_ai/_parts_manager.py @@ -13,9 +13,9 @@ from __future__ import annotations as _annotations -from collections.abc import Hashable +from collections.abc import Hashable, Iterator from dataclasses import dataclass, field, replace -from typing import Any +from typing import Any, TypeVar from pydantic_ai.exceptions import UnexpectedModelBehavior from pydantic_ai.messages import ( @@ -24,6 +24,7 @@ ModelResponseStreamEvent, PartDeltaEvent, PartStartEvent, + ProviderDetailsDelta, TextPart, TextPartDelta, ThinkingPart, @@ -46,6 +47,8 @@ this includes ToolCallPartDelta's in addition to the more fully-formed ModelResponsePart's. """ +PartT = TypeVar('PartT', bound=ManagedPart) + @dataclass class ModelResponsePartsManager: @@ -76,7 +79,7 @@ def handle_text_delta( provider_details: dict[str, Any] | None = None, thinking_tags: tuple[str, str] | None = None, ignore_leading_whitespace: bool = False, - ) -> ModelResponseStreamEvent | None: + ) -> Iterator[ModelResponseStreamEvent]: """Handle incoming text content, creating or updating a TextPart in the manager as appropriate. When `vendor_part_id` is None, the latest part is updated if it exists and is a TextPart; @@ -93,10 +96,9 @@ def handle_text_delta( thinking_tags: If provided, will handle content between the thinking tags as thinking parts. ignore_leading_whitespace: If True, will ignore leading whitespace in the content. - Returns: - - A `PartStartEvent` if a new part was created. - - A `PartDeltaEvent` if an existing part was updated. - - `None` if no new event is emitted (e.g., the first text part was all whitespace). + Yields: + A `PartStartEvent` if a new part was created, or a `PartDeltaEvent` if an existing part was updated. + Yields nothing if no event should be emitted (e.g., the first text part was all whitespace). Raises: UnexpectedModelBehavior: If attempting to apply text content to a part that is not a TextPart. @@ -105,11 +107,7 @@ def handle_text_delta( if vendor_part_id is None: # If the vendor_part_id is None, check if the latest part is a TextPart to update - if self._parts: - part_index = len(self._parts) - 1 - latest_part = self._parts[part_index] - if isinstance(latest_part, TextPart): - existing_text_part_and_index = latest_part, part_index + existing_text_part_and_index = self._latest_part_if_of_type(TextPart) else: # Otherwise, attempt to look up an existing TextPart by vendor_part_id part_index = self._vendor_id_to_part_index.get(vendor_part_id) @@ -120,12 +118,12 @@ def handle_text_delta( # We may be building a thinking part instead of a text part if we had previously seen a thinking tag if content == thinking_tags[1]: # When we see the thinking end tag, we're done with the thinking part and the next text delta will need a new part - self._vendor_id_to_part_index.pop(vendor_part_id) - return None - else: - return self.handle_thinking_delta( - vendor_part_id=vendor_part_id, content=content, provider_details=provider_details - ) + self._handle_embedded_thinking_end(vendor_part_id) + return + yield from self._handle_embedded_thinking_content( + existing_part, part_index, content, provider_details + ) + return elif isinstance(existing_part, TextPart): existing_text_part_and_index = existing_part, part_index else: @@ -133,30 +131,25 @@ def handle_text_delta( if thinking_tags and content == thinking_tags[0]: # When we see a thinking start tag (which is a single token), we'll build a new thinking part instead - self._vendor_id_to_part_index.pop(vendor_part_id, None) - return self.handle_thinking_delta( - vendor_part_id=vendor_part_id, content='', provider_details=provider_details - ) + yield from self._handle_embedded_thinking_start(vendor_part_id, provider_details) + return if existing_text_part_and_index is None: # This is a workaround for models that emit `\n\n\n` or an empty text part ahead of tool calls (e.g. Ollama + Qwen3), # which we don't want to end up treating as a final result when using `run_stream` with `str` a valid `output_type`. if ignore_leading_whitespace and (len(content) == 0 or content.isspace()): - return None + return # There is no existing text part that should be updated, so create a new one - new_part_index = len(self._parts) part = TextPart(content=content, id=id, provider_details=provider_details) - if vendor_part_id is not None: - self._vendor_id_to_part_index[vendor_part_id] = new_part_index - self._parts.append(part) - return PartStartEvent(index=new_part_index, part=part) + new_part_index = self._append_part(part, vendor_part_id) + yield PartStartEvent(index=new_part_index, part=part) else: # Update the existing TextPart with the new content delta existing_text_part, part_index = existing_text_part_and_index part_delta = TextPartDelta(content_delta=content, provider_details=provider_details) self._parts[part_index] = part_delta.apply(existing_text_part) - return PartDeltaEvent(index=part_index, delta=part_delta) + yield PartDeltaEvent(index=part_index, delta=part_delta) def handle_thinking_delta( self, @@ -166,8 +159,8 @@ def handle_thinking_delta( id: str | None = None, signature: str | None = None, provider_name: str | None = None, - provider_details: dict[str, Any] | None = None, - ) -> ModelResponseStreamEvent: + provider_details: ProviderDetailsDelta = None, + ) -> Iterator[ModelResponseStreamEvent]: """Handle incoming thinking content, creating or updating a ThinkingPart in the manager as appropriate. When `vendor_part_id` is None, the latest part is updated if it exists and is a ThinkingPart; @@ -182,9 +175,11 @@ def handle_thinking_delta( id: An optional id for the thinking part. signature: An optional signature for the thinking content. provider_name: An optional provider name for the thinking part. - provider_details: An optional dictionary of provider-specific details for the thinking part. + provider_details: Either a dict of provider-specific details, or a callable that takes + the existing part's `provider_details` and returns the updated details. Callables + allow provider-specific update logic without the parts manager knowing the details. - Returns: + Yields: A `PartStartEvent` if a new part was created, or a `PartDeltaEvent` if an existing part was updated. Raises: @@ -194,11 +189,7 @@ def handle_thinking_delta( if vendor_part_id is None: # If the vendor_part_id is None, check if the latest part is a ThinkingPart to update - if self._parts: - part_index = len(self._parts) - 1 - latest_part = self._parts[part_index] - if isinstance(latest_part, ThinkingPart): # pragma: no branch - existing_thinking_part_and_index = latest_part, part_index + existing_thinking_part_and_index = self._latest_part_if_of_type(ThinkingPart) else: # Otherwise, attempt to look up an existing ThinkingPart by vendor_part_id part_index = self._vendor_id_to_part_index.get(vendor_part_id) @@ -209,36 +200,39 @@ def handle_thinking_delta( existing_thinking_part_and_index = existing_part, part_index if existing_thinking_part_and_index is None: - if content is not None or signature is not None: + if content is not None or signature is not None or provider_details is not None: # There is no existing thinking part that should be updated, so create a new one - new_part_index = len(self._parts) + # Resolve provider_details if it's a callback (with None since there's no existing part) + resolved_details: dict[str, Any] | None + resolved_details = provider_details(None) if callable(provider_details) else provider_details part = ThinkingPart( content=content or '', id=id, signature=signature, provider_name=provider_name, - provider_details=provider_details, + provider_details=resolved_details, ) - if vendor_part_id is not None: # pragma: no branch - self._vendor_id_to_part_index[vendor_part_id] = new_part_index - self._parts.append(part) - return PartStartEvent(index=new_part_index, part=part) + new_part_index = self._append_part(part, vendor_part_id) + yield PartStartEvent(index=new_part_index, part=part) else: - raise UnexpectedModelBehavior('Cannot create a ThinkingPart with no content or signature') - else: - if content is not None or signature is not None: - # Update the existing ThinkingPart with the new content and/or signature delta - existing_thinking_part, part_index = existing_thinking_part_and_index - part_delta = ThinkingPartDelta( - content_delta=content, - signature_delta=signature, - provider_name=provider_name, - provider_details=provider_details, + raise UnexpectedModelBehavior( + 'Cannot create a ThinkingPart with no content, signature, or provider_details' ) - self._parts[part_index] = part_delta.apply(existing_thinking_part) - return PartDeltaEvent(index=part_index, delta=part_delta) - else: - raise UnexpectedModelBehavior('Cannot update a ThinkingPart with no content or signature') + else: + existing_thinking_part, part_index = existing_thinking_part_and_index + + # Skip if nothing to update + if content is None and signature is None and provider_name is None and provider_details is None: + return + + part_delta = ThinkingPartDelta( + content_delta=content, + signature_delta=signature, + provider_name=provider_name, + provider_details=provider_details, + ) + self._parts[part_index] = part_delta.apply(existing_thinking_part) + yield PartDeltaEvent(index=part_index, delta=part_delta) def handle_tool_call_delta( self, @@ -283,11 +277,10 @@ def handle_tool_call_delta( # vendor_part_id is None, so check if the latest part is a matching tool call or delta to update # When the vendor_part_id is None, if the tool_name is _not_ None, assume this should be a new part rather # than a delta on an existing one. We can change this behavior in the future if necessary for some model. - if tool_name is None and self._parts: - part_index = len(self._parts) - 1 - latest_part = self._parts[part_index] - if isinstance(latest_part, ToolCallPart | BuiltinToolCallPart | ToolCallPartDelta): # pragma: no branch - existing_matching_part_and_index = latest_part, part_index + if tool_name is None: + existing_matching_part_and_index = self._latest_part_if_of_type( + ToolCallPart, BuiltinToolCallPart, ToolCallPartDelta + ) else: # vendor_part_id is provided, so look up the corresponding part or delta part_index = self._vendor_id_to_part_index.get(vendor_part_id) @@ -303,10 +296,7 @@ def handle_tool_call_delta( tool_name_delta=tool_name, args_delta=args, tool_call_id=tool_call_id, provider_details=provider_details ) part = delta.as_part() or delta - if vendor_part_id is not None: - self._vendor_id_to_part_index[vendor_part_id] = len(self._parts) - new_part_index = len(self._parts) - self._parts.append(part) + new_part_index = self._append_part(part, vendor_part_id) # Only emit a PartStartEvent if we have enough information to produce a full ToolCallPart if isinstance(part, ToolCallPart | BuiltinToolCallPart): return PartStartEvent(index=new_part_index, part=part) @@ -364,8 +354,7 @@ def handle_tool_call_part( ) if vendor_part_id is None: # vendor_part_id is None, so we unconditionally append a new ToolCallPart to the end of the list - new_part_index = len(self._parts) - self._parts.append(new_part) + new_part_index = self._append_part(new_part) else: # vendor_part_id is provided, so find and overwrite or create a new ToolCallPart. maybe_part_index = self._vendor_id_to_part_index.get(vendor_part_id) @@ -373,8 +362,7 @@ def handle_tool_call_part( new_part_index = maybe_part_index self._parts[new_part_index] = new_part else: - new_part_index = len(self._parts) - self._parts.append(new_part) + new_part_index = self._append_part(new_part) self._vendor_id_to_part_index[vendor_part_id] = new_part_index return PartStartEvent(index=new_part_index, part=new_part) @@ -397,8 +385,7 @@ def handle_part( """ if vendor_part_id is None: # vendor_part_id is None, so we unconditionally append a new part to the end of the list - new_part_index = len(self._parts) - self._parts.append(part) + new_part_index = self._append_part(part) else: # vendor_part_id is provided, so find and overwrite or create a new part. maybe_part_index = self._vendor_id_to_part_index.get(vendor_part_id) @@ -406,7 +393,49 @@ def handle_part( new_part_index = maybe_part_index self._parts[new_part_index] = part else: - new_part_index = len(self._parts) - self._parts.append(part) + new_part_index = self._append_part(part) self._vendor_id_to_part_index[vendor_part_id] = new_part_index return PartStartEvent(index=new_part_index, part=part) + + def _stop_tracking_vendor_id(self, vendor_part_id: VendorId | None) -> None: + """Stop tracking a vendor_part_id (no-op if None or not tracked).""" + if vendor_part_id is not None: # pragma: no branch + self._vendor_id_to_part_index.pop(vendor_part_id, None) + + def _append_part(self, part: ManagedPart, vendor_part_id: VendorId | None = None) -> int: + """Append a part, optionally track vendor_part_id, return new index.""" + new_index = len(self._parts) + self._parts.append(part) + if vendor_part_id is not None: + self._vendor_id_to_part_index[vendor_part_id] = new_index + return new_index + + def _latest_part_if_of_type(self, *part_types: type[PartT]) -> tuple[PartT, int] | None: + """Get the latest part and its index if it's an instance of the given type(s).""" + if self._parts: + part_index = len(self._parts) - 1 + latest_part = self._parts[part_index] + if isinstance(latest_part, part_types): + return latest_part, part_index + return None + + def _handle_embedded_thinking_start( + self, vendor_part_id: VendorId, provider_details: dict[str, Any] | None + ) -> Iterator[ModelResponseStreamEvent]: + """Handle tag - create new ThinkingPart.""" + self._stop_tracking_vendor_id(vendor_part_id) + part = ThinkingPart(content='', provider_details=provider_details) + new_index = self._append_part(part, vendor_part_id) + yield PartStartEvent(index=new_index, part=part) + + def _handle_embedded_thinking_content( + self, existing_part: ThinkingPart, part_index: int, content: str, provider_details: dict[str, Any] | None + ) -> Iterator[ModelResponseStreamEvent]: + """Handle content inside ....""" + part_delta = ThinkingPartDelta(content_delta=content, provider_details=provider_details) + self._parts[part_index] = part_delta.apply(existing_part) + yield PartDeltaEvent(index=part_index, delta=part_delta) + + def _handle_embedded_thinking_end(self, vendor_part_id: VendorId) -> None: + """Handle tag - stop tracking so next delta creates new part.""" + self._stop_tracking_vendor_id(vendor_part_id) diff --git a/pydantic_ai_slim/pydantic_ai/messages.py b/pydantic_ai_slim/pydantic_ai/messages.py index 51f1534132..6f802f57b8 100644 --- a/pydantic_ai_slim/pydantic_ai/messages.py +++ b/pydantic_ai_slim/pydantic_ai/messages.py @@ -3,7 +3,7 @@ import base64 import hashlib from abc import ABC, abstractmethod -from collections.abc import Sequence +from collections.abc import Callable, Sequence from dataclasses import KW_ONLY, dataclass, field, replace from datetime import datetime from mimetypes import guess_type @@ -64,6 +64,9 @@ ] """Reason the model finished generating the response, normalized to OpenTelemetry values.""" +ProviderDetailsDelta: TypeAlias = dict[str, Any] | Callable[[dict[str, Any] | None], dict[str, Any]] | None +"""Type for provider_details input: can be a static dict, a callback to update existing details, or None.""" + @dataclass(repr=False) class SystemPromptPart: @@ -1525,9 +1528,12 @@ class ThinkingPartDelta: Signatures are only sent back to the same provider. """ - provider_details: dict[str, Any] | None = None + provider_details: ProviderDetailsDelta = None """Additional data returned by the provider that can't be mapped to standard fields. + Can be a dict to merge with existing details, or a callable that takes + the existing details and returns updated details. + This is used for data that is required to be sent back to APIs, as well as data users may want to access programmatically.""" part_delta_kind: Literal['thinking'] = 'thinking' @@ -1555,7 +1561,13 @@ def apply(self, part: ModelResponsePart | ThinkingPartDelta) -> ThinkingPart | T new_content = part.content + self.content_delta if self.content_delta else part.content new_signature = self.signature_delta if self.signature_delta is not None else part.signature new_provider_name = self.provider_name if self.provider_name is not None else part.provider_name - new_provider_details = {**(part.provider_details or {}), **(self.provider_details or {})} or None + # Resolve callable provider_details if needed + resolved_details = ( + self.provider_details(part.provider_details) + if callable(self.provider_details) + else self.provider_details + ) + new_provider_details = {**(part.provider_details or {}), **(resolved_details or {})} or None return replace( part, content=new_content, @@ -1573,7 +1585,28 @@ def apply(self, part: ModelResponsePart | ThinkingPartDelta) -> ThinkingPart | T if self.provider_name is not None: part = replace(part, provider_name=self.provider_name) if self.provider_details is not None: - part = replace(part, provider_details={**(part.provider_details or {}), **self.provider_details}) + if callable(self.provider_details): + if callable(part.provider_details): + existing_fn = part.provider_details + new_fn = self.provider_details + + def chained_both(d: dict[str, Any] | None) -> dict[str, Any]: + return new_fn(existing_fn(d)) + + part = replace(part, provider_details=chained_both) + else: + part = replace(part, provider_details=self.provider_details) + elif callable(part.provider_details): + existing_fn = part.provider_details + new_dict = self.provider_details + + def chained_dict(d: dict[str, Any] | None) -> dict[str, Any]: + return {**existing_fn(d), **new_dict} + + part = replace(part, provider_details=chained_dict) + else: + existing = part.provider_details if isinstance(part.provider_details, dict) else {} + part = replace(part, provider_details={**existing, **self.provider_details}) return part raise ValueError( # pragma: no cover f'Cannot apply ThinkingPartDeltas to non-ThinkingParts or non-ThinkingPartDeltas ({part=}, {self=})' diff --git a/pydantic_ai_slim/pydantic_ai/models/anthropic.py b/pydantic_ai_slim/pydantic_ai/models/anthropic.py index 586f9762f1..28395f56bd 100644 --- a/pydantic_ai_slim/pydantic_ai/models/anthropic.py +++ b/pydantic_ai_slim/pydantic_ai/models/anthropic.py @@ -1129,25 +1129,26 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: elif isinstance(event, BetaRawContentBlockStartEvent): current_block = event.content_block if isinstance(current_block, BetaTextBlock) and current_block.text: - maybe_event = self._parts_manager.handle_text_delta( + for event_ in self._parts_manager.handle_text_delta( vendor_part_id=event.index, content=current_block.text - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event_ elif isinstance(current_block, BetaThinkingBlock): - yield self._parts_manager.handle_thinking_delta( + for event_ in self._parts_manager.handle_thinking_delta( vendor_part_id=event.index, content=current_block.thinking, signature=current_block.signature, provider_name=self.provider_name, - ) + ): + yield event_ elif isinstance(current_block, BetaRedactedThinkingBlock): - yield self._parts_manager.handle_thinking_delta( + for event_ in self._parts_manager.handle_thinking_delta( vendor_part_id=event.index, id='redacted_thinking', signature=current_block.data, provider_name=self.provider_name, - ) + ): + yield event_ elif isinstance(current_block, BetaToolUseBlock): maybe_event = self._parts_manager.handle_tool_call_delta( vendor_part_id=event.index, @@ -1208,23 +1209,24 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: elif isinstance(event, BetaRawContentBlockDeltaEvent): if isinstance(event.delta, BetaTextDelta): - maybe_event = self._parts_manager.handle_text_delta( + for event_ in self._parts_manager.handle_text_delta( vendor_part_id=event.index, content=event.delta.text - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event_ elif isinstance(event.delta, BetaThinkingDelta): - yield self._parts_manager.handle_thinking_delta( + for event_ in self._parts_manager.handle_thinking_delta( vendor_part_id=event.index, content=event.delta.thinking, provider_name=self.provider_name, - ) + ): + yield event_ elif isinstance(event.delta, BetaSignatureDelta): - yield self._parts_manager.handle_thinking_delta( + for event_ in self._parts_manager.handle_thinking_delta( vendor_part_id=event.index, signature=event.delta.signature, provider_name=self.provider_name, - ) + ): + yield event_ elif isinstance(event.delta, BetaInputJSONDelta): maybe_event = self._parts_manager.handle_tool_call_delta( vendor_part_id=event.index, diff --git a/pydantic_ai_slim/pydantic_ai/models/bedrock.py b/pydantic_ai_slim/pydantic_ai/models/bedrock.py index ff03460904..8d81948f68 100644 --- a/pydantic_ai_slim/pydantic_ai/models/bedrock.py +++ b/pydantic_ai_slim/pydantic_ai/models/bedrock.py @@ -751,24 +751,25 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: delta = content_block_delta['delta'] if 'reasoningContent' in delta: if redacted_content := delta['reasoningContent'].get('redactedContent'): - yield self._parts_manager.handle_thinking_delta( + for event in self._parts_manager.handle_thinking_delta( vendor_part_id=index, id='redacted_content', signature=redacted_content.decode('utf-8'), provider_name=self.provider_name, - ) + ): + yield event else: signature = delta['reasoningContent'].get('signature') - yield self._parts_manager.handle_thinking_delta( + for event in self._parts_manager.handle_thinking_delta( vendor_part_id=index, content=delta['reasoningContent'].get('text'), signature=signature, provider_name=self.provider_name if signature else None, - ) + ): + yield event if text := delta.get('text'): - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=index, content=text) - if maybe_event is not None: # pragma: no branch - yield maybe_event + for event in self._parts_manager.handle_text_delta(vendor_part_id=index, content=text): + yield event if 'toolUse' in delta: tool_use = delta['toolUse'] maybe_event = self._parts_manager.handle_tool_call_delta( diff --git a/pydantic_ai_slim/pydantic_ai/models/function.py b/pydantic_ai_slim/pydantic_ai/models/function.py index 37876e3e80..94a635296f 100644 --- a/pydantic_ai_slim/pydantic_ai/models/function.py +++ b/pydantic_ai_slim/pydantic_ai/models/function.py @@ -292,26 +292,26 @@ class FunctionStreamedResponse(StreamedResponse): def __post_init__(self): self._usage += _estimate_usage([]) - async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: + async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: # noqa: C901 async for item in self._iter: if isinstance(item, str): response_tokens = _estimate_string_tokens(item) self._usage += usage.RequestUsage(output_tokens=response_tokens) - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id='content', content=item) - if maybe_event is not None: # pragma: no branch - yield maybe_event + for event in self._parts_manager.handle_text_delta(vendor_part_id='content', content=item): + yield event elif isinstance(item, dict) and item: for dtc_index, delta in item.items(): if isinstance(delta, DeltaThinkingPart): if delta.content: # pragma: no branch response_tokens = _estimate_string_tokens(delta.content) self._usage += usage.RequestUsage(output_tokens=response_tokens) - yield self._parts_manager.handle_thinking_delta( + for event in self._parts_manager.handle_thinking_delta( vendor_part_id=dtc_index, content=delta.content, signature=delta.signature, provider_name='function' if delta.signature else None, - ) + ): + yield event elif isinstance(delta, DeltaToolCall): if delta.json_args: response_tokens = _estimate_string_tokens(delta.json_args) diff --git a/pydantic_ai_slim/pydantic_ai/models/gemini.py b/pydantic_ai_slim/pydantic_ai/models/gemini.py index 4da92018fd..2772e26631 100644 --- a/pydantic_ai_slim/pydantic_ai/models/gemini.py +++ b/pydantic_ai_slim/pydantic_ai/models/gemini.py @@ -465,11 +465,10 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: if 'text' in gemini_part: # Using vendor_part_id=None means we can produce multiple text parts if their deltas are sprinkled # amongst the tool call deltas - maybe_event = self._parts_manager.handle_text_delta( + for event in self._parts_manager.handle_text_delta( vendor_part_id=None, content=gemini_part['text'] - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event elif 'function_call' in gemini_part: # Here, we assume all function_call parts are complete and don't have deltas. diff --git a/pydantic_ai_slim/pydantic_ai/models/google.py b/pydantic_ai_slim/pydantic_ai/models/google.py index 89290ea3ce..8aca93c720 100644 --- a/pydantic_ai_slim/pydantic_ai/models/google.py +++ b/pydantic_ai_slim/pydantic_ai/models/google.py @@ -722,15 +722,15 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: if len(part.text) == 0 and not provider_details: continue if part.thought: - yield self._parts_manager.handle_thinking_delta( + for event in self._parts_manager.handle_thinking_delta( vendor_part_id=None, content=part.text, provider_details=provider_details - ) + ): + yield event else: - maybe_event = self._parts_manager.handle_text_delta( + for event in self._parts_manager.handle_text_delta( vendor_part_id=None, content=part.text, provider_details=provider_details - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event elif part.function_call: maybe_event = self._parts_manager.handle_tool_call_delta( vendor_part_id=uuid4(), diff --git a/pydantic_ai_slim/pydantic_ai/models/groq.py b/pydantic_ai_slim/pydantic_ai/models/groq.py index 64f7ddcf85..780ee0b305 100644 --- a/pydantic_ai_slim/pydantic_ai/models/groq.py +++ b/pydantic_ai_slim/pydantic_ai/models/groq.py @@ -551,9 +551,10 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: reasoning = True # NOTE: The `reasoning` field is only present if `groq_reasoning_format` is set to `parsed`. - yield self._parts_manager.handle_thinking_delta( + for event in self._parts_manager.handle_thinking_delta( vendor_part_id=f'reasoning-{reasoning_index}', content=choice.delta.reasoning - ) + ): + yield event else: reasoning = False @@ -576,14 +577,13 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: # Handle the text part of the response content = choice.delta.content if content: - maybe_event = self._parts_manager.handle_text_delta( + for event in self._parts_manager.handle_text_delta( vendor_part_id='content', content=content, thinking_tags=self._model_profile.thinking_tags, ignore_leading_whitespace=self._model_profile.ignore_streamed_leading_whitespace, - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event # Handle the tool calls for dtc in choice.delta.tool_calls or []: diff --git a/pydantic_ai_slim/pydantic_ai/models/huggingface.py b/pydantic_ai_slim/pydantic_ai/models/huggingface.py index 790b30bec3..f439b3ccb6 100644 --- a/pydantic_ai_slim/pydantic_ai/models/huggingface.py +++ b/pydantic_ai_slim/pydantic_ai/models/huggingface.py @@ -487,14 +487,13 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: # Handle the text part of the response content = choice.delta.content if content: - maybe_event = self._parts_manager.handle_text_delta( + for event in self._parts_manager.handle_text_delta( vendor_part_id='content', content=content, thinking_tags=self._model_profile.thinking_tags, ignore_leading_whitespace=self._model_profile.ignore_streamed_leading_whitespace, - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event for dtc in choice.delta.tool_calls or []: maybe_event = self._parts_manager.handle_tool_call_delta( diff --git a/pydantic_ai_slim/pydantic_ai/models/mistral.py b/pydantic_ai_slim/pydantic_ai/models/mistral.py index cefa28e9dc..2a3752c370 100644 --- a/pydantic_ai_slim/pydantic_ai/models/mistral.py +++ b/pydantic_ai_slim/pydantic_ai/models/mistral.py @@ -639,7 +639,8 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: content = choice.delta.content text, thinking = _map_content(content) for thought in thinking: - self._parts_manager.handle_thinking_delta(vendor_part_id='thinking', content=thought) + for event in self._parts_manager.handle_thinking_delta(vendor_part_id='thinking', content=thought): + yield event if text: # Attempt to produce an output tool call from the received text output_tools = {c.name: c for c in self.model_request_parameters.output_tools} @@ -655,9 +656,8 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: tool_call_id=maybe_tool_call_part.tool_call_id, ) else: - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id='content', content=text) - if maybe_event is not None: # pragma: no branch - yield maybe_event + for event in self._parts_manager.handle_text_delta(vendor_part_id='content', content=text): + yield event # Handle the explicit tool calls for index, dtc in enumerate(choice.delta.tool_calls or []): diff --git a/pydantic_ai_slim/pydantic_ai/models/openai.py b/pydantic_ai_slim/pydantic_ai/models/openai.py index 3c5c184a76..a37be4f024 100644 --- a/pydantic_ai_slim/pydantic_ai/models/openai.py +++ b/pydantic_ai_slim/pydantic_ai/models/openai.py @@ -4,7 +4,7 @@ import itertools import json import warnings -from collections.abc import AsyncIterable, AsyncIterator, Iterable, Sequence +from collections.abc import AsyncIterable, AsyncIterator, Callable, Iterable, Sequence from contextlib import asynccontextmanager from dataclasses import dataclass, field, replace from datetime import datetime @@ -83,7 +83,10 @@ ) from openai.types.responses import ComputerToolParam, FileSearchToolParam, WebSearchToolParam from openai.types.responses.response_input_param import FunctionCallOutput, Message - from openai.types.responses.response_reasoning_item_param import Summary + from openai.types.responses.response_reasoning_item_param import ( + Content as ReasoningContent, + Summary as ReasoningSummary, + ) from openai.types.responses.response_status import ResponseStatus from openai.types.shared import ReasoningEffort from openai.types.shared_params import Reasoning @@ -1151,6 +1154,10 @@ def _process_response( # noqa: C901 for item in response.output: if isinstance(item, responses.ResponseReasoningItem): signature = item.encrypted_content + # Handle raw CoT content from gpt-oss models + raw_content: list[str] | None = [c.text for c in item.content] if item.content else None + provider_details: dict[str, Any] | None = {'raw_content': raw_content} if raw_content else None + if item.summary: for summary in item.summary: # We use the same id for all summaries so that we can merge them on the round trip. @@ -1159,22 +1166,23 @@ def _process_response( # noqa: C901 content=summary.text, id=item.id, signature=signature, - provider_name=self.system if signature else None, + provider_name=self.system if (signature or provider_details) else None, + provider_details=provider_details, ) ) - # We only need to store the signature once. + # We only need to store the signature and raw_content once. signature = None - elif signature: + provider_details = None + elif signature or provider_details: items.append( ThinkingPart( content='', id=item.id, signature=signature, - provider_name=self.system, + provider_name=self.system if (signature or provider_details) else None, + provider_details=provider_details, ) ) - # NOTE: We don't currently handle the raw CoT from gpt-oss `reasoning_text`: https://cookbook.openai.com/articles/gpt-oss/handle-raw-cot - # If you need this, please file an issue. elif isinstance(item, responses.ResponseOutputMessage): for content in item.content: if isinstance(content, responses.ResponseOutputText): # pragma: no branch @@ -1522,7 +1530,15 @@ async def _map_messages( # noqa: C901 model_settings: OpenAIResponsesModelSettings, model_request_parameters: ModelRequestParameters, ) -> tuple[str | Omit, list[responses.ResponseInputItemParam]]: - """Just maps a `pydantic_ai.Message` to a `openai.types.responses.ResponseInputParam`.""" + """Maps a `pydantic_ai.Message` to a `openai.types.responses.ResponseInputParam` i.e. the OpenAI Responses API input format. + + For `ThinkingParts`, this method: + - Sends `signature` back as `encrypted_content` (for official OpenAI reasoning) + - Sends `content` back as `summary` text + - Sends `provider_details['raw_content']` back as `content` items (for gpt-oss raw CoT) + + Raw CoT is sent back to improve model performance in multi-turn conversations. + """ profile = OpenAIModelProfile.from_profile(self.profile) send_item_ids = model_settings.get( 'openai_send_reasoning_ids', profile.openai_supports_encrypted_reasoning_content @@ -1707,7 +1723,12 @@ async def _map_messages( # noqa: C901 # If `send_item_ids` is false, we won't send the `BuiltinToolReturnPart`, but OpenAI does not have a type for files from the assistant. pass elif isinstance(item, ThinkingPart): - if item.id and send_item_ids: + # Get raw CoT content from provider_details if present and from this provider + raw_content: list[str] | None = None + if item.provider_name == self.system: + raw_content = (item.provider_details or {}).get('raw_content') + + if item.id and (send_item_ids or raw_content): signature: str | None = None if ( item.signature @@ -1717,7 +1738,7 @@ async def _map_messages( # noqa: C901 signature = item.signature if (reasoning_item is None or reasoning_item['id'] != item.id) and ( - signature or item.content + signature or item.content or raw_content ): # pragma: no branch reasoning_item = responses.ResponseReasoningItemParam( id=item.id, @@ -1732,7 +1753,14 @@ async def _map_messages( # noqa: C901 assert reasoning_item is not None reasoning_item['summary'] = [ *reasoning_item['summary'], - Summary(text=item.content, type='summary_text'), + ReasoningSummary(text=item.content, type='summary_text'), + ] + + if raw_content: + # Send raw CoT back + assert reasoning_item is not None + reasoning_item['content'] = [ + ReasoningContent(text=text, type='reasoning_text') for text in raw_content ] else: start_tag, end_tag = profile.thinking_tags @@ -1923,7 +1951,7 @@ def _map_thinking_delta(self, choice: chat_completion_chunk.Choice) -> Iterable[ continue reasoning: str | None = getattr(choice.delta, field_name, None) if reasoning: # pragma: no branch - yield self._parts_manager.handle_thinking_delta( + yield from self._parts_manager.handle_thinking_delta( vendor_part_id=field_name, id=field_name, content=reasoning, @@ -1939,17 +1967,16 @@ def _map_text_delta(self, choice: chat_completion_chunk.Choice) -> Iterable[Mode # Handle the text part of the response content = choice.delta.content if content: - maybe_event = self._parts_manager.handle_text_delta( + for event in self._parts_manager.handle_text_delta( vendor_part_id='content', content=content, thinking_tags=self._model_profile.thinking_tags, ignore_leading_whitespace=self._model_profile.ignore_streamed_leading_whitespace, - ) - if maybe_event is not None: # pragma: no branch - if isinstance(maybe_event, PartStartEvent) and isinstance(maybe_event.part, ThinkingPart): - maybe_event.part.id = 'content' - maybe_event.part.provider_name = self.provider_name - yield maybe_event + ): + if isinstance(event, PartStartEvent) and isinstance(event.part, ThinkingPart): + event.part.id = 'content' + event.part.provider_name = self.provider_name + yield event def _map_tool_call_delta(self, choice: chat_completion_chunk.Choice) -> Iterable[ModelResponseStreamEvent]: """Hook that maps tool call delta content to events. @@ -2123,13 +2150,14 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: elif isinstance(chunk, responses.ResponseOutputItemDoneEvent): if isinstance(chunk.item, responses.ResponseReasoningItem): if signature := chunk.item.encrypted_content: # pragma: no branch - # Add the signature to the part corresponding to the first summary item - yield self._parts_manager.handle_thinking_delta( - vendor_part_id=f'{chunk.item.id}-0', + # Add the signature to the part corresponding to the first summary/raw CoT + for event in self._parts_manager.handle_thinking_delta( + vendor_part_id=chunk.item.id, id=chunk.item.id, signature=signature, provider_name=self.provider_name, - ) + ): + yield event elif isinstance(chunk.item, responses.ResponseCodeInterpreterToolCall): _, return_part, file_parts = _map_code_interpreter_tool_call(chunk.item, self.provider_name) for i, file_part in enumerate(file_parts): @@ -2162,11 +2190,14 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: yield self._parts_manager.handle_part(vendor_part_id=f'{chunk.item.id}-return', part=return_part) elif isinstance(chunk, responses.ResponseReasoningSummaryPartAddedEvent): - yield self._parts_manager.handle_thinking_delta( - vendor_part_id=f'{chunk.item_id}-{chunk.summary_index}', + # Use same vendor_part_id as raw CoT for first summary (index 0) so they merge into one ThinkingPart + vendor_id = chunk.item_id if chunk.summary_index == 0 else f'{chunk.item_id}-{chunk.summary_index}' + for event in self._parts_manager.handle_thinking_delta( + vendor_part_id=vendor_id, content=chunk.part.text, id=chunk.item_id, - ) + ): + yield event elif isinstance(chunk, responses.ResponseReasoningSummaryPartDoneEvent): pass # there's nothing we need to do here @@ -2175,22 +2206,36 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: pass # there's nothing we need to do here elif isinstance(chunk, responses.ResponseReasoningSummaryTextDeltaEvent): - yield self._parts_manager.handle_thinking_delta( - vendor_part_id=f'{chunk.item_id}-{chunk.summary_index}', + # Use same vendor_part_id as raw CoT for first summary (index 0) so they merge into one ThinkingPart + vendor_id = chunk.item_id if chunk.summary_index == 0 else f'{chunk.item_id}-{chunk.summary_index}' + for event in self._parts_manager.handle_thinking_delta( + vendor_part_id=vendor_id, content=chunk.delta, id=chunk.item_id, - ) + ): + yield event + + elif isinstance(chunk, responses.ResponseReasoningTextDeltaEvent): + # Handle raw CoT from gpt-oss models using callback pattern + for event in self._parts_manager.handle_thinking_delta( + vendor_part_id=chunk.item_id, + id=chunk.item_id, + provider_details=_make_raw_content_updater(chunk.delta, chunk.content_index), + ): + yield event + + elif isinstance(chunk, responses.ResponseReasoningTextDoneEvent): + pass # content already accumulated via delta events elif isinstance(chunk, responses.ResponseOutputTextAnnotationAddedEvent): # TODO(Marcelo): We should support annotations in the future. pass # there's nothing we need to do here elif isinstance(chunk, responses.ResponseTextDeltaEvent): - maybe_event = self._parts_manager.handle_text_delta( + for event in self._parts_manager.handle_text_delta( vendor_part_id=chunk.item_id, content=chunk.delta, id=chunk.item_id - ) - if maybe_event is not None: # pragma: no branch - yield maybe_event + ): + yield event elif isinstance(chunk, responses.ResponseTextDoneEvent): pass # there's nothing we need to do here @@ -2314,6 +2359,25 @@ def timestamp(self) -> datetime: return self._timestamp +def _make_raw_content_updater(delta: str, index: int) -> Callable[[dict[str, Any] | None], dict[str, Any]]: + """Create a callback that updates `provider_details['raw_content']`. + + This is used for streaming raw CoT from gpt-oss models. The callback pattern keeps + `raw_content` logic in OpenAI code while the parts manager stays provider-agnostic. + """ + + def update_provider_details(existing: dict[str, Any] | None) -> dict[str, Any]: + details = {**(existing or {})} + raw_list: list[str] = list(details.get('raw_content', [])) + while len(raw_list) <= index: + raw_list.append('') + raw_list[index] += delta + details['raw_content'] = raw_list + return details + + return update_provider_details + + # Convert logprobs to a serializable format def _map_logprobs( logprobs: list[chat_completion_token_logprob.ChatCompletionTokenLogprob] diff --git a/pydantic_ai_slim/pydantic_ai/models/openrouter.py b/pydantic_ai_slim/pydantic_ai/models/openrouter.py index e5c14ef77c..fd3d7dfce4 100644 --- a/pydantic_ai_slim/pydantic_ai/models/openrouter.py +++ b/pydantic_ai_slim/pydantic_ai/models/openrouter.py @@ -650,7 +650,7 @@ def _map_thinking_delta(self, choice: chat_completion_chunk.Choice) -> Iterable[ # This is required for Gemini 3 Pro which returns multiple reasoning # detail types that must be preserved separately for thought_signature handling. vendor_id = f'reasoning_detail_{detail.type}_{i}' - yield self._parts_manager.handle_thinking_delta( + yield from self._parts_manager.handle_thinking_delta( vendor_part_id=vendor_id, id=thinking_part.id, content=thinking_part.content, diff --git a/pydantic_ai_slim/pydantic_ai/models/outlines.py b/pydantic_ai_slim/pydantic_ai/models/outlines.py index e2f16ffa0d..34efece6fa 100644 --- a/pydantic_ai_slim/pydantic_ai/models/outlines.py +++ b/pydantic_ai_slim/pydantic_ai/models/outlines.py @@ -546,14 +546,13 @@ class OutlinesStreamedResponse(StreamedResponse): _provider_name: str async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: - async for event in self._response: - event = self._parts_manager.handle_text_delta( + async for content in self._response: + for event in self._parts_manager.handle_text_delta( vendor_part_id='content', - content=event, + content=content, thinking_tags=self._model_profile.thinking_tags, ignore_leading_whitespace=self._model_profile.ignore_streamed_leading_whitespace, - ) - if event is not None: # pragma: no branch + ): yield event @property diff --git a/pydantic_ai_slim/pydantic_ai/models/test.py b/pydantic_ai_slim/pydantic_ai/models/test.py index 170113a999..eddc98787b 100644 --- a/pydantic_ai_slim/pydantic_ai/models/test.py +++ b/pydantic_ai_slim/pydantic_ai/models/test.py @@ -313,14 +313,12 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: mid = len(text) // 2 words = [text[:mid], text[mid:]] self._usage += _get_string_usage('') - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=i, content='') - if maybe_event is not None: # pragma: no branch - yield maybe_event + for event in self._parts_manager.handle_text_delta(vendor_part_id=i, content=''): + yield event for word in words: self._usage += _get_string_usage(word) - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=i, content=word) - if maybe_event is not None: # pragma: no branch - yield maybe_event + for event in self._parts_manager.handle_text_delta(vendor_part_id=i, content=word): + yield event elif isinstance(part, ToolCallPart): yield self._parts_manager.handle_tool_call_part( vendor_part_id=i, tool_name=part.tool_name, args=part.args, tool_call_id=part.tool_call_id diff --git a/tests/models/cassettes/test_mistral/test_image_as_binary_content_tool_response.yaml b/tests/models/cassettes/test_mistral/test_image_as_binary_content_tool_response.yaml index e826eb942f..0a0135f49d 100644 --- a/tests/models/cassettes/test_mistral/test_image_as_binary_content_tool_response.yaml +++ b/tests/models/cassettes/test_mistral/test_image_as_binary_content_tool_response.yaml @@ -8,7 +8,7 @@ interactions: connection: - keep-alive content-length: - - '381' + - '366' content-type: - application/json host: @@ -32,7 +32,6 @@ interactions: additionalProperties: false properties: {} type: object - strict: false top_p: 1.0 uri: https://api.mistral.ai/v1/chat/completions response: @@ -44,24 +43,19 @@ interactions: connection: - keep-alive content-length: - - '394' + - '378' content-type: - application/json - ratelimitbysize-limit: - - '5000000' - ratelimitbysize-query-cost: - - '32000' - ratelimitbysize-remaining: - - '4968000' - ratelimitbysize-reset: - - '12' + mistral-correlation-id: + - 019ac842-9519-74fd-8f4f-7fbc4a234278 + strict-transport-security: + - max-age=15552000; includeSubDomains; preload transfer-encoding: - chunked parsed_body: choices: - finish_reason: tool_calls index: 0 - logprobs: null message: content: '' role: assistant @@ -69,10 +63,10 @@ interactions: - function: arguments: '{}' name: get_image - id: utZJMAZN4 + id: GJYBCIkcS index: 0 - created: 1745958108 - id: fce6d16a4e5940edb24ae16dd0369947 + created: 1764296398 + id: 412174432ea945889703eac58b44ae35 model: pixtral-12b-latest object: chat.completion usage: @@ -91,12 +85,12 @@ interactions: connection: - keep-alive content-length: - - '2780308' + - '2780293' content-type: - application/json cookie: - - __cf_bm=3WmtMDDbVoD5a1xLGm8HF0OjhXhDx1lEuKEqxaS1u8g-1745958108-1.0.1.1-m7Ve2HoqiAB9RmyGw0yyGxi1s64Ij2HoX2kRQDbtZsY5R5l7wcPk.x2Z57rAp9sUjB_ErAYM6k9t.CSP6VPLPqvqTeS8GIKozA3aQWRllow; - _cfuvid=v0kdRXioGuqqRUowF17sySiegLOq9b7mAOQpsO4Xlrg-1745958108368-0.0.1.1-604800000 + - __cf_bm=1UlAAXD0SyPFUXPKDVjpG941nWKknyKxBO5wNJBryvY-1764296398-1.0.1.1-eNIbtGW3UmBMgAIPnmRycErc076o_OZBVpE26PDFxQicyBF3TsLOcrhe4mx0Id0OG7GLEPtWyYPQAfTjEA01cyfs6DNz5XXloP6ugZtnVpI; + _cfuvid=v1Nl.HtsDN5eK78u9sclXIhQ5ugl5pK.eXxTfV2bHdY-1764296398445-0.0.1.1-604800000 host: - api.mistral.ai method: POST @@ -113,12 +107,12 @@ interactions: - function: arguments: '{}' name: get_image - id: utZJMAZN4 + id: GJYBCIkcS index: 0 type: function - content: See file 1c8566 role: tool - tool_call_id: utZJMAZN4 + tool_call_id: GJYBCIkcS - content: - text: OK type: text @@ -143,7 +137,6 @@ interactions: additionalProperties: false properties: {} type: object - strict: false top_p: 1.0 uri: https://api.mistral.ai/v1/chat/completions response: @@ -155,38 +148,33 @@ interactions: connection: - keep-alive content-length: - - '591' + - '572' content-type: - application/json - ratelimitbysize-limit: - - '5000000' - ratelimitbysize-query-cost: - - '32004' - ratelimitbysize-remaining: - - '4967996' - ratelimitbysize-reset: - - '12' + mistral-correlation-id: + - 019ac842-9ff6-708a-8713-bca74f14d8bd + strict-transport-security: + - max-age=15552000; includeSubDomains; preload transfer-encoding: - chunked parsed_body: choices: - finish_reason: stop index: 0 - logprobs: null message: - content: The image you're referring to, labeled as "file 1c8566," shows a kiwi. Kiwis are small, brown, oval-shaped - fruits with a bright green flesh inside that is dotted with tiny black seeds. They have a sweet and tangy flavor - and are known for being rich in vitamin C and fiber. + content: The image you're referring to, labeled as "file 1c8566," shows a kiwi fruit that has been cut in half. + The kiwi is known for its bright green flesh with tiny black seeds and a central white core. It is a popular fruit + known for its sweet taste and nutritional benefits. role: assistant tool_calls: null - created: 1745958109 - id: 26e7de193646460e8904f8e604a60dc1 + created: 1764296405 + id: 049b5c7704554d3396e727a95cb6d947 model: pixtral-12b-latest object: chat.completion usage: - completion_tokens: 70 + completion_tokens: 66 prompt_tokens: 2931 - total_tokens: 3001 + total_tokens: 2997 status: code: 200 message: OK diff --git a/tests/models/cassettes/test_mistral/test_mistral_model_thinking_part_iter.yaml b/tests/models/cassettes/test_mistral/test_mistral_model_thinking_part_iter.yaml index 72342c22b6..c656a9d1a1 100644 --- a/tests/models/cassettes/test_mistral/test_mistral_model_thinking_part_iter.yaml +++ b/tests/models/cassettes/test_mistral/test_mistral_model_thinking_part_iter.yaml @@ -24,693 +24,321 @@ interactions: response: body: string: |+ - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":""},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":""},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"Okay"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"Okay"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", the"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", the"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" user"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" user"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" is"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" is"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" asking"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" asking"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a very"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" how"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" basic question about"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to cross the"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" how"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" street. I"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to cross the street"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" know"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":". This"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" that"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" seems"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" crossing"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" like a straightforward query"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":","}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" street safely"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" but"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" involves"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" I"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" need to"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" few"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" make"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" key"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" sure I provide"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" steps:"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" clear"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" first"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" and"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", look"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" safe"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" both"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" instructions"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" ways"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":". Crossing"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to check"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the street safely"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" for"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" involves a"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" on"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" few"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"coming traffic;"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" key"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" second"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" steps that"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", use"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" are"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a cross"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" generally"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"walk"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" taught"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" if"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" one"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" children"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" is"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" and"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" available; third,"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" are"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" obey"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" important"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" any"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" for"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" traffic signals"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" everyone"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" or"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signs"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" follow.\n\n"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" that may be present"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"First"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"; and finally,"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", I"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" proceed"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" recall"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" with caution"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" that"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" until"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" you have"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" basic"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" safely"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" steps involve"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" reached"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" looking"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the other"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" both"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" side. Let"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" ways for"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" me"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" on"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" compile"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"coming traffic,"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" this"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" using"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" information"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" designated"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" into"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" cross"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a clear"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"wal"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" and"}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"ks if"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" concise response."}]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" available"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[]}]},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", and following traffic"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"To"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signals"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" cross the street safely"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" if"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":", follow these steps"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" there"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":":\n\n1. Look"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" are"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" both ways to check"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" any"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" for oncoming traffic"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"."}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" But"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"2. Use a"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" I"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" crosswalk if one"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" should"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" is available.\n3"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" break"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":". O"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" it"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"bey any traffic signals"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" down into"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" or signs that may"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" clear"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" be present.\n4"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":","}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":". Proceed with"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" action"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" caution until you have"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"able steps.\n\n"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" safely reached the other"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"1. **Find"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" side.\n\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"```"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Safe"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"mark"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Place"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"down"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Cross**:"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"To"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Ideally"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" cross"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", you should cross"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" at"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" street"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" safely"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" designated"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":","},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" crosswalk or"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" follow"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" intersection"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" these"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":". These"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" steps"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" are typically"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":":\n\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" marked"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"1"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" with white"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" lines"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" Look"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" on the road and"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" both"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" may"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" ways"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" have traffic"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" to"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signals"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" check"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" or"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" for"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signs"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" on"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":".\n\n"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"coming"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"2. **Look"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" traffic"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Both"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Ways**: Before"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"2"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" stepping"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" off"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" Use"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the curb"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" a"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", look"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" cross"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" left"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"walk"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":","}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" if"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" right, and"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" one"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" then"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" is"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" left"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" available"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" again to"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" check"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"3"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" for"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" on"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" O"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"coming traffic. This"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"bey"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" is"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" any"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" because"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" traffic"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" in"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" signals"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" many"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" or"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" places, traffic comes"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" signs"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" from"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" that"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" may"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" left first"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" be"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" ("}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" present"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"depend"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"ing on the"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"4"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" country"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"'s"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" Pro"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" driving"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"ceed"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" side"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" with"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":").\n\n"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" caution"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"3. **Wait"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" until"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" for a"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" you"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Safe"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" have"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Gap"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" safely"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"**: Make"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" reached"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" sure there"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" is enough"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" other"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" time"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" side"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" cross the street before"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"```\n\n"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" any"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"By"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" vehicles"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" following"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" approach"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" these"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":". If there's"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" steps"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a traffic"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":","},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" light, wait"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" you"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" for the"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" can"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" pedestrian"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" ensure"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signal"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" a"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to indicate"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" safe"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" it"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" crossing"},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"'s safe"}]}]},"finish_reason":null}]} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]} - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" cross.\n\n4."}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" **Cross with"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" C"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"aution**: Walk"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" br"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"iskly across"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the street while"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" keeping"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" an"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" eye out"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" for any unexpected"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" vehicles"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"."}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Avoid"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" running"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" unless"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" absolutely"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" necessary.\n\n"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"5. **Continue"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Looking"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"**: Even"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" while"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" crossing,"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" continue to look for"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" vehicles to"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" ensure"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" your"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" safety.\n\n"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"6. **Follow"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" Traffic Signals**: If"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" there"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" are traffic"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" lights or"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" pedestrian"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signals,"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" obey"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" them. Only"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" cross"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" when"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" signal"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" indicates"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" it"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"'s safe to"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" do so.\n\nAdditionally"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", it"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"'s important to make"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" eye"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" contact with drivers"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" if"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" possible"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":","}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" to"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" ensure"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" they see"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" you before"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" you"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" cross. Avoid"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" distra"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"ctions like using"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" your"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" phone while crossing the"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" street.\n\nBut"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" wait"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", does"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" user"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" need"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" any specific"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" context"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"?"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" For"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" example"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", are"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" they in"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a country"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" where cars"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" drive"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" on the left or"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" right?"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" That"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" might"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" affect"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the direction they"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" should"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" look"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" first"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":". However"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", since"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the user"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" hasn"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"'t specified"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a location"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", I'll provide"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a general answer"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" that should"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" work"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" in"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" most places.\n\n"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":"Also"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", if"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the user is asking"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" this"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" question,"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" they"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" might"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" be very"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" young"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" or unfamiliar"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" with urban"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" environments"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":", so I"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" should"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" keep"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" the"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" instructions"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" simple and clear"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":".\n\nHere's"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" a concise"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" response based"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":" on this thinking"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[{"type":"text","text":":"}]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":[{"type":"thinking","thinking":[]}]},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"To"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" cross the street safely"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":", follow"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" these steps"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":":\n\n1. Find"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" a designated crosswalk"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" or intersection if"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" possible"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n2. Look"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" left"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":","},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" right, and then"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" left again to"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" check for oncoming"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" traffic.\n3."},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" Wait"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" for a safe gap"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" in"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" traffic"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" or"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" for"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" pedestrian signal to indicate"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" it's safe to"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" cross.\n4."},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" Cross"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" street br"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"iskly while continuing"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" to look for vehicles"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":".\n"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"5. Follow any"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" traffic signals and"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" always"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" be"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" cautious of your"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" surroundings.\n\n"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"If"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" you"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"'re in"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" a country where cars"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" drive on the left"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" ("},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"like"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" the UK"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" or"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" Japan"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"), remember"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" to"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" look"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" right"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" first"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" instead"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" of left. Always"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" priorit"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":"ize your"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" safety and"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" make"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" sure drivers"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" see"},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":" you before crossing."},"finish_reason":null}]} - - data: {"id":"9faf4309c1d743d189f16b29211d8b45","object":"chat.completion.chunk","created":1757459263,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":""},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"total_tokens":612,"completion_tokens":602}} + data: {"id":"9f9d90210f194076abeee223863eaaf0","object":"chat.completion.chunk","created":1764296393,"model":"magistral-medium-latest","choices":[{"index":0,"delta":{"content":""},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"total_tokens":242,"completion_tokens":232}} data: [DONE] @@ -724,9 +352,9 @@ interactions: content-type: - text/event-stream; charset=utf-8 mistral-correlation-id: - - 019930bc-2e47-7f5d-ab5e-1ceb8d616e6f + - 019ac842-8151-73a9-a77a-2b27a0800270 strict-transport-security: - - max-age=15552000; includeSubDomains + - max-age=15552000; includeSubDomains; preload transfer-encoding: - chunked status: diff --git a/tests/models/cassettes/test_openai_responses/test_openai_responses_raw_cot_stream_openrouter.yaml b/tests/models/cassettes/test_openai_responses/test_openai_responses_raw_cot_stream_openrouter.yaml new file mode 100644 index 0000000000..9413b7be42 --- /dev/null +++ b/tests/models/cassettes/test_openai_responses/test_openai_responses_raw_cot_stream_openrouter.yaml @@ -0,0 +1,133 @@ +interactions: +- request: + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + connection: + - keep-alive + content-length: + - '95' + content-type: + - application/json + host: + - openrouter.ai + method: POST + parsed_body: + input: + - content: What is 2+2? + role: user + model: openai/gpt-oss-20b + stream: true + uri: https://openrouter.ai/api/v1/responses + response: + body: + string: |+ + : OPENROUTER PROCESSING + + data: {"type":"response.created","response":{"object":"response","id":"gen-1764265411-Fu1iEX7h5MRWiL79lb94","created_at":1764265411,"status":"in_progress","error":null,"output_text":"","output":[],"model":"openai/gpt-oss-20b","incomplete_details":null,"max_tool_calls":null,"tools":[],"tool_choice":"auto","parallel_tool_calls":true,"max_output_tokens":null,"temperature":null,"top_p":null,"metadata":{},"background":false,"previous_response_id":null,"service_tier":"auto","truncation":null,"store":false,"instructions":null,"reasoning":null,"safety_identifier":null,"prompt_cache_key":null,"user":null},"sequence_number":0} + + data: {"type":"response.in_progress","response":{"object":"response","id":"gen-1764265411-Fu1iEX7h5MRWiL79lb94","created_at":1764265411,"status":"in_progress","error":null,"output_text":"","output":[],"model":"openai/gpt-oss-20b","incomplete_details":null,"max_tool_calls":null,"tools":[],"tool_choice":"auto","parallel_tool_calls":true,"max_output_tokens":null,"temperature":null,"top_p":null,"metadata":{},"background":false,"previous_response_id":null,"service_tier":"auto","truncation":null,"store":false,"instructions":null,"reasoning":null,"safety_identifier":null,"prompt_cache_key":null,"user":null},"sequence_number":1} + + data: {"type":"response.output_item.added","output_index":0,"item":{"type":"reasoning","id":"rs_tmp_2kbe7x16sax","summary":[]},"sequence_number":2} + + data: {"type":"response.content_part.added","item_id":"rs_tmp_2kbe7x16sax","output_index":0,"content_index":0,"part":{"type":"reasoning_text","text":""},"sequence_number":3} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"The","sequence_number":4} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" user","sequence_number":5} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" asks","sequence_number":6} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":":","sequence_number":7} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" \"","sequence_number":8} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"What","sequence_number":9} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" is","sequence_number":10} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" ","sequence_number":11} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"2","sequence_number":12} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"+","sequence_number":13} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"2","sequence_number":14} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"?\"","sequence_number":15} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" They","sequence_number":16} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" expect","sequence_number":17} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" a","sequence_number":18} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" straightforward","sequence_number":19} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" answer","sequence_number":20} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":":","sequence_number":21} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" ","sequence_number":22} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"4","sequence_number":23} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":".","sequence_number":24} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" Just","sequence_number":25} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" answer","sequence_number":26} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":" ","sequence_number":27} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":"4","sequence_number":28} + + data: {"type":"response.reasoning_text.delta","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"delta":".","sequence_number":29} + + data: {"type":"response.output_item.added","output_index":1,"item":{"type":"message","status":"in_progress","content":[],"id":"msg_tmp_8cjof4f6zpw","role":"assistant"},"sequence_number":30} + + data: {"type":"response.content_part.added","item_id":"msg_tmp_8cjof4f6zpw","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"text":""},"sequence_number":31} + + data: {"type":"response.output_text.delta","logprobs":[],"output_index":1,"item_id":"msg_tmp_8cjof4f6zpw","content_index":0,"delta":"4","sequence_number":32} + + data: {"type":"response.output_text.done","item_id":"msg_tmp_8cjof4f6zpw","output_index":1,"content_index":0,"text":"4","logprobs":[],"sequence_number":33} + + data: {"type":"response.content_part.done","item_id":"msg_tmp_8cjof4f6zpw","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"text":"4"},"sequence_number":34} + + data: {"type":"response.output_item.done","output_index":1,"item":{"type":"message","status":"completed","content":[{"type":"output_text","text":"4","annotations":[]}],"id":"msg_tmp_8cjof4f6zpw","role":"assistant"},"sequence_number":35} + + data: {"type":"response.reasoning_text.done","output_index":0,"item_id":"rs_tmp_2kbe7x16sax","content_index":0,"text":"The user asks: \"What is 2+2?\" They expect a straightforward answer: 4. Just answer 4.","sequence_number":36} + + data: {"type":"response.content_part.done","item_id":"rs_tmp_2kbe7x16sax","output_index":0,"content_index":0,"part":{"type":"reasoning_text","text":"The user asks: \"What is 2+2?\" They expect a straightforward answer: 4. Just answer 4."},"sequence_number":37} + + data: {"type":"response.output_item.done","output_index":0,"item":{"type":"reasoning","id":"rs_tmp_2kbe7x16sax","summary":[],"content":[{"type":"reasoning_text","text":"The user asks: \"What is 2+2?\" They expect a straightforward answer: 4. Just answer 4."}]},"sequence_number":38} + + data: {"type":"response.completed","response":{"object":"response","id":"gen-1764265411-Fu1iEX7h5MRWiL79lb94","created_at":1764265411,"model":"openai/gpt-oss-20b","status":"completed","output":[{"type":"reasoning","id":"rs_tmp_ku4i7pagjwn","summary":[],"content":[{"type":"reasoning_text","text":"The user asks: \"What is 2+2?\" They expect a straightforward answer: 4. Just answer 4."}]},{"type":"message","status":"completed","content":[{"type":"output_text","text":"4","annotations":[]}],"id":"msg_tmp_8cjof4f6zpw","role":"assistant"}],"output_text":"","error":null,"incomplete_details":null,"usage":{"input_tokens":78,"input_tokens_details":{"cached_tokens":0},"output_tokens":37,"output_tokens_details":{"reasoning_tokens":22},"total_tokens":115,"cost":0.0000113,"is_byok":false,"cost_details":{"upstream_inference_cost":null,"upstream_inference_input_cost":0.0000039,"upstream_inference_output_cost":0.0000074}},"max_tool_calls":null,"tools":[],"tool_choice":"auto","parallel_tool_calls":true,"max_output_tokens":null,"temperature":null,"top_p":null,"metadata":{},"background":false,"previous_response_id":null,"service_tier":"auto","truncation":null,"store":false,"instructions":null,"reasoning":null,"safety_identifier":null,"prompt_cache_key":null,"user":null},"sequence_number":39} + + data: [DONE] + + headers: + access-control-allow-origin: + - '*' + cache-control: + - no-cache + connection: + - keep-alive + content-type: + - text/event-stream + permissions-policy: + - payment=(self "https://checkout.stripe.com" "https://connect-js.stripe.com" "https://js.stripe.com" "https://*.js.stripe.com" + "https://hooks.stripe.com") + referrer-policy: + - no-referrer, strict-origin-when-cross-origin + transfer-encoding: + - chunked + vary: + - Accept-Encoding + status: + code: 200 + message: OK +version: 1 +... diff --git a/tests/models/test_instrumented.py b/tests/models/test_instrumented.py index b6a52e0c25..651a5b6a41 100644 --- a/tests/models/test_instrumented.py +++ b/tests/models/test_instrumented.py @@ -118,12 +118,10 @@ async def request_stream( class MyResponseStream(StreamedResponse): async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: self._usage = RequestUsage(input_tokens=300, output_tokens=400) - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=0, content='text1') - if maybe_event is not None: # pragma: no branch - yield maybe_event - maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=0, content='text2') - if maybe_event is not None: # pragma: no branch - yield maybe_event + for event in self._parts_manager.handle_text_delta(vendor_part_id=0, content='text1'): + yield event + for event in self._parts_manager.handle_text_delta(vendor_part_id=0, content='text2'): + yield event @property def model_name(self) -> str: diff --git a/tests/models/test_mistral.py b/tests/models/test_mistral.py index 4ae21ad221..32a56c6395 100644 --- a/tests/models/test_mistral.py +++ b/tests/models/test_mistral.py @@ -1901,13 +1901,13 @@ async def get_image() -> BinaryContent: run_id=IsStr(), ), ModelResponse( - parts=[ToolCallPart(tool_name='get_image', args='{}', tool_call_id='utZJMAZN4')], + parts=[ToolCallPart(tool_name='get_image', args='{}', tool_call_id='GJYBCIkcS')], usage=RequestUsage(input_tokens=65, output_tokens=16), model_name='pixtral-12b-latest', timestamp=IsDatetime(), provider_name='mistral', provider_details={'finish_reason': 'tool_calls'}, - provider_response_id='fce6d16a4e5940edb24ae16dd0369947', + provider_response_id='412174432ea945889703eac58b44ae35', finish_reason='tool_call', run_id=IsStr(), ), @@ -1916,7 +1916,7 @@ async def get_image() -> BinaryContent: ToolReturnPart( tool_name='get_image', content='See file 1c8566', - tool_call_id='utZJMAZN4', + tool_call_id='GJYBCIkcS', timestamp=IsDatetime(), ), UserPromptPart( @@ -1932,15 +1932,15 @@ async def get_image() -> BinaryContent: ModelResponse( parts=[ TextPart( - content='The image you\'re referring to, labeled as "file 1c8566," shows a kiwi. Kiwis are small, brown, oval-shaped fruits with a bright green flesh inside that is dotted with tiny black seeds. They have a sweet and tangy flavor and are known for being rich in vitamin C and fiber.' + content='The image you\'re referring to, labeled as "file 1c8566," shows a kiwi fruit that has been cut in half. The kiwi is known for its bright green flesh with tiny black seeds and a central white core. It is a popular fruit known for its sweet taste and nutritional benefits.' ) ], - usage=RequestUsage(input_tokens=2931, output_tokens=70), + usage=RequestUsage(input_tokens=2931, output_tokens=66), model_name='pixtral-12b-latest', timestamp=IsDatetime(), provider_name='mistral', provider_details={'finish_reason': 'stop'}, - provider_response_id='26e7de193646460e8904f8e604a60dc1', + provider_response_id='049b5c7704554d3396e727a95cb6d947', finish_reason='stop', run_id=IsStr(), ), @@ -2310,52 +2310,36 @@ async def test_mistral_model_thinking_part_iter(allow_model_requests: None, mist ModelResponse( parts=[ ThinkingPart( - content="""\ -Okay, the user is asking a very basic question about how to cross the street. This seems like a straightforward query, but I need to make sure I provide clear and safe instructions. Crossing the street safely involves a few key steps that are generally taught to children and are important for everyone to follow. - -First, I recall that the basic steps involve looking both ways for oncoming traffic, using designated crosswalks if available, and following traffic signals if there are any. But I should break it down into clear, actionable steps. - -1. **Find a Safe Place to Cross**: Ideally, you should cross at a designated crosswalk or intersection. These are typically marked with white lines on the road and may have traffic signals or signs. - -2. **Look Both Ways**: Before stepping off the curb, look left, right, and then left again to check for oncoming traffic. This is because in many places, traffic comes from the left first (depending on the country's driving side). - -3. **Wait for a Safe Gap**: Make sure there is enough time to cross the street before any vehicles approach. If there's a traffic light, wait for the pedestrian signal to indicate it's safe to cross. - -4. **Cross with Caution**: Walk briskly across the street while keeping an eye out for any unexpected vehicles. Avoid running unless absolutely necessary. - -5. **Continue Looking**: Even while crossing, continue to look for vehicles to ensure your safety. - -6. **Follow Traffic Signals**: If there are traffic lights or pedestrian signals, obey them. Only cross when the signal indicates it's safe to do so. - -Additionally, it's important to make eye contact with drivers if possible, to ensure they see you before you cross. Avoid distractions like using your phone while crossing the street. - -But wait, does the user need any specific context? For example, are they in a country where cars drive on the left or the right? That might affect the direction they should look first. However, since the user hasn't specified a location, I'll provide a general answer that should work in most places. - -Also, if the user is asking this question, they might be very young or unfamiliar with urban environments, so I should keep the instructions simple and clear. - -Here's a concise response based on this thinking:\ -""" + content='Okay, the user is asking how to cross the street. I know that crossing the street safely involves a few key steps: first, look both ways to check for oncoming traffic; second, use a crosswalk if one is available; third, obey any traffic signals or signs that may be present; and finally, proceed with caution until you have safely reached the other side. Let me compile this information into a clear and concise response.' ), TextPart( content="""\ To cross the street safely, follow these steps: -1. Find a designated crosswalk or intersection if possible. -2. Look left, right, and then left again to check for oncoming traffic. -3. Wait for a safe gap in traffic or for the pedestrian signal to indicate it's safe to cross. -4. Cross the street briskly while continuing to look for vehicles. -5. Follow any traffic signals and always be cautious of your surroundings. +1. Look both ways to check for oncoming traffic. +2. Use a crosswalk if one is available. +3. Obey any traffic signals or signs that may be present. +4. Proceed with caution until you have safely reached the other side. + +```markdown +To cross the street safely, follow these steps: + +1. Look both ways to check for oncoming traffic. +2. Use a crosswalk if one is available. +3. Obey any traffic signals or signs that may be present. +4. Proceed with caution until you have safely reached the other side. +``` -If you're in a country where cars drive on the left (like the UK or Japan), remember to look right first instead of left. Always prioritize your safety and make sure drivers see you before crossing.\ +By following these steps, you can ensure a safe crossing.\ """ ), ], - usage=RequestUsage(input_tokens=10, output_tokens=602), + usage=RequestUsage(input_tokens=10, output_tokens=232), model_name='magistral-medium-latest', timestamp=IsDatetime(), provider_name='mistral', provider_details={'finish_reason': 'stop'}, - provider_response_id='9faf4309c1d743d189f16b29211d8b45', + provider_response_id='9f9d90210f194076abeee223863eaaf0', finish_reason='stop', run_id=IsStr(), ), diff --git a/tests/models/test_openai_responses.py b/tests/models/test_openai_responses.py index fc72a48cb1..47bdeaea3f 100644 --- a/tests/models/test_openai_responses.py +++ b/tests/models/test_openai_responses.py @@ -53,7 +53,11 @@ with try_import() as imports_successful: from openai.types.responses.response_output_message import Content, ResponseOutputMessage, ResponseOutputText - from openai.types.responses.response_reasoning_item import ResponseReasoningItem, Summary + from openai.types.responses.response_reasoning_item import ( + Content as ReasoningContent, + ResponseReasoningItem, + Summary, + ) from openai.types.responses.response_usage import ResponseUsage from pydantic_ai.models.anthropic import AnthropicModel, AnthropicModelSettings @@ -7444,6 +7448,573 @@ def get_meaning_of_life() -> int: ) +async def test_openai_responses_raw_cot_only(allow_model_requests: None): + """Test raw CoT content from gpt-oss models (no summary, only raw content).""" + c = response_message( + [ + ResponseReasoningItem( + id='rs_123', + summary=[], + type='reasoning', + content=[ + ReasoningContent(text='Let me think about this...', type='reasoning_text'), + ReasoningContent(text='The answer is 4.', type='reasoning_text'), + ], + ), + ResponseOutputMessage( + id='msg_123', + content=cast(list[Content], [ResponseOutputText(text='4', type='output_text', annotations=[])]), + role='assistant', + status='completed', + type='message', + ), + ], + ) + mock_client = MockOpenAIResponses.create_mock(c) + model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(openai_client=mock_client)) + + agent = Agent(model=model) + result = await agent.run('What is 2+2?') + assert result.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='What is 2+2?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='', + id='rs_123', + provider_name='openai', + provider_details={'raw_content': ['Let me think about this...', 'The answer is 4.']}, + ), + TextPart(content='4', id='msg_123'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ] + ) + + +async def test_openai_responses_raw_cot_with_summary(allow_model_requests: None): + """Test raw CoT content with summary from gpt-oss models. + + When both summary and raw content exist, raw content is stored in provider_details + while summary goes in content. + """ + c = response_message( + [ + ResponseReasoningItem( + id='rs_123', + summary=[Summary(text='Summary of thinking', type='summary_text')], + type='reasoning', + encrypted_content='encrypted_sig', + content=[ + ReasoningContent(text='Raw thinking step 1', type='reasoning_text'), + ReasoningContent(text='Raw thinking step 2', type='reasoning_text'), + ], + ), + ResponseOutputMessage( + id='msg_123', + content=cast(list[Content], [ResponseOutputText(text='4', type='output_text', annotations=[])]), + role='assistant', + status='completed', + type='message', + ), + ], + ) + mock_client = MockOpenAIResponses.create_mock(c) + model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(openai_client=mock_client)) + + agent = Agent(model=model) + result = await agent.run('What is 2+2?') + assert result.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='What is 2+2?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='Summary of thinking', + id='rs_123', + signature='encrypted_sig', + provider_name='openai', + provider_details={'raw_content': ['Raw thinking step 1', 'Raw thinking step 2']}, + ), + TextPart(content='4', id='msg_123'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ] + ) + + +async def test_openai_responses_multiple_summaries(allow_model_requests: None): + """Test reasoning item with multiple summaries. + + When a reasoning item has multiple summary texts, each should become a separate ThinkingPart. + """ + c = response_message( + [ + ResponseReasoningItem( + id='rs_123', + summary=[ + Summary(text='First summary', type='summary_text'), + Summary(text='Second summary', type='summary_text'), + Summary(text='Third summary', type='summary_text'), + ], + type='reasoning', + encrypted_content='encrypted_sig', + content=[ + ReasoningContent(text='Raw thinking step 1', type='reasoning_text'), + ], + ), + ResponseOutputMessage( + id='msg_123', + content=cast(list[Content], [ResponseOutputText(text='Done', type='output_text', annotations=[])]), + role='assistant', + status='completed', + type='message', + ), + ], + ) + mock_client = MockOpenAIResponses.create_mock(c) + model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(openai_client=mock_client)) + + agent = Agent(model=model) + result = await agent.run('Test multiple summaries') + assert result.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='Test multiple summaries', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='First summary', + id='rs_123', + signature='encrypted_sig', + provider_name='openai', + provider_details={'raw_content': ['Raw thinking step 1']}, + ), + ThinkingPart(content='Second summary', id='rs_123'), + ThinkingPart(content='Third summary', id='rs_123'), + TextPart(content='Done', id='msg_123'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ] + ) + + +@pytest.mark.vcr() +async def test_openai_responses_raw_cot_stream_openrouter(allow_model_requests: None, openrouter_api_key: str): + """Test streaming raw CoT content from gpt-oss via OpenRouter. + + This is a live test (with cassette) that verifies the streaming raw CoT implementation + works end-to-end with a real gpt-oss model response. + """ + from pydantic_ai.providers.openrouter import OpenRouterProvider + + model = OpenAIResponsesModel('openai/gpt-oss-20b', provider=OpenRouterProvider(api_key=openrouter_api_key)) + agent = Agent(model=model) + async with agent.run_stream('What is 2+2?') as result: + output = await result.get_output() + assert output == snapshot('4') + assert result.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='What is 2+2?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='', + id='rs_tmp_2kbe7x16sax', + provider_details={ + 'raw_content': [ + 'The user asks: "What is 2+2?" They expect a straightforward answer: 4. Just answer 4.' + ] + }, + ), + TextPart(content='4', id='msg_tmp_8cjof4f6zpw'), + ], + usage=RequestUsage( + input_tokens=78, + output_tokens=37, + details={'is_byok': 0, 'reasoning_tokens': 22}, + ), + model_name='openai/gpt-oss-20b', + timestamp=IsDatetime(), + provider_name='openrouter', + provider_details={'finish_reason': 'completed'}, + provider_response_id='gen-1764265411-Fu1iEX7h5MRWiL79lb94', + finish_reason='stop', + run_id=IsStr(), + ), + ] + ) + + +async def test_openai_responses_raw_cot_sent_in_multiturn(allow_model_requests: None): + """Test that raw CoT and summaries are sent back correctly in multi-turn conversations. + + Tests three distinct cases across turns: + - Turn 1: Only raw content (no summary) - gpt-oss style + - Turn 2: Summary AND raw content - hybrid case + - Turn 3: Only summary (no raw content) - official OpenAI style + """ + # Track messages sent to OpenAI + sent_openai_messages: list[Any] = [] + + # Turn 1: Only raw content, no summary + c1 = response_message( + [ + ResponseReasoningItem( + id='rs_123', + summary=[], + type='reasoning', + content=[ + ReasoningContent(text='Raw CoT step 1', type='reasoning_text'), + ReasoningContent(text='Raw CoT step 2', type='reasoning_text'), + ], + ), + ResponseOutputMessage( + id='msg_123', + content=cast(list[Content], [ResponseOutputText(text='4', type='output_text', annotations=[])]), + role='assistant', + status='completed', + type='message', + ), + ], + ) + + # Turn 2: Summary and raw content + c2 = response_message( + [ + ResponseReasoningItem( + id='rs_456', + summary=[ + Summary(text='First summary', type='summary_text'), + Summary(text='Second summary', type='summary_text'), + ], + type='reasoning', + encrypted_content='encrypted_sig_abc', + content=[ + ReasoningContent(text='More raw thinking', type='reasoning_text'), + ], + ), + ResponseOutputMessage( + id='msg_456', + content=cast(list[Content], [ResponseOutputText(text='9', type='output_text', annotations=[])]), + role='assistant', + status='completed', + type='message', + ), + ], + ) + + # Turn 3: Only summary, no raw content + c3 = response_message( + [ + ResponseReasoningItem( + id='rs_789', + summary=[ + Summary(text='Final summary', type='summary_text'), + ], + type='reasoning', + encrypted_content='encrypted_sig_xyz', + content=[], + ), + ResponseOutputMessage( + id='msg_789', + content=cast(list[Content], [ResponseOutputText(text='42', type='output_text', annotations=[])]), + role='assistant', + status='completed', + type='message', + ), + ], + ) + + mock_client = MockOpenAIResponses.create_mock([c1, c2, c3]) + model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(openai_client=mock_client)) + + # Hook into model to capture sent messages + original_map_messages = model._map_messages # pyright: ignore[reportPrivateUsage] + + async def capture_messages(*args: Any, **kwargs: Any) -> Any: + result = await original_map_messages(*args, **kwargs) + sent_openai_messages.append(result[1]) # result is (instructions, messages) + return result + + model._map_messages = capture_messages # type: ignore[method-assign] + + agent = Agent(model=model) + + # Turn 1: Only raw content, no summary + result1 = await agent.run('What is 2+2?') + assert result1.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='What is 2+2?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='', + id='rs_123', + provider_name='openai', + provider_details={'raw_content': ['Raw CoT step 1', 'Raw CoT step 2']}, + ), + TextPart(content='4', id='msg_123'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ] + ) + + # Turn 2: Summary and raw content + result2 = await agent.run('Add 5 to that', message_history=result1.all_messages()) + assert result2.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='What is 2+2?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='', + id='rs_123', + provider_name='openai', + provider_details={'raw_content': ['Raw CoT step 1', 'Raw CoT step 2']}, + ), + TextPart(content='4', id='msg_123'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ModelRequest( + parts=[ + UserPromptPart( + content='Add 5 to that', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='First summary', + id='rs_456', + signature='encrypted_sig_abc', + provider_name='openai', + provider_details={'raw_content': ['More raw thinking']}, + ), + ThinkingPart(content='Second summary', id='rs_456'), + TextPart(content='9', id='msg_456'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ] + ) + + # Turn 3: Only summary, no raw content + result3 = await agent.run('What next?', message_history=result2.all_messages()) + assert result3.all_messages() == snapshot( + [ + ModelRequest( + parts=[ + UserPromptPart( + content='What is 2+2?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='', + id='rs_123', + provider_name='openai', + provider_details={'raw_content': ['Raw CoT step 1', 'Raw CoT step 2']}, + ), + TextPart(content='4', id='msg_123'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ModelRequest( + parts=[ + UserPromptPart( + content='Add 5 to that', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='First summary', + id='rs_456', + signature='encrypted_sig_abc', + provider_name='openai', + provider_details={'raw_content': ['More raw thinking']}, + ), + ThinkingPart(content='Second summary', id='rs_456'), + TextPart(content='9', id='msg_456'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ModelRequest( + parts=[ + UserPromptPart( + content='What next?', + timestamp=IsDatetime(), + ) + ], + run_id=IsStr(), + ), + ModelResponse( + parts=[ + ThinkingPart( + content='Final summary', + id='rs_789', + signature='encrypted_sig_xyz', + provider_name='openai', + ), + TextPart(content='42', id='msg_789'), + ], + model_name='gpt-4o-123', + timestamp=IsDatetime(), + provider_name='openai', + provider_response_id='123', + run_id=IsStr(), + ), + ] + ) + + # Verify what was sent to the API in each turn + assert len(sent_openai_messages) == 3 + + # Turn 2 messages: should contain raw-only reasoning item from turn 1 + turn2_messages = sent_openai_messages[1] + turn2_reasoning = [msg for msg in turn2_messages if msg.get('type') == 'reasoning'] + assert len(turn2_reasoning) == 1 + assert turn2_reasoning[0] == snapshot( + { + 'type': 'reasoning', + 'summary': [], + 'encrypted_content': None, + 'id': 'rs_123', + 'content': [ + {'type': 'reasoning_text', 'text': 'Raw CoT step 1'}, + {'type': 'reasoning_text', 'text': 'Raw CoT step 2'}, + ], + } + ) + + # Turn 3 messages: should contain both reasoning items + turn3_messages = sent_openai_messages[2] + turn3_reasoning = [msg for msg in turn3_messages if msg.get('type') == 'reasoning'] + assert len(turn3_reasoning) == 2 + assert turn3_reasoning[0] == snapshot( + { + 'type': 'reasoning', + 'summary': [], + 'encrypted_content': None, + 'id': 'rs_123', + 'content': [ + {'type': 'reasoning_text', 'text': 'Raw CoT step 1'}, + {'type': 'reasoning_text', 'text': 'Raw CoT step 2'}, + ], + } + ) + assert turn3_reasoning[1] == snapshot( + { + 'type': 'reasoning', + 'summary': [ + {'type': 'summary_text', 'text': 'First summary'}, + {'type': 'summary_text', 'text': 'Second summary'}, + ], + 'encrypted_content': 'encrypted_sig_abc', + 'id': 'rs_456', + 'content': [ + {'type': 'reasoning_text', 'text': 'More raw thinking'}, + ], + } + ) + + @pytest.mark.vcr() async def test_openai_responses_runs_with_instructions_only( allow_model_requests: None, diff --git a/tests/test_messages.py b/tests/test_messages.py index d6d9617247..f116502882 100644 --- a/tests/test_messages.py +++ b/tests/test_messages.py @@ -373,6 +373,39 @@ def test_thinking_part_delta_apply_to_thinking_part_delta(): assert isinstance(result, ThinkingPartDelta) assert result.provider_details == {'foo': 'qux', 'baz': 'qux', 'finish_reason': 'STOP'} + # Test chaining callable provider_details in delta-to-delta + delta1 = ThinkingPartDelta( + content_delta='first', + provider_details=lambda d: {**(d or {}), 'first': 1}, + ) + delta2 = ThinkingPartDelta( + content_delta=' second', + provider_details=lambda d: {**(d or {}), 'second': 2}, + ) + chained = delta2.apply(delta1) + assert isinstance(chained, ThinkingPartDelta) + assert callable(chained.provider_details) + # Apply chained delta to actual ThinkingPart to verify both callables ran + part = ThinkingPart(content='') + result_part = chained.apply(part) + assert result_part.provider_details == {'first': 1, 'second': 2} + + # Test applying dict delta to callable delta (dict should merge with callable result) + delta_callable = ThinkingPartDelta( + content_delta='callable', + provider_details=lambda d: {**(d or {}), 'from_callable': 'yes'}, + ) + delta_dict = ThinkingPartDelta( + content_delta=' dict', + provider_details={'from_dict': 'also'}, + ) + chained = delta_dict.apply(delta_callable) + assert isinstance(chained, ThinkingPartDelta) + assert callable(chained.provider_details) + part = ThinkingPart(content='') + result_part = chained.apply(part) + assert result_part.provider_details == {'from_callable': 'yes', 'from_dict': 'also'} + def test_pre_usage_refactor_messages_deserializable(): # https://github.com/pydantic/pydantic-ai/pull/2378 changed the `ModelResponse` fields, diff --git a/tests/test_parts_manager.py b/tests/test_parts_manager.py index 59ce3e31a9..3c39061356 100644 --- a/tests/test_parts_manager.py +++ b/tests/test_parts_manager.py @@ -28,13 +28,13 @@ def test_handle_text_deltas(vendor_part_id: str | None): manager = ModelResponsePartsManager() assert manager.get_parts() == [] - event = manager.handle_text_delta(vendor_part_id=vendor_part_id, content='hello ') + event = next(manager.handle_text_delta(vendor_part_id=vendor_part_id, content='hello ')) assert event == snapshot( PartStartEvent(index=0, part=TextPart(content='hello ', part_kind='text'), event_kind='part_start') ) assert manager.get_parts() == snapshot([TextPart(content='hello ', part_kind='text')]) - event = manager.handle_text_delta(vendor_part_id=vendor_part_id, content='world') + event = next(manager.handle_text_delta(vendor_part_id=vendor_part_id, content='world')) assert event == snapshot( PartDeltaEvent( index=0, delta=TextPartDelta(content_delta='world', part_delta_kind='text'), event_kind='part_delta' @@ -46,13 +46,13 @@ def test_handle_text_deltas(vendor_part_id: str | None): def test_handle_dovetailed_text_deltas(): manager = ModelResponsePartsManager() - event = manager.handle_text_delta(vendor_part_id='first', content='hello ') + event = next(manager.handle_text_delta(vendor_part_id='first', content='hello ')) assert event == snapshot( PartStartEvent(index=0, part=TextPart(content='hello ', part_kind='text'), event_kind='part_start') ) assert manager.get_parts() == snapshot([TextPart(content='hello ', part_kind='text')]) - event = manager.handle_text_delta(vendor_part_id='second', content='goodbye ') + event = next(manager.handle_text_delta(vendor_part_id='second', content='goodbye ')) assert event == snapshot( PartStartEvent(index=1, part=TextPart(content='goodbye ', part_kind='text'), event_kind='part_start') ) @@ -60,7 +60,7 @@ def test_handle_dovetailed_text_deltas(): [TextPart(content='hello ', part_kind='text'), TextPart(content='goodbye ', part_kind='text')] ) - event = manager.handle_text_delta(vendor_part_id='first', content='world') + event = next(manager.handle_text_delta(vendor_part_id='first', content='world')) assert event == snapshot( PartDeltaEvent( index=0, delta=TextPartDelta(content_delta='world', part_delta_kind='text'), event_kind='part_delta' @@ -70,7 +70,7 @@ def test_handle_dovetailed_text_deltas(): [TextPart(content='hello world', part_kind='text'), TextPart(content='goodbye ', part_kind='text')] ) - event = manager.handle_text_delta(vendor_part_id='second', content='Samuel') + event = next(manager.handle_text_delta(vendor_part_id='second', content='Samuel')) assert event == snapshot( PartDeltaEvent( index=1, delta=TextPartDelta(content_delta='Samuel', part_delta_kind='text'), event_kind='part_delta' @@ -85,13 +85,13 @@ def test_handle_text_deltas_with_think_tags(): manager = ModelResponsePartsManager() thinking_tags = ('', '') - event = manager.handle_text_delta(vendor_part_id='content', content='pre-', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content='pre-', thinking_tags=thinking_tags)) assert event == snapshot( PartStartEvent(index=0, part=TextPart(content='pre-', part_kind='text'), event_kind='part_start') ) assert manager.get_parts() == snapshot([TextPart(content='pre-', part_kind='text')]) - event = manager.handle_text_delta(vendor_part_id='content', content='thinking', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content='thinking', thinking_tags=thinking_tags)) assert event == snapshot( PartDeltaEvent( index=0, delta=TextPartDelta(content_delta='thinking', part_delta_kind='text'), event_kind='part_delta' @@ -99,7 +99,7 @@ def test_handle_text_deltas_with_think_tags(): ) assert manager.get_parts() == snapshot([TextPart(content='pre-thinking', part_kind='text')]) - event = manager.handle_text_delta(vendor_part_id='content', content='', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content='', thinking_tags=thinking_tags)) assert event == snapshot( PartStartEvent(index=1, part=ThinkingPart(content='', part_kind='thinking'), event_kind='part_start') ) @@ -107,7 +107,7 @@ def test_handle_text_deltas_with_think_tags(): [TextPart(content='pre-thinking', part_kind='text'), ThinkingPart(content='', part_kind='thinking')] ) - event = manager.handle_text_delta(vendor_part_id='content', content='thinking', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content='thinking', thinking_tags=thinking_tags)) assert event == snapshot( PartDeltaEvent( index=1, @@ -119,7 +119,7 @@ def test_handle_text_deltas_with_think_tags(): [TextPart(content='pre-thinking', part_kind='text'), ThinkingPart(content='thinking', part_kind='thinking')] ) - event = manager.handle_text_delta(vendor_part_id='content', content=' more', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content=' more', thinking_tags=thinking_tags)) assert event == snapshot( PartDeltaEvent( index=1, delta=ThinkingPartDelta(content_delta=' more', part_delta_kind='thinking'), event_kind='part_delta' @@ -132,10 +132,10 @@ def test_handle_text_deltas_with_think_tags(): ] ) - event = manager.handle_text_delta(vendor_part_id='content', content='', thinking_tags=thinking_tags) - assert event is None + events = list(manager.handle_text_delta(vendor_part_id='content', content='', thinking_tags=thinking_tags)) + assert events == [] - event = manager.handle_text_delta(vendor_part_id='content', content='post-', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content='post-', thinking_tags=thinking_tags)) assert event == snapshot( PartStartEvent(index=2, part=TextPart(content='post-', part_kind='text'), event_kind='part_start') ) @@ -147,7 +147,7 @@ def test_handle_text_deltas_with_think_tags(): ] ) - event = manager.handle_text_delta(vendor_part_id='content', content='thinking', thinking_tags=thinking_tags) + event = next(manager.handle_text_delta(vendor_part_id='content', content='thinking', thinking_tags=thinking_tags)) assert event == snapshot( PartDeltaEvent( index=2, delta=TextPartDelta(content_delta='thinking', part_delta_kind='text'), event_kind='part_delta' @@ -376,7 +376,7 @@ def test_handle_tool_call_part(): def test_handle_mixed_deltas_without_text_part_id(text_vendor_part_id: str | None, tool_vendor_part_id: str | None): manager = ModelResponsePartsManager() - event = manager.handle_text_delta(vendor_part_id=text_vendor_part_id, content='hello ') + event = next(manager.handle_text_delta(vendor_part_id=text_vendor_part_id, content='hello ')) assert event == snapshot( PartStartEvent(index=0, part=TextPart(content='hello ', part_kind='text'), event_kind='part_start') ) @@ -393,7 +393,7 @@ def test_handle_mixed_deltas_without_text_part_id(text_vendor_part_id: str | Non ) ) - event = manager.handle_text_delta(vendor_part_id=text_vendor_part_id, content='world') + event = next(manager.handle_text_delta(vendor_part_id=text_vendor_part_id, content='world')) if text_vendor_part_id is None: assert event == snapshot( PartStartEvent( @@ -425,7 +425,7 @@ def test_handle_mixed_deltas_without_text_part_id(text_vendor_part_id: str | Non def test_cannot_convert_from_text_to_tool_call(): manager = ModelResponsePartsManager() - manager.handle_text_delta(vendor_part_id=1, content='hello') + list(manager.handle_text_delta(vendor_part_id=1, content='hello')) with pytest.raises( UnexpectedModelBehavior, match=re.escape('Cannot apply a tool call delta to existing_part=TextPart(') ): @@ -438,7 +438,7 @@ def test_cannot_convert_from_tool_call_to_text(): with pytest.raises( UnexpectedModelBehavior, match=re.escape('Cannot apply a text delta to existing_part=ToolCallPart(') ): - manager.handle_text_delta(vendor_part_id=1, content='hello') + list(manager.handle_text_delta(vendor_part_id=1, content='hello')) def test_tool_call_id_delta(): @@ -529,12 +529,12 @@ def test_handle_thinking_delta_no_vendor_id_with_existing_thinking_part(): manager = ModelResponsePartsManager() # Add a thinking part first - event = manager.handle_thinking_delta(vendor_part_id='first', content='initial thought', signature=None) + event = next(manager.handle_thinking_delta(vendor_part_id='first', content='initial thought', signature=None)) assert isinstance(event, PartStartEvent) assert event.index == 0 # Now add another thinking delta with no vendor_part_id - should update the latest thinking part - event = manager.handle_thinking_delta(vendor_part_id=None, content=' more', signature=None) + event = next(manager.handle_thinking_delta(vendor_part_id=None, content=' more', signature=None)) assert isinstance(event, PartDeltaEvent) assert event.index == 0 @@ -546,17 +546,17 @@ def test_handle_thinking_delta_wrong_part_type(): manager = ModelResponsePartsManager() # Add a text part first - manager.handle_text_delta(vendor_part_id='text', content='hello') + list(manager.handle_text_delta(vendor_part_id='text', content='hello')) # Try to apply thinking delta to the text part - should raise error with pytest.raises(UnexpectedModelBehavior, match=r'Cannot apply a thinking delta to existing_part='): - manager.handle_thinking_delta(vendor_part_id='text', content='thinking', signature=None) + list(manager.handle_thinking_delta(vendor_part_id='text', content='thinking', signature=None)) def test_handle_thinking_delta_new_part_with_vendor_id(): manager = ModelResponsePartsManager() - event = manager.handle_thinking_delta(vendor_part_id='thinking', content='new thought', signature=None) + event = next(manager.handle_thinking_delta(vendor_part_id='thinking', content='new thought', signature=None)) assert isinstance(event, PartStartEvent) assert event.index == 0 @@ -568,18 +568,56 @@ def test_handle_thinking_delta_no_content(): manager = ModelResponsePartsManager() with pytest.raises(UnexpectedModelBehavior, match='Cannot create a ThinkingPart with no content'): - manager.handle_thinking_delta(vendor_part_id=None, content=None, signature=None) + list(manager.handle_thinking_delta(vendor_part_id=None, content=None, signature=None)) def test_handle_thinking_delta_no_content_or_signature(): manager = ModelResponsePartsManager() # Add a thinking part first - manager.handle_thinking_delta(vendor_part_id='thinking', content='initial', signature=None) + list(manager.handle_thinking_delta(vendor_part_id='thinking', content='initial', signature=None)) - # Try to update with no content or signature - should raise error - with pytest.raises(UnexpectedModelBehavior, match='Cannot update a ThinkingPart with no content or signature'): - manager.handle_thinking_delta(vendor_part_id='thinking', content=None, signature=None) + # Updating with no content, signature, or provider_details emits no event + events = list(manager.handle_thinking_delta(vendor_part_id='thinking', content=None, signature=None)) + assert events == [] + + +def test_handle_thinking_delta_provider_details_callback(): + """Test that provider_details can be a callback function.""" + manager = ModelResponsePartsManager() + + # Create initial part with provider_details + list(manager.handle_thinking_delta(vendor_part_id='t', content='initial', provider_details={'count': 1})) + + # Update using callback to modify provider_details + def update_details(existing: dict[str, Any] | None) -> dict[str, Any]: + details = dict(existing or {}) + details['count'] = details.get('count', 0) + 1 + return details + + list(manager.handle_thinking_delta(vendor_part_id='t', content=' more', provider_details=update_details)) + + assert manager.get_parts() == snapshot([ThinkingPart(content='initial more', provider_details={'count': 2})]) + + +def test_handle_thinking_delta_provider_details_callback_from_none(): + """Test callback when existing provider_details is None.""" + manager = ModelResponsePartsManager() + + # Create initial part without provider_details + list(manager.handle_thinking_delta(vendor_part_id='t', content='initial')) + + # Update using callback that handles None + def add_details(existing: dict[str, Any] | None) -> dict[str, Any]: + details = dict(existing or {}) + details['new_key'] = 'new_value' + return details + + list(manager.handle_thinking_delta(vendor_part_id='t', content=' more', provider_details=add_details)) + + assert manager.get_parts() == snapshot( + [ThinkingPart(content='initial more', provider_details={'new_key': 'new_value'})] + ) def test_handle_part():