unitysvc-core 0.2.24__tar.gz → 0.2.25__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {unitysvc_core-0.2.24/src/unitysvc_core.egg-info → unitysvc_core-0.2.25}/PKG-INFO +1 -1
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/pyproject.toml +1 -1
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/validators.py +29 -12
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25/src/unitysvc_core.egg-info}/PKG-INFO +1 -1
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_validators.py +21 -4
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/LICENSE +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/README.md +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/setup.cfg +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/__init__.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/__init__.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/base.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/documents.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/listing_data.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/listing_v1.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/offering_data.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/offering_v1.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/pricing.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/promotion_data.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/provider_data.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/provider_v1.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/service.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/service_group_data.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/py.typed +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/base.json +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/listing_v1.json +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/offering_v1.json +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/promotion_v1.json +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/provider_v1.json +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/service_group_v1.json +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/utils.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/validator.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core.egg-info/SOURCES.txt +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core.egg-info/dependency_links.txt +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core.egg-info/requires.txt +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core.egg-info/top_level.txt +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_access_interface_routing.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_hidden_path_skip.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_pricing.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_provider_account_rate_limits.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_service_group.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_service_status.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_utils.py +0 -0
- {unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/tests/test_validator.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "unitysvc-core"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.25"
|
|
8
8
|
description = "Shared data models and validation helpers for UnitySVC packages"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Bo Peng", email = "bo.peng@unitysvc.com" }]
|
|
@@ -815,20 +815,39 @@ def validate_mcp_offering(data: dict[str, Any] | None) -> list[str]:
|
|
|
815
815
|
"""
|
|
816
816
|
if not data or not isinstance(data, dict):
|
|
817
817
|
return []
|
|
818
|
-
if data.get("service_type") != "mcp":
|
|
819
|
-
return []
|
|
820
818
|
|
|
819
|
+
service_type = data.get("service_type")
|
|
820
|
+
capabilities = data.get("capabilities")
|
|
821
821
|
channels = data.get("upstream_access_config")
|
|
822
|
+
mcp_channels = (
|
|
823
|
+
sorted(
|
|
824
|
+
name
|
|
825
|
+
for name, config in (channels or {}).items()
|
|
826
|
+
if isinstance(config, dict) and config.get("access_method") == "mcp"
|
|
827
|
+
)
|
|
828
|
+
if isinstance(channels, dict)
|
|
829
|
+
else []
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
if service_type != "mcp":
|
|
833
|
+
declarations: list[str] = []
|
|
834
|
+
if isinstance(capabilities, list) and "mcp-delegation" in capabilities:
|
|
835
|
+
declarations.append("capability 'mcp-delegation'")
|
|
836
|
+
if mcp_channels:
|
|
837
|
+
declarations.append("MCP upstream channel(s) " + ", ".join(repr(name) for name in mcp_channels))
|
|
838
|
+
if declarations:
|
|
839
|
+
return [
|
|
840
|
+
f"service_type {service_type!r} may not declare "
|
|
841
|
+
+ "; ".join(declarations)
|
|
842
|
+
+ "; use service_type 'mcp' instead"
|
|
843
|
+
]
|
|
844
|
+
return []
|
|
845
|
+
|
|
822
846
|
if not channels or not isinstance(channels, dict):
|
|
823
847
|
return ["upstream_access_config: an MCP service must declare at least one channel"]
|
|
824
848
|
|
|
825
|
-
if not
|
|
826
|
-
|
|
827
|
-
):
|
|
828
|
-
return [
|
|
829
|
-
"upstream_access_config: an MCP service must have at least one channel "
|
|
830
|
-
"with access_method 'mcp'"
|
|
831
|
-
]
|
|
849
|
+
if not mcp_channels:
|
|
850
|
+
return ["upstream_access_config: an MCP service must have at least one channel with access_method 'mcp'"]
|
|
832
851
|
|
|
833
852
|
return []
|
|
834
853
|
|
|
@@ -901,9 +920,7 @@ def validate_listing_mcp_base_urls(user_access_interfaces: dict[str, Any] | None
|
|
|
901
920
|
f"a non-empty 'namespace' in routing_key"
|
|
902
921
|
)
|
|
903
922
|
else:
|
|
904
|
-
errors.extend(
|
|
905
|
-
validate_mcp_namespace(namespace, f"{field}.routing_key.namespace")
|
|
906
|
-
)
|
|
923
|
+
errors.extend(validate_mcp_namespace(namespace, f"{field}.routing_key.namespace"))
|
|
907
924
|
|
|
908
925
|
return errors
|
|
909
926
|
|
|
@@ -583,9 +583,28 @@ class TestValidateMcpOffering:
|
|
|
583
583
|
def test_valid_mcp_offering_passes(self) -> None:
|
|
584
584
|
assert validate_mcp_offering(self._offering()) == []
|
|
585
585
|
|
|
586
|
-
def
|
|
586
|
+
def test_non_mcp_offering_without_mcp_declarations_is_ignored(self) -> None:
|
|
587
587
|
assert validate_mcp_offering({"service_type": "llm"}) == []
|
|
588
588
|
|
|
589
|
+
def test_non_mcp_offering_cannot_declare_mcp_delegation(self) -> None:
|
|
590
|
+
errors = validate_mcp_offering({"service_type": "proxy", "capabilities": ["mcp-delegation"]})
|
|
591
|
+
assert errors
|
|
592
|
+
assert "mcp-delegation" in errors[0]
|
|
593
|
+
assert "service_type 'mcp'" in errors[0]
|
|
594
|
+
|
|
595
|
+
def test_non_mcp_offering_cannot_declare_an_mcp_channel(self) -> None:
|
|
596
|
+
errors = validate_mcp_offering(
|
|
597
|
+
{
|
|
598
|
+
"service_type": "proxy",
|
|
599
|
+
"upstream_access_config": {
|
|
600
|
+
"upstream": {"access_method": "mcp", "base_url": "https://mcp.example.test"}
|
|
601
|
+
},
|
|
602
|
+
}
|
|
603
|
+
)
|
|
604
|
+
assert errors
|
|
605
|
+
assert "MCP upstream channel" in errors[0]
|
|
606
|
+
assert "service_type 'mcp'" in errors[0]
|
|
607
|
+
|
|
589
608
|
def test_requires_a_channel(self) -> None:
|
|
590
609
|
errors = validate_mcp_offering(self._offering(upstream_access_config={}))
|
|
591
610
|
assert errors
|
|
@@ -593,9 +612,7 @@ class TestValidateMcpOffering:
|
|
|
593
612
|
|
|
594
613
|
def test_requires_an_mcp_access_method_channel(self) -> None:
|
|
595
614
|
errors = validate_mcp_offering(
|
|
596
|
-
self._offering(
|
|
597
|
-
upstream_access_config={"x": {"access_method": "http", "base_url": "https://x"}}
|
|
598
|
-
)
|
|
615
|
+
self._offering(upstream_access_config={"x": {"access_method": "http", "base_url": "https://x"}})
|
|
599
616
|
)
|
|
600
617
|
assert errors
|
|
601
618
|
assert "access_method 'mcp'" in errors[0]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/models/service_group_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core/schema/service_group_v1.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitysvc_core-0.2.24 → unitysvc_core-0.2.25}/src/unitysvc_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|