Conversation
|
🧪 Testing To try out this version of the SDK, run: Expires at: Sun, 15 Mar 2026 00:06:55 GMT |
ac5c5d9 to
c72a9be
Compare
c72a9be to
00246c5
Compare
| *, | ||
| cast_to: Type[ResponseT], | ||
| body: Body | None = None, | ||
| content: BinaryTypes | None = None, |
There was a problem hiding this comment.
Iterator content silently lost on request retry
Medium Severity
When content is an Iterable[bytes] (like a generator), the iterator is consumed on the first request attempt. If a retryable error occurs, the retry logic uses model_copy which performs a shallow copy, so options.content still references the same exhausted iterator. Subsequent retry attempts send an empty request body. This is exacerbated by DEFAULT_MAX_RETRIES being increased from 0 to 2 in this same PR. Users passing generator-based content could experience silent data loss on transient failures.
Additional Locations (1)
00246c5 to
f4bfcf4
Compare
f4bfcf4 to
120f4f7
Compare
120f4f7 to
b02a9df
Compare
PR SummaryMedium Risk Overview Adds new API surface: Updates the HTTP layer to support raw/binary request bodies via a new Refactors the runner to pass through a wider set of chat-completions parameters, preserves CI/release workflows are updated (checkout v6, github-script v8, PyPI workflow now targets Written by Cursor Bugbot for commit afba00e. This will update automatically on new commits. Configure here. |
b02a9df to
3c98764
Compare
| [], | ||
| steps, | ||
| verbose=exec_config.verbose, | ||
| ) |
There was a problem hiding this comment.
Missing assistant message before tool execution in streaming paths
High Severity
Both streaming paths (_execute_streaming_async and _execute_streaming_sync) call the scheduler's execute_local_tools_async/execute_local_tools_sync without first appending an assistant message with tool_calls to the messages list. The scheduler's own docstring explicitly states the caller is responsible for this. The non-streaming paths (_execute_tool_calls at line 1204, _execute_tool_calls_sync at line 1229) correctly append {"role": "assistant", "tool_calls": ...} before calling the scheduler. The old streaming code also did this but the line was removed during the refactoring. This produces a malformed conversation (tool messages without a preceding assistant message), which will cause the API to reject subsequent requests.
Additional Locations (1)
| # Collect MCP tool results emitted by the server | ||
| chunk_extra = getattr(chunk, "__pydantic_extra__", None) or {} | ||
| if isinstance(chunk_extra, dict) and "mcp_tool_results" in chunk_extra: | ||
| mcp_tool_results_from_server = chunk_extra["mcp_tool_results"] |
There was a problem hiding this comment.
Collected MCP tool results variable is never used
Low Severity
mcp_tool_results_from_server is assigned in both _execute_streaming_async and _execute_streaming_sync but is never read after assignment. The variable is dead code — the collected MCP tool results are silently discarded. Given the PR includes a fix for "inject server tool results into conversation for mixed tool calls," this may represent an incomplete implementation for the streaming paths.
Additional Locations (1)
This comment has been minimized.
This comment has been minimized.
3c98764 to
b8e048e
Compare
b8e048e to
a3df0b4
Compare
a3df0b4 to
d04fc33
Compare
d04fc33 to
2fef7e6
Compare
2fef7e6 to
1ca826f
Compare
This comment has been minimized.
This comment has been minimized.
Stainless regen (2026-02-07) added `by_alias=by_alias` but a manually added `by_alias=True` from Nov 2025 was still present. Duplicate keyword arguments are a SyntaxError on Python 3.9.
stream_async and stream_sync now accumulate content and tool-call deltas into a StreamResult dataclass and return it. The accumulation logic is extracted into a shared accumulate_tool_call() function that DedalusRunner.core also delegates to (DRY). Exports StreamResult and accumulate_tool_call from dedalus_labs.utils.stream. Adds tests covering content, tool-call reassembly, thought_signature, parallel calls, empty streams, and result independence.
Standardise hand-written test files (test_encryption, test_mcp_wire, test_mcp_wire_connections, test__bug_report) to match the module-level function style used in test_local_scheduler. Replaces class wrappers and multi-line banners with single-line section comments.
1ca826f to
f20bb1f
Compare
f20bb1f to
36b0123
Compare
36b0123 to
afba00e
Compare
| exclude=exclude, | ||
| exclude_unset=exclude_unset, | ||
| exclude_defaults=exclude_defaults, | ||
| exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias) |
There was a problem hiding this comment.
Default by_alias change breaks request serialization of aliased fields
Medium Severity
The model_dump helper in _compat.py changed its by_alias default from hardcoded True to None (effectively False). The _transform_recursive function in _transform.py calls model_dump(data, exclude_unset=True, mode="json") without passing by_alias, relying on the previous default. This breaks serialization of Pydantic models with field aliases — notably JSONSchema.schema_ (aliased to "schema") will now serialize as "schema_" instead of "schema", sending incorrect field names to the API.
|
Bugbot Autofix prepared fixes for 1 of the 1 bugs found in the latest run.
Or push these changes by commenting: Preview (018c6c55a4)diff --git a/src/dedalus_labs/_compat.py b/src/dedalus_labs/_compat.py
--- a/src/dedalus_labs/_compat.py
+++ b/src/dedalus_labs/_compat.py
@@ -139,7 +139,7 @@
exclude_defaults: bool = False,
warnings: bool = True,
mode: Literal["json", "python"] = "python",
- by_alias: bool | None = None,
+ by_alias: bool = True,
) -> dict[str, Any]:
if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
return model.model_dump(
@@ -154,7 +154,7 @@
return cast(
"dict[str, Any]",
model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
- exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias)
+ exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=by_alias
),
) |



Automated Release PR
0.3.0 (2026-02-13)
Full Changelog: v0.2.0...v0.3.0
Features
Bug Fixes
Chores
actions/github-script(cf53a9e)api.mdfiles (ead37d4)actions/checkoutversion (c72dfca)Styles
This pull request is managed by Stainless's GitHub App.
The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.
For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.
🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions