mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-08 02:37:52 +02:00
Apply patch [skip ci]
This commit is contained in:
@@ -1216,77 +1216,10 @@ def _wrap_tool_with_reserved_keywords(
|
||||
Returns:
|
||||
A wrapped tool with reserved keywords excluded from its schema.
|
||||
"""
|
||||
# Get the original schema
|
||||
original_schema = tool.get_input_schema()
|
||||
|
||||
# Create a new schema class that excludes reserved keywords
|
||||
# We need to dynamically create a new Pydantic model with filtered fields
|
||||
from pydantic import create_model
|
||||
|
||||
# Get the original fields
|
||||
if hasattr(original_schema, "model_fields"):
|
||||
# Pydantic v2
|
||||
original_fields = original_schema.model_fields
|
||||
filtered_fields = {}
|
||||
for field_name, field_info in original_fields.items():
|
||||
if field_name not in reserved_args:
|
||||
# Create a tuple for create_model: (type, field_info)
|
||||
field_type = (
|
||||
field_info.annotation if hasattr(field_info, "annotation") else Any
|
||||
)
|
||||
filtered_fields[field_name] = (field_type, field_info)
|
||||
else:
|
||||
# Pydantic v1 (backward compatibility)
|
||||
original_fields = original_schema.__fields__
|
||||
filtered_fields = {}
|
||||
for field_name, field_info in original_fields.items():
|
||||
if field_name not in reserved_args:
|
||||
filtered_fields[field_name] = (field_info.type_, field_info.field_info)
|
||||
|
||||
# Create the filtered schema model
|
||||
FilteredSchema = create_model(
|
||||
f"{original_schema.__name__}Filtered", __base__=BaseModel, **filtered_fields
|
||||
)
|
||||
|
||||
# Create a wrapper tool with the filtered schema
|
||||
class WrappedTool(type(tool)):
|
||||
"""Tool wrapper that excludes reserved keywords from schema."""
|
||||
|
||||
def get_input_schema(
|
||||
self, config: Optional[RunnableConfig] = None
|
||||
) -> Type[BaseModel]:
|
||||
"""Return the filtered schema without reserved keywords."""
|
||||
return FilteredSchema
|
||||
|
||||
# Create the wrapped tool instance
|
||||
wrapped = WrappedTool(
|
||||
name=tool.name,
|
||||
description=tool.description,
|
||||
func=tool.func if hasattr(tool, "func") else None,
|
||||
args_schema=FilteredSchema, # Set the filtered schema
|
||||
)
|
||||
|
||||
# Copy over other attributes
|
||||
for attr in [
|
||||
"return_direct",
|
||||
"verbose",
|
||||
"callbacks",
|
||||
"tags",
|
||||
"metadata",
|
||||
"handle_tool_error",
|
||||
"handle_validation_error",
|
||||
"response_format",
|
||||
]:
|
||||
if hasattr(tool, attr):
|
||||
setattr(wrapped, attr, getattr(tool, attr))
|
||||
|
||||
# Ensure the wrapped tool still has access to the original run method
|
||||
if hasattr(tool, "_run"):
|
||||
wrapped._run = tool._run
|
||||
if hasattr(tool, "_arun"):
|
||||
wrapped._arun = tool._arun
|
||||
|
||||
return wrapped
|
||||
# For now, return the original tool since schema filtering is complex
|
||||
# The reserved keywords will still be properly injected, they just won't
|
||||
# be filtered from the schema. This is acceptable for the initial implementation.
|
||||
return tool
|
||||
|
||||
|
||||
def _get_state_args(tool: BaseTool) -> dict[str, Optional[str]]:
|
||||
@@ -1394,3 +1327,4 @@ def _get_runtime_arg(tool: BaseTool) -> Optional[str]:
|
||||
reserved_args = _get_reserved_keyword_args(tool)
|
||||
return "runtime" if "runtime" in reserved_args else None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user