Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #151 +/- ##
==========================================
+ Coverage 90.08% 92.29% +2.20%
==========================================
Files 19 19
Lines 1503 1531 +28
==========================================
+ Hits 1354 1413 +59
+ Misses 149 118 -31 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
a251c82 to
2b3fa66
Compare
addbfb9 to
002c82c
Compare
for more information, see https://pre-commit.ci
|
That's a big PR, and I need to spend more time on it... what do you think @wang-boyu @sanika-n ? |
There was a problem hiding this comment.
Pull request overview
This PR aims to unify spatial APIs across legacy mesa.space and newer mesa.discrete_space by standardizing how LLMAgent exposes position and performs movement, and by refactoring inbuilt movement tools to rely on that unified interface.
Changes:
- Added a standardized
LLMAgent.posproperty andLLMAgent.move_to(...)method to abstract overAgent.posvscell.coordinateand different space types. - Refactored inbuilt movement tools (
move_one_step,teleport_to_location) to useagent.pos/agent.move_to(...)and introduced a@requiresdecorator intended to express tool preconditions. - Added/updated tests to exercise the new position/movement behaviors and some tool-decorator schema parsing.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
mesa_llm/llm_agent.py |
Adds unified pos property and move_to(...); simplifies observation location to use self.pos. |
mesa_llm/tools/inbuilt_tools.py |
Removes _get_agent_position, switches to agent.pos + agent.move_to(...), adds @requires annotations. |
mesa_llm/tools/tool_decorator.py |
Introduces requires(...) and extends _python_to_json_type parsing for string annotations. |
mesa_llm/__init__.py |
Exposes requires at the package level. |
tests/test_tools/test_inbuilt_tools.py |
Updates DummyAgent to provide pos/move_to consistent with the new unified API. |
tests/test_coverage_gap.py |
Adds tests for LLMAgent.pos/move_to, async wrappers, and tool schema parsing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| def decorator(func: Callable): | ||
| if not hasattr(func, "__tool_requirements__"): | ||
| func.__tool_requirements__ = [] | ||
| func.__tool_requirements__.append( | ||
| {"precondition": precondition, "reason": reason} | ||
| ) | ||
| return func |
There was a problem hiding this comment.
requires stores preconditions on __tool_requirements__, but nothing in the codebase reads/enforces this attribute (e.g., ToolManager executes tools unconditionally). As a result, the new @requires usage in tools is currently a no-op and won't prevent invalid tool execution. Either integrate requirement checking into ToolManager (before calling the tool) and surface the optional reason, or remove requires to avoid a misleading public API.
| @@ -82,7 +74,7 @@ def move_one_step(agent: "LLMAgent", direction: str) -> str: | |||
|
|
|||
| grid = getattr(agent.model, "grid", None) | |||
| if isinstance(grid, OrthogonalMooreGrid | OrthogonalVonNeumannGrid): | |||
There was a problem hiding this comment.
move_one_step now unconditionally unpacks agent.pos (e.g., row, col = agent.pos). If agent.pos is None or not a 2-tuple, this will raise a TypeError instead of returning a clear error as before. Since @requires(...) is not enforced anywhere, this needs an explicit runtime check (raise ValueError with a helpful message) or the requirements mechanism needs to be wired into tool execution.
| if isinstance(grid, OrthogonalMooreGrid | OrthogonalVonNeumannGrid): | |
| if isinstance(grid, OrthogonalMooreGrid | OrthogonalVonNeumannGrid): | |
| # Validate agent.pos before unpacking to avoid obscure TypeError. | |
| if not isinstance(agent.pos, (tuple, list)) or len(agent.pos) != 2: | |
| raise ValueError( | |
| "Agent position must be a 2-tuple (row, col) for orthogonal grids; " | |
| f"got: {agent.pos!r}" | |
| ) |
| loop = asyncio.new_event_loop() | ||
| asyncio.set_event_loop(loop) | ||
| loop.run_until_complete(run_astep()) | ||
| assert agent.step_called is True | ||
|
|
||
|
|
There was a problem hiding this comment.
This test creates and sets a new global event loop but never closes it (and doesn't restore the previous loop). That can leak resources and cause cross-test interference. Prefer asyncio.run(...), pytest.mark.asyncio with await, or ensure the loop is closed and the prior loop is restored in a try/finally.
| loop = asyncio.new_event_loop() | |
| asyncio.set_event_loop(loop) | |
| loop.run_until_complete(run_astep()) | |
| assert agent.step_called is True | |
| asyncio.run(run_astep()) | |
| assert agent.step_called is True |
| @tool | ||
| def string_annotated_tool(agent, data: "list[int]") -> str: | ||
| """A tool with string annotations. | ||
| Args: | ||
| data: describe data | ||
| """ | ||
| return str(data) | ||
|
|
||
|
|
||
| def test_string_annotated_tool_schema(): |
There was a problem hiding this comment.
Defining a @tool at module import time mutates the global tool registry (_GLOBAL_TOOL_REGISTRY) as a side effect of importing this test module, which can make unrelated tests order-dependent. Consider defining this tool inside the test and/or clearing/restoring _GLOBAL_TOOL_REGISTRY around the assertions.
| @tool | |
| def string_annotated_tool(agent, data: "list[int]") -> str: | |
| """A tool with string annotations. | |
| Args: | |
| data: describe data | |
| """ | |
| return str(data) | |
| def test_string_annotated_tool_schema(): | |
| def test_string_annotated_tool_schema(): | |
| @tool | |
| def string_annotated_tool(agent, data: "list[int]") -> str: | |
| """A tool with string annotations. | |
| Args: | |
| data: describe data | |
| """ | |
| return str(data) |
|
I would prefer to have the unified spatial API provided by Mesa, not part of Mesa-LLM.
Hi @quaquel @EwoutH, are functions like these of interest to you in Mesa?
Would it be feasible & useful to have a unifed |
|
i made these changes when i have old version of mesa on my system. As in new version space is removed and lots of development happen. so i need to revise the changes again. |
Fix for:#150
Changes
Standardized
LLMAgent.posAdded a
@propertyinLLMAgentthat resolves the correct coordinates for both:mesa.space(usingself.pos)mesa.discrete_space(usingself.cell.coordinate)Unified Movement
Added
LLMAgent.move_to(target_coordinates)to encapsulate movement logic for different Mesa space types.Refactored Inbuilt Tools
Simplified
move_one_stepandteleport_to_locationto useagent.posandagent.move_to().Full Compatibility
Verified that all 203 tests pass, including
test_inbuilt_tools.pyacross different environment setups.