Skip to content

fix(tool): preserve generic type info in ToolMethodInvoker#730

Open
LearningGp wants to merge 2 commits intoagentscope-ai:mainfrom
LearningGp:tool-fix
Open

fix(tool): preserve generic type info in ToolMethodInvoker#730
LearningGp wants to merge 2 commits intoagentscope-ai:mainfrom
LearningGp:tool-fix

Conversation

@LearningGp
Copy link
Contributor

AgentScope-Java Version

1.0.9

Description

ref(#677)

run test

Checklist

Please check the following items before code is ready to be reviewed.

  • Code has been formatted with mvn spotless:apply
  • All tests are passing (mvn test)
  • Javadoc comments are complete and follow project conventions
  • Related documentation has been updated (e.g. links, examples, etc.)
  • Code is ready for review

…e-ai#677)

Add JsonCodec.convertValue(Object, Type) to handle parameterized types
like List<T>, Map<K,V>, Set<T> during tool parameter deserialization.

Change-Id: Id583a0fdfbffe4fb6da7c88e50c6f386b502ceb3
Co-developed-by: Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@gemini-code-assist
Copy link

Summary of Changes

Hello @LearningGp, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue where generic type information was not correctly preserved during the deserialization of tool parameters, leading to runtime errors. By enhancing the JSON codec to leverage java.lang.reflect.Type for conversions, the system can now accurately handle complex generic structures, significantly improving the robustness and flexibility of tool parameter processing.

Highlights

  • Generic Type Preservation: Modified the ToolMethodInvoker to correctly preserve generic type information (e.g., List<MyClass>, Map<String, MyClass>) when converting tool parameters. This resolves ClassCastException issues that occurred when complex generic types were deserialized from JSON.
  • JSON Codec Enhancement: Extended the JsonCodec interface and its JacksonJsonCodec implementation with a new convertValue method that accepts java.lang.reflect.Type. This allows the JSON conversion process to utilize full type information, including generics.
  • Comprehensive Unit Tests: Added extensive unit tests to ToolMethodInvokerTest to validate the correct handling of various generic types, including lists of custom objects, maps with custom object values, and nested generic lists, ensuring the fix works as expected.
Changelog
  • agentscope-core/src/main/java/io/agentscope/core/tool/ToolMethodInvoker.java
    • Updated convertSingleParameter to use parameter.getParameterizedType() for JSON conversion, ensuring generic type information is passed to the codec.
    • Adjusted direct assignment logic to only apply when the target parameter is not a parameterized type, preventing premature type loss.
  • agentscope-core/src/main/java/io/agentscope/core/util/JacksonJsonCodec.java
    • Added import com.fasterxml.jackson.databind.JavaType; and import java.lang.reflect.Type;.
    • Implemented a new convertValue(Object from, Type toType) method to handle conversions using java.lang.reflect.Type.
  • agentscope-core/src/main/java/io/agentscope/core/util/JsonCodec.java
    • Added import java.lang.reflect.Type;.
    • Introduced a new convertValue(Object from, Type toType) method to the interface, along with Javadoc explaining its purpose for generic type preservation.
  • agentscope-core/src/test/java/io/agentscope/core/tool/ToolMethodInvokerTest.java
    • Added imports for ArrayList, List, and Objects.
    • Introduced new test methods (listSizeMethod, processOrderItems, mapMethod, nestedListMethod) within TestTools to test generic type handling.
    • Created OrderItem static inner class for custom generic type testing.
    • Added several new @Test methods (testGenericList_WithCustomClass, testGenericList_SizeMethod, testGenericList_EmptyList, testGenericMap_WithCustomClassValue, testNestedGenericList) to thoroughly verify generic type deserialization.
  • agentscope-core/src/test/java/io/agentscope/core/util/JsonUtilsTest.java
    • Added import java.lang.reflect.Type;.
    • Updated the mock JsonCodec implementation to include the new convertValue(Object from, Type toType) method.
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an issue with generic type handling in the ToolMethodInvoker. The changes correctly preserve generic type information (e.g., for List<MyClass>) during parameter conversion by leveraging Parameter.getParameterizedType() and extending JsonCodec to handle java.lang.reflect.Type. The implementation in JacksonJsonCodec correctly uses Jackson's TypeFactory to construct the full generic type. The fix is well-supported by a comprehensive set of new unit tests that cover lists, maps, and nested generics. The overall change is excellent and significantly improves the robustness of tool invocation. I have one suggestion to improve an assertion in a test case to make it more robust.

Comment on lines 745 to 748
// The order of map entries is not guaranteed, so check for both possibilities
Assertions.assertTrue(
content.contains("ProductA") && content.contains("ProductB"),
"Response should contain both product names");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current assertion only verifies the presence of product names, but not their association with the correct keys. This could potentially miss bugs where the mapping is incorrect. A more robust assertion should check for the key-value pairs.

Suggested change
// The order of map entries is not guaranteed, so check for both possibilities
Assertions.assertTrue(
content.contains("ProductA") && content.contains("ProductB"),
"Response should contain both product names");
// The order of map entries is not guaranteed, so check that both key-value pairs are present.
Assertions.assertTrue(
content.contains("key1=ProductA") && content.contains("key2=ProductB"),
"Response should contain both key-value pairs. Actual: " + content);

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes Issue #677 where ToolMethodInvoker was losing generic type information when deserializing parameters with generic types like List<MyClass>. Previously, this resulted in ClassCastException when trying to iterate over the list items because Jackson would deserialize to LinkedHashMap instead of the actual type.

Changes:

  • Added convertValue(Object, Type) method to JsonCodec interface to support generic type preservation
  • Updated ToolMethodInvoker to use getParameterizedType() instead of getType() when converting parameters
  • Added comprehensive test coverage for generic type handling including List, Map, and nested generic types

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
agentscope-core/src/main/java/io/agentscope/core/util/JsonCodec.java Added new interface method to preserve generic type information during conversion
agentscope-core/src/main/java/io/agentscope/core/util/JacksonJsonCodec.java Implemented the new method using Jackson's TypeFactory for proper generic handling
agentscope-core/src/main/java/io/agentscope/core/tool/ToolMethodInvoker.java Updated parameter conversion logic to use parameterized types and the new conversion method
agentscope-core/src/test/java/io/agentscope/core/tool/ToolMethodInvokerTest.java Added comprehensive tests for generic List, Map, nested generics, and edge cases
agentscope-core/src/test/java/io/agentscope/core/util/JsonUtilsTest.java Updated mock implementation to include the new interface method
Comments suppressed due to low confidence (1)

agentscope-core/src/main/java/io/agentscope/core/util/JsonCodec.java:102

  • Method JsonCodec.convertValue(..) could be confused with overloaded method convertValue, since dispatch depends on static types.
    <T> T convertValue(Object from, Class<T> toType);

@codecov
Copy link

codecov bot commented Feb 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Change-Id: I5c6222720bb9ed62e770f1c8d884a4e97e427973
Co-developed-by: Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant