From 2f450842e83fee9770521086e45013092b0c634b Mon Sep 17 00:00:00 2001 From: Zhongxuan Wang Date: Fri, 14 Aug 2026 11:37:08 -0700 Subject: [PATCH] fix: reject colliding tool definition extensions Signed-off-by: Zhongxuan Wang --- python/src/nemo_fabric/models.py | 9 ++++++++- tests/python/test_sdk_contract.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/python/src/nemo_fabric/models.py b/python/src/nemo_fabric/models.py index d483fc9cc..d5ab3a95e 100644 --- a/python/src/nemo_fabric/models.py +++ b/python/src/nemo_fabric/models.py @@ -982,11 +982,18 @@ def add_definition( if not name.strip(): raise ValueError("tool definition names must not be empty") + extras = dict(extra_fields or {}) + overlap = {"kind", "ref", "settings"}.intersection(extras) + if overlap: + raise ValueError( + "extra_fields duplicates known fields: " + + ", ".join(sorted(overlap)) + ) value = { "kind": kind, "ref": ref, "settings": dict(settings or {}), - **dict(extra_fields or {}), + **extras, } self.definitions[name] = ToolDefinitionConfig.model_validate(value) return self diff --git a/tests/python/test_sdk_contract.py b/tests/python/test_sdk_contract.py index 6fe5b8b73..5c7c878cc 100644 --- a/tests/python/test_sdk_contract.py +++ b/tests/python/test_sdk_contract.py @@ -763,6 +763,19 @@ def test_typed_tool_definition_omits_empty_settings(): } +@pytest.mark.parametrize("field", ["kind", "ref", "settings"]) +def test_typed_tool_definition_rejects_known_extra_field_collisions(field: str): + tools = ToolsConfig() + + with pytest.raises(ValueError, match="extra_fields duplicates known fields"): + tools.add_definition( + "web", + kind="function_group", + ref="web_tools", + extra_fields={field: "replacement"}, + ) + + def test_run_plan_snapshot_removes_named_definition(): config = _FabricConfigSnapshot.from_mapping( {