Skip to content

Commit df5321b

Browse files
committed
fix(sdk): make the capability catalog lookup case-insensitive on provider
1 parent a8f5a18 commit df5321b

2 files changed

Lines changed: 32 additions & 8 deletions

File tree

sdks/python/agenta/sdk/agents/model_catalog.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,29 @@ def claude_model_catalog() -> ModelCatalog:
145145
return _CLAUDE_CATALOG
146146

147147

148+
def _catalog_id(provider: Optional[str], model_id: str) -> str:
149+
"""Build the ``provider/model`` join key.
150+
151+
Catalog ids carry a lowercase provider, and the rest of the system (environment resolver,
152+
connection matching) treats provider names case-insensitively, so a caller-supplied
153+
``"OpenAI"`` must still join.
154+
"""
155+
head, separator, tail = model_id.partition("/")
156+
if provider is None:
157+
return f"{head.lower()}/{tail}" if separator else model_id
158+
if separator and head.lower() == provider.lower():
159+
return f"{provider.lower()}/{tail}"
160+
return f"{provider.lower()}/{model_id}"
161+
162+
148163
def model_input_modalities(
149164
harness: Optional[str], model_id: str, *, provider: Optional[str] = None
150165
) -> Optional[List[str]]:
151166
"""Look up input modalities using the model id form accepted by ``harness``."""
152167
entry: Optional[ModelCatalogEntry]
153168
if harness in ("pi_core", "pi_agenta"):
154169
catalog = pi_model_catalog()
155-
catalog_id = (
156-
model_id
157-
if provider is None or model_id.startswith(f"{provider}/")
158-
else f"{provider}/{model_id}"
159-
)
170+
catalog_id = _catalog_id(provider, model_id)
160171
elif harness == "claude":
161172
catalog = claude_model_catalog()
162173
catalog_id = model_id
@@ -166,9 +177,7 @@ def model_input_modalities(
166177
entry = next((item for item in catalog.models if item.id == catalog_id), None)
167178
if harness == "claude" and entry is None:
168179
# Reuse the same sourced Anthropic fact from Pi's generated catalog; do not guess.
169-
pi_catalog_id = (
170-
model_id if model_id.startswith("anthropic/") else f"anthropic/{model_id}"
171-
)
180+
pi_catalog_id = _catalog_id("anthropic", model_id)
172181
entry = next(
173182
(item for item in pi_model_catalog().models if item.id == pi_catalog_id),
174183
None,

sdks/python/oss/tests/pytest/unit/agents/connections/test_model_catalog.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,21 @@ def test_pi_input_modalities_lookup_joins_resolved_provider_and_model(harness):
164164
]
165165

166166

167+
def test_input_modalities_lookup_is_case_insensitive_on_provider():
168+
# Provider names are matched case-insensitively everywhere else (environment resolver,
169+
# connection matching); a mixed-case provider must not silently drop the modality fact.
170+
assert model_input_modalities(
171+
"pi_core", "gpt-5.5", provider="OpenAI"
172+
) == model_input_modalities("pi_core", "gpt-5.5", provider="openai")
173+
assert model_input_modalities("pi_core", "OpenAI/gpt-5.5", provider="OpenAI") == [
174+
"text",
175+
"image",
176+
]
177+
assert model_input_modalities(
178+
"claude", "claude-sonnet-4-6", provider="Anthropic"
179+
) == ["text", "image"]
180+
181+
167182
def test_claude_input_modalities_lookup_uses_bare_alias():
168183
assert model_input_modalities("claude", "sonnet", provider="anthropic") == [
169184
"text",

0 commit comments

Comments
 (0)