fix(oci): polish stream chunk handling and signed body default

- cohere stream terminal consolidation now emits content=None instead of ""
- drop redundant index truthiness check (None is already replaced with 0)
- accept both "TOOL_CALL" and "TOOL_CALLS" finish reasons in cohere
- signed_json_body defaults to None and uses explicit None check, so an
  explicitly empty bytes body wouldn't be silently re-serialized

Co-authored-by: Yassin Kortam <yassin@berri.ai>
This commit is contained in:
Cursor Agent 2026-05-21 06:05:48 +00:00
parent 1e45b63949
commit 1c6cd61311
No known key found for this signature in database
4 changed files with 23 additions and 13 deletions

View file

@ -214,7 +214,7 @@ def handle_cohere_response(
finish_reason = "stop"
elif oci_finish_reason == "MAX_TOKENS":
finish_reason = "length"
elif oci_finish_reason == "TOOL_CALL":
elif oci_finish_reason in ("TOOL_CALL", "TOOL_CALLS"):
finish_reason = "tool_calls"
elif oci_finish_reason is not None:
# OCI Cohere can emit error/cancel finish reasons (e.g. ``ERROR``,
@ -291,7 +291,9 @@ def handle_cohere_stream_chunk(dict_chunk: dict) -> ModelResponseStream:
is_terminal_consolidation = (
typed_chunk.chatHistory is not None and typed_chunk.finishReason is not None
)
text = "" if is_terminal_consolidation else (typed_chunk.text or "")
text: Optional[str] = (
None if is_terminal_consolidation else (typed_chunk.text or "")
)
# Tool calls on the terminal consolidation chunk (whether from
# `typed_chunk.toolCalls` or from `chatHistory`) restate what was already
@ -326,7 +328,7 @@ def handle_cohere_stream_chunk(dict_chunk: dict) -> ModelResponseStream:
finish_reason = "stop"
elif finish_reason == "MAX_TOKENS":
finish_reason = "length"
elif finish_reason == "TOOL_CALL":
elif finish_reason in ("TOOL_CALL", "TOOL_CALLS"):
finish_reason = "tool_calls"
elif finish_reason is not None:
# OCI Cohere can emit error/cancel finish reasons (e.g. ``ERROR``,
@ -338,7 +340,7 @@ def handle_cohere_stream_chunk(dict_chunk: dict) -> ModelResponseStream:
return ModelResponseStream(
choices=[
StreamingChoices(
index=typed_chunk.index if typed_chunk.index else 0,
index=typed_chunk.index,
delta=Delta(
content=text,
tool_calls=tool_calls,

View file

@ -432,7 +432,7 @@ def handle_generic_stream_chunk(dict_chunk: dict) -> ModelResponseStream:
return ModelResponseStream(
choices=[
StreamingChoices(
index=typed_chunk.index if typed_chunk.index else 0,
index=typed_chunk.index,
delta=Delta(
content=text,
tool_calls=(

View file

@ -565,7 +565,7 @@ class OCIChatConfig(BaseConfig):
messages: list,
client: Optional[Union[HTTPHandler, AsyncHTTPHandler]] = None,
json_mode: Optional[bool] = None,
signed_json_body: bytes = b"",
signed_json_body: Optional[bytes] = None,
) -> "OCIStreamWrapper":
if "stream" in data:
del data["stream"]
@ -576,7 +576,11 @@ class OCIChatConfig(BaseConfig):
response = client.post(
api_base,
headers=headers,
data=signed_json_body or json.dumps(data),
data=(
signed_json_body
if signed_json_body is not None
else json.dumps(data)
),
stream=True,
logging_obj=logging_obj,
timeout=STREAMING_TIMEOUT,
@ -606,7 +610,7 @@ class OCIChatConfig(BaseConfig):
messages: list,
client: Optional[Union[HTTPHandler, AsyncHTTPHandler]] = None,
json_mode: Optional[bool] = None,
signed_json_body: bytes = b"",
signed_json_body: Optional[bytes] = None,
) -> "OCIStreamWrapper":
if "stream" in data:
del data["stream"]
@ -617,7 +621,11 @@ class OCIChatConfig(BaseConfig):
response = await client.post(
api_base,
headers=headers,
data=signed_json_body or json.dumps(data),
data=(
signed_json_body
if signed_json_body is not None
else json.dumps(data)
),
stream=True,
logging_obj=logging_obj,
timeout=STREAMING_TIMEOUT,

View file

@ -614,7 +614,7 @@ def test_handle_cohere_stream_chunk_complete():
}
result = handle_cohere_stream_chunk(chunk)
assert result.choices[0].finish_reason == "stop"
assert result.choices[0].delta.content == ""
assert result.choices[0].delta.content is None
def test_handle_cohere_stream_chunk_max_tokens():
@ -626,7 +626,7 @@ def test_handle_cohere_stream_chunk_max_tokens():
}
result = handle_cohere_stream_chunk(chunk)
assert result.choices[0].finish_reason == "length"
assert result.choices[0].delta.content == ""
assert result.choices[0].delta.content is None
def test_handle_cohere_stream_chunk_tool_call():
@ -638,7 +638,7 @@ def test_handle_cohere_stream_chunk_tool_call():
}
result = handle_cohere_stream_chunk(chunk)
assert result.choices[0].finish_reason == "tool_calls"
assert result.choices[0].delta.content == ""
assert result.choices[0].delta.content is None
def test_handle_cohere_stream_chunk_terminal_drops_full_response_text():
@ -658,7 +658,7 @@ def test_handle_cohere_stream_chunk_terminal_drops_full_response_text():
],
}
result = handle_cohere_stream_chunk(chunk)
assert result.choices[0].delta.content == ""
assert result.choices[0].delta.content is None
def test_handle_cohere_stream_chunk_incremental_passes_text_through():