Conversation
|
Caution Review failedThe pull request is closed. WalkthroughThe PR bumps the package version and updates many dependency versions (core haiway and several provider libs), adds a new gemini optional group, refactors public exports (removing several deprecated symbols and adding ContextIdentifier/ContextMissing/ContextPresets/ContextStateMissing), replaces MissingState with ContextStateMissing, changes Disposables usage to plain Collection[Disposable] with empty-iterable defaults, simplifies lifespan/disposable handling in server and stage modules, fixes a headers.get call, and updates tests to use hyphenated UUIDs. Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (9)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
188bb3a to
89c6a59
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @pyproject.toml:
- Line 27: Update the haiway dependency in the pyproject.toml dependencies
entry: replace the unavailable version spec "haiway~=0.42" with a valid released
version like "haiway~=0.40" (or pin to the latest available 0.40.x, e.g.,
0.40.2) so the dependencies line (dependencies = ["numpy~=2.3", "haiway~=0.40"])
references a PyPI-released version.
- Line 41: The gemini dependency group currently pins google-genai but leaves
google-api-core unpinned; update the gemini entry in pyproject.toml to pin
google-api-core (for example to ~=2.29.0 or another appropriate 2.x constraint)
so the indirect import google.api_core.exceptions.ResourceExhausted has a
guaranteed compatible version, then regenerate the lockfile (poetry lock /
pip-compile) to lock this change.
📜 Review details
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
pyproject.tomlsrc/draive/__init__.pysrc/draive/mcp/server.pysrc/draive/resources/http.pysrc/draive/stages/stage.pysrc/draive/stages/types.pytests/test_model.pytests/test_stage.pytests/test_toolbox.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no looseAnyunless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamicgetattrexcept at narrow boundaries
In public types, prefer abstract immutable protocols likeMapping,Sequence,Iterableover concretedict,list,set
Usefinalwhere applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow withmatch/isinstance; avoidcastunless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols likeHTTPRequestingto keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and usectx.spawnfor detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider,operation, identifiers) while redacting sensitive payloads
Don't raise bareException; preserve contextual information in exception construction
Use observability hooks (ctx.log_*,ctx.record) fromctxhelper instead oflogging; tests assert on emitted events
Files:
tests/test_stage.pysrc/draive/__init__.pysrc/draive/mcp/server.pytests/test_toolbox.pytests/test_model.pysrc/draive/stages/types.pysrc/draive/resources/http.pysrc/draive/stages/stage.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout intests/; colocate new tests alongside features and preferpytestparametrization over loops
Test async flows withpytest.mark.asyncio; usectx.scopein tests to isolate state and avoid leaking globals
Files:
tests/test_stage.pytests/test_toolbox.pytests/test_model.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import symbols fromdraivedirectly (e.g.,from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scopedDisposables, activeStateinstances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings
Files:
src/draive/__init__.pysrc/draive/mcp/server.pysrc/draive/stages/types.pysrc/draive/resources/http.pysrc/draive/stages/stage.py
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
Centralize public exports in
src/draive/__init__.py; update this file when adding or modifying public APIs
Files:
src/draive/__init__.py
🧠 Learnings (6)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs
Applied to files:
src/draive/__init__.pypyproject.toml
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Use context scoping (`ctx.scope(...)`) to bind scoped `Disposables`, active `State` instances, and avoid global state
Applied to files:
src/draive/__init__.pysrc/draive/stages/stage.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Import symbols from `draive` directly (e.g., `from draive import State, ctx`) rather than internal module paths
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.
Applied to files:
pyproject.toml
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Draive is built on top of Haiway for state, context, observability, and config management; understand and leverage its abstractions
Applied to files:
pyproject.toml
📚 Learning: 2025-05-28T17:41:57.460Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 327
File: src/draive/helpers/instruction_preparation.py:28-34
Timestamp: 2025-05-28T17:41:57.460Z
Learning: The draive project uses and requires Python 3.12+, so PEP-695 generic syntax with square brackets (e.g., `def func[T: Type]()`) is valid and should be used instead of the older TypeVar approach.
Applied to files:
pyproject.toml
🧬 Code graph analysis (2)
tests/test_toolbox.py (3)
src/draive/models/tools/function.py (4)
tool(390-409)tool(413-459)tool(463-505)tool(508-538)src/draive/models/tools/types.py (1)
handling(92-92)src/draive/models/types.py (1)
wait(196-202)
src/draive/stages/stage.py (3)
src/draive/stages/types.py (2)
StageState(30-269)updated(208-241)src/draive/models/tools/function.py (1)
updated(160-215)src/draive/parameters/model.py (1)
updated(486-490)
🔇 Additional comments (18)
src/draive/resources/http.py (1)
43-46: LGTM! Correct fix fordict.get()usage.The standard
dict.get(key, default)method takes the default as a positional argument, not a keyword argument. This change fixes the incorrectdefault=keyword usage.src/draive/stages/types.py (2)
4-4: LGTM! Import updated to use new haiway exception type.The import correctly brings in
ContextStateMissingfrom haiway 0.42, replacing the deprecatedMissingState.
182-203: Exception handling and API exports are consistent.The
ContextStateMissingexception is properly imported fromhaiway(line 4), exported from the maindraivemodule, and has no conflicting legacyMissingStatereferences remaining in the codebase. Tests have been updated to expect this exception, and the error message includes the state type's qualified name for effective debugging.src/draive/__init__.py (2)
15-18: LGTM! New haiway symbols imported for re-export.The new context-related symbols (
ContextIdentifier,ContextMissing,ContextPresets,ContextStateMissing) from haiway 0.42 are correctly imported and maintain alphabetical ordering.
225-228: LGTM! Public API exports updated consistently.The
__all__tuple correctly includes the new symbols, maintaining alphabetical order and synchronization with the imports. As per coding guidelines, this file centralizes public exports appropriately.pyproject.toml (2)
8-8: LGTM! Version bump reflects breaking changes.Bumping to 0.96.0 is appropriate given the breaking API changes (removed exports, renamed exceptions).
34-45: LGTM! Dependency versions updated consistently.Provider libraries are updated with compatible release constraints (
~=). The version bumps align with the haiway 0.42 update and broader ecosystem updates.tests/test_stage.py (2)
4-4: LGTM! Test import updated to match new exception type.The import correctly uses
ContextStateMissingfrom haiway, consistent with the implementation changes.
1012-1013: LGTM! Test expectation updated for new exception type.The test correctly validates that
StageState.get()raisesContextStateMissingwhenrequired=Trueand the state is not found.tests/test_toolbox.py (1)
237-256: LGTM! Improved test synchronization with event-driven coordination.Replacing a fixed sleep with
asyncio.Eventis the correct pattern for synchronizing with detached/spawned tasks in tests. This makes the test deterministic and avoids flakiness from arbitrary delays.tests/test_model.py (3)
64-64: LGTM! UUID serialization updated to standard hyphenated format.The change to hyphenated UUID representation aligns with RFC 4122 and improves readability.
102-102: LGTM! UUID encoding test fixture updated consistently.
275-275: LGTM! Conversation message JSON fixtures updated with hyphenated UUIDs.All three message fixtures (basic, media_url, media_data) are consistently updated at lines 275, 300, and 327.
src/draive/mcp/server.py (2)
39-46: LGTM! Clean API simplification using empty iterables as defaults.The change from
Nonedefaults to empty iterables (()) simplifies the implementation by eliminating None-handling branches. UsingDisposablesas an async context manager provides consistent lifecycle management.
55-59: LGTM! Truthiness checks work correctly for iterables.Empty tuples/lists are falsy in Python, so
if resources:andif tools:correctly guard exposure only when the respective iterables contain elements.src/draive/stages/stage.py (3)
1464-1470: LGTM! Overload signature correctly typed for disposables-only case.The overload correctly specifies
Collection[Disposable]without a default, ensuring type inference works properly when only disposables are provided.
1480-1486: LGTM! Clean signature with empty collection default.The implementation signature correctly uses
Collection[Disposable] = ()as the default, eliminating None-handling complexity. This aligns with the PR-wide pattern of using empty iterables as defaults.
1515-1545: LGTM! Well-structured conditional logic covering all cases.The implementation cleanly handles all four combinations:
- State + disposables → nested
ctx.updated+ctx.disposables- State only →
ctx.updated- Disposables only →
ctx.disposables- Neither → return
self(no-op)The assertions at lines 1535 and 1544 provide good defensive checks against invalid usage patterns.
| ] | ||
| license = { file = "LICENSE" } | ||
| dependencies = ["numpy~=2.3", "haiway~=0.40.2"] | ||
| dependencies = ["numpy~=2.3", "haiway~=0.42"] |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
haiway python package 0.42 changelog release notes breaking changes
💡 Result:
I couldn't find a haiway 0.42 release — the latest published haiway release on PyPI is 0.40.2 (uploaded Dec 16, 2025). See PyPI and package listings. [1][2]
Sources:
- PyPI: haiway (shows latest 0.40.2). [1]
- piwheels / Safety listings for haiway (release list up to 0.40.2). [2]
🏁 Script executed:
# Find all haiway imports and usages in the codebase
rg "from haiway|import haiway" --type pyRepository: miquido/draive
Length of output: 9980
🏁 Script executed:
# Check the project structure to understand the codebase
git ls-files | head -20Repository: miquido/draive
Length of output: 528
Correct haiway dependency version—0.42 is not available on PyPI.
haiway 0.42 does not exist; the latest released version on PyPI is 0.40.2 (Dec 16, 2025). Update the dependency to haiway~=0.40 or an available version to allow the project to install.
🤖 Prompt for AI Agents
In @pyproject.toml at line 27, Update the haiway dependency in the
pyproject.toml dependencies entry: replace the unavailable version spec
"haiway~=0.42" with a valid released version like "haiway~=0.40" (or pin to the
latest available 0.40.x, e.g., 0.40.2) so the dependencies line (dependencies =
["numpy~=2.3", "haiway~=0.40"]) references a PyPI-released version.
| anthropic = ["anthropic~=0.75"] | ||
| anthropic_bedrock = ["anthropic[bedrock]~=0.75"] | ||
| mistral = ["mistralai~=1.10"] | ||
| gemini = ["google-genai~=1.50", "google-api-core"] |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🌐 Web query:
google-api-core latest version pypi
💡 Result:
Latest google-api-core on PyPI: 2.29.0 — uploaded Jan 8, 2026. [1]
Sources:
[1] PyPI project page for google-api-core (release files & upload date).
🏁 Script executed:
# First, let's look at the pyproject.toml file to see the current state
git ls-files | grep -E "pyproject\.toml$"Repository: miquido/draive
Length of output: 72
🏁 Script executed:
cat -n pyproject.toml | sed -n '35,50p'Repository: miquido/draive
Length of output: 658
🌐 Web query:
google-genai 1.50 dependencies google-api-core requirements
💡 Result:
Short answer: google-genai 1.50 does NOT list google-api-core as a direct requirement. The google-genai PyPI metadata (v1.50 series) shows runtime deps like google-auth, httpx, pydantic, requests, tenacity, typing-extensions, websockets, etc., but not google-api-core. [1]
If you use Google Cloud/Generative Language helper packages (e.g., google-ai-generativelanguage), those do require google-api-core with bounds similar to:
google-api-core[grpc] !=2.0.,!=2.1.,!=2.2.,!=2.3.,!=2.4.,!=2.5.,!=2.6.,!=2.7.,!=2.8.,!=2.9., <3.0.0, >=1.34.1. [2]
Sources:
- google-genai (PyPI project page / metadata). [1]
- google-ai-generativelanguage METADATA showing google-api-core bounds. [2]
🏁 Script executed:
rg "google.api" --type py -iRepository: miquido/draive
Length of output: 363
🌐 Web query:
google-genai 1.50.0 google-api-core compatibility version requirements
💡 Result:
Do you want me to look up the exact google-api-core requirement for google-genai 1.50.0 on PyPI/GitHub and report the precise version specifier?
🌐 Web query:
google-genai 1.50.0 setup.py requires_dist google-api-core version pypi
💡 Result:
You can see the exact requires_dist for google-genai 1.50.0 from the PyPI JSON for that release. Run:
- curl -s https://pypi.org/pypi/google-genai/1.50.0/json | jq '.releases["1.50.0"][] .requires_dist'
That returns the google-api-core requirement string declared for that release. PyPI project page / releases: [1].
Sources:
[1] PyPI — google-genai project page. https://pypi.org/project/google-genai/
🏁 Script executed:
curl -s https://pypi.org/pypi/google-genai/1.50.0/json | jq '.info.requires_dist'Repository: miquido/draive
Length of output: 439
🏁 Script executed:
curl -s https://pypi.org/pypi/google-auth/2.14.1/json | jq '.info.requires_dist'Repository: miquido/draive
Length of output: 680
🌐 Web query:
google-api-core ResourceExhausted exception minimum version history
💡 Result:
Summary: The google.api_core.exceptions.ResourceExhausted exception has existed in the library since at least google-api-core v1.14.1 and is present in all subsequent 1.x and 2.x releases (e.g. v1.19.0, v1.22.0, v1.28.0, v2.1.0, v2.8.1). See the exceptions docs for those versions showing ResourceExhausted. [1][2][3][4][5]
Sources:
- google-api-core v1.14.1 exceptions (ResourceExhausted). [1]
- google-api-core v1.19.0 exceptions (ResourceExhausted). [2]
- google-api-core v1.28.0 exceptions (ResourceExhausted). [3]
- google-api-core v2.1.0 exceptions (ResourceExhausted). [4]
- google-api-core latest (2.x) exceptions (ResourceExhausted). [5]
🏁 Script executed:
# Let me check if there are any test requirements or compatibility information
fd "requirements" -t f | head -20Repository: miquido/draive
Length of output: 40
Add version constraint for google-api-core.
The gemini dependency group pins google-genai~=1.50 but leaves google-api-core unpinned. Although google-genai does not directly require it, google-api-core is imported in the code (google.api_core.exceptions.ResourceExhausted), making it an indirect dependency that should have a version constraint. The suggested version should be updated to reflect current compatibility; as of January 2026, google-api-core 2.29.0 is available and compatible.
♻️ Suggested fix
-gemini = ["google-genai~=1.50", "google-api-core"]
+gemini = ["google-genai~=1.50", "google-api-core>=2.14"]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| gemini = ["google-genai~=1.50", "google-api-core"] | |
| gemini = ["google-genai~=1.50", "google-api-core>=2.14"] |
🤖 Prompt for AI Agents
In @pyproject.toml at line 41, The gemini dependency group currently pins
google-genai but leaves google-api-core unpinned; update the gemini entry in
pyproject.toml to pin google-api-core (for example to ~=2.29.0 or another
appropriate 2.x constraint) so the indirect import
google.api_core.exceptions.ResourceExhausted has a guaranteed compatible
version, then regenerate the lockfile (poetry lock / pip-compile) to lock this
change.
No description provided.