Skip to content

Commit 93f4978

Browse files
committed
fix: preserve legacy aggregate image limits
Signed-off-by: DragonFSKY <38503900+DragonFSKY@users.noreply.github.com>
1 parent d5c1228 commit 93f4978

2 files changed

Lines changed: 46 additions & 12 deletions

File tree

tests/test_base_tool_image_validation.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,32 @@ def test_validate_image_limits_respects_custom_total_cap(tmp_path):
9292
assert result is not None
9393
assert result["status"] == "error"
9494
assert "Total image size limit exceeded" in result["content"]
95+
96+
97+
def test_validate_image_limits_uses_legacy_total_cap_when_total_limit_missing(tmp_path):
98+
tool = ChatTool()
99+
caps = FakeCapabilities(provider=ProviderType.GOOGLE, max_image_size_mb=0.002, max_total_image_size_mb=0.0)
100+
ctx = FakeModelContext(caps)
101+
102+
img1 = tmp_path / "img1.bin"
103+
img2 = tmp_path / "img2.bin"
104+
for path in (img1, img2):
105+
path.write_bytes(b"\x00" * 1536)
106+
107+
result = tool._validate_image_limits([str(img1), str(img2)], model_context=ctx)
108+
assert result is not None
109+
assert result["status"] == "error"
110+
assert "Total image size limit exceeded" in result["content"]
111+
112+
113+
def test_validate_image_limits_does_not_apply_openrouter_total_cap_without_total_limit(tmp_path):
114+
tool = ChatTool()
115+
caps = FakeCapabilities(provider=ProviderType.OPENROUTER, max_image_size_mb=0.002, max_total_image_size_mb=0.0)
116+
ctx = FakeModelContext(caps)
117+
118+
img1 = tmp_path / "img1.bin"
119+
img2 = tmp_path / "img2.bin"
120+
for path in (img1, img2):
121+
path.write_bytes(b"\x00" * 1536)
122+
123+
assert tool._validate_image_limits([str(img1), str(img2)], model_context=ctx) is None

tools/shared/base_tool.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from config import MCP_PROMPT_SIZE_LIMIT
2626
from providers import ModelProvider, ModelProviderRegistry
27+
from providers.shared import ProviderType
2728
from utils import estimate_tokens
2829
from utils.conversation_memory import (
2930
ConversationTurn,
@@ -1460,17 +1461,21 @@ def _get_effective_limit(self, configured_limit_mb: float, capabilities: Any) ->
14601461
if configured_limit_mb <= 0:
14611462
return configured_limit_mb
14621463

1463-
effective_limit_mb = configured_limit_mb
1464-
try:
1465-
from providers.shared import ProviderType
1464+
if capabilities.provider == ProviderType.CUSTOM:
1465+
return min(configured_limit_mb, 40.0)
14661466

1467-
if getattr(capabilities, "provider", None) == ProviderType.CUSTOM:
1468-
effective_limit_mb = min(configured_limit_mb, 40.0)
1469-
except Exception:
1470-
# Fall back to configured limit on any exception
1471-
logger.debug("Failed to apply provider-specific limit; using configured limit", exc_info=True)
1467+
return configured_limit_mb
14721468

1473-
return effective_limit_mb
1469+
def _get_total_image_size_limit(self, capabilities: Any, max_image_size_mb: float) -> float:
1470+
"""Return the total image size limit while preserving legacy provider config semantics."""
1471+
max_total_size_mb = capabilities.max_total_image_size_mb
1472+
if max_total_size_mb > 0:
1473+
return max_total_size_mb
1474+
1475+
if capabilities.provider != ProviderType.OPENROUTER and max_image_size_mb > 0:
1476+
return max_image_size_mb
1477+
1478+
return 0.0
14741479

14751480
def _calculate_image_size(self, image_path: str) -> tuple[Optional[float], Optional[str]]:
14761481
"""
@@ -1642,13 +1647,13 @@ def _validate_image_limits(
16421647
},
16431648
}
16441649

1645-
# Check total request size limit (only if model has explicit total limit)
1646-
# If max_total_image_size_mb is 0, skip total size validation (no official limit documented)
1650+
# Check total request size limit. Older provider configs used max_image_size_mb
1651+
# as a total request cap, while OpenRouter uses it as a per-image cap.
16471652
# NOTE: We validate against original image sizes, not base64-encoded sizes.
16481653
# Provider-specific limits (e.g. Google 15MB, Anthropic 24MB) are already adjusted
16491654
# to account for base64 encoding overhead (~33% increase) and text content.
16501655
# This keeps validation simple and performant while providing adequate safety margin.
1651-
max_total_size_mb = capabilities.max_total_image_size_mb
1656+
max_total_size_mb = self._get_total_image_size_limit(capabilities, max_size_mb)
16521657
if max_total_size_mb > 0:
16531658
effective_total_limit_mb = self._get_effective_limit(max_total_size_mb, capabilities)
16541659
# Check if total size exceeds the request limit

0 commit comments

Comments
 (0)