fix: handle null values for optional fetch parameters

Make max_length, start_index, and raw parameters properly optional
by using Optional[] types and handling null values gracefully.

This fixes the issue where LibreChat passes explicit null values
for optional parameters, which was causing Pydantic validation
failures.

Co-authored-by: Ola Hungerford <olaservo@users.noreply.github.com>
This commit is contained in:
claude[bot]
2025-08-27 12:24:48 +00:00
parent e3284edb47
commit ec20ee77e9

View File

@@ -1,4 +1,4 @@
from typing import Annotated, Tuple from typing import Annotated, Tuple, Optional
from urllib.parse import urlparse, urlunparse from urllib.parse import urlparse, urlunparse
import markdownify import markdownify
@@ -153,7 +153,7 @@ class Fetch(BaseModel):
url: Annotated[AnyUrl, Field(description="URL to fetch")] url: Annotated[AnyUrl, Field(description="URL to fetch")]
max_length: Annotated[ max_length: Annotated[
int, Optional[int],
Field( Field(
default=5000, default=5000,
description="Maximum number of characters to return.", description="Maximum number of characters to return.",
@@ -162,7 +162,7 @@ class Fetch(BaseModel):
), ),
] ]
start_index: Annotated[ start_index: Annotated[
int, Optional[int],
Field( Field(
default=0, default=0,
description="On return output starting at this character index, useful if a previous fetch was truncated and more context is required.", description="On return output starting at this character index, useful if a previous fetch was truncated and more context is required.",
@@ -170,7 +170,7 @@ class Fetch(BaseModel):
), ),
] ]
raw: Annotated[ raw: Annotated[
bool, Optional[bool],
Field( Field(
default=False, default=False,
description="Get the actual HTML content of the requested page, without simplification.", description="Get the actual HTML content of the requested page, without simplification.",
@@ -235,22 +235,24 @@ Although originally you did not have internet access, and were advised to refuse
await check_may_autonomously_fetch_url(url, user_agent_autonomous, proxy_url) await check_may_autonomously_fetch_url(url, user_agent_autonomous, proxy_url)
content, prefix = await fetch_url( content, prefix = await fetch_url(
url, user_agent_autonomous, force_raw=args.raw, proxy_url=proxy_url url, user_agent_autonomous, force_raw=args.raw or False, proxy_url=proxy_url
) )
original_length = len(content) original_length = len(content)
if args.start_index >= original_length: start_index = args.start_index or 0
max_length = args.max_length or 5000
if start_index >= original_length:
content = "<error>No more content available.</error>" content = "<error>No more content available.</error>"
else: else:
truncated_content = content[args.start_index : args.start_index + args.max_length] truncated_content = content[start_index : start_index + max_length]
if not truncated_content: if not truncated_content:
content = "<error>No more content available.</error>" content = "<error>No more content available.</error>"
else: else:
content = truncated_content content = truncated_content
actual_content_length = len(truncated_content) actual_content_length = len(truncated_content)
remaining_content = original_length - (args.start_index + actual_content_length) remaining_content = original_length - (start_index + actual_content_length)
# Only add the prompt to continue fetching if there is still remaining content # Only add the prompt to continue fetching if there is still remaining content
if actual_content_length == args.max_length and remaining_content > 0: if actual_content_length == max_length and remaining_content > 0:
next_start = args.start_index + actual_content_length next_start = start_index + actual_content_length
content += f"\n\n<error>Content truncated. Call the fetch tool with a start_index of {next_start} to get more content.</error>" content += f"\n\n<error>Content truncated. Call the fetch tool with a start_index of {next_start} to get more content.</error>"
return [TextContent(type="text", text=f"{prefix}Contents of {url}:\n{content}")] return [TextContent(type="text", text=f"{prefix}Contents of {url}:\n{content}")]