upload
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
from app.models.capability import Capability, CapabilityType
|
||||
from app.services.pipeline_service import PipelineService
|
||||
from app.services.semantic_selection import SelectedCapability
|
||||
|
||||
|
||||
def _build_capability(*, name: str, required_inputs: list[str] | None = None) -> Capability:
|
||||
cap_id = uuid4()
|
||||
action_id = uuid4()
|
||||
input_schema = None
|
||||
if required_inputs is not None:
|
||||
input_schema = {
|
||||
"type": "object",
|
||||
"required": required_inputs,
|
||||
"properties": {
|
||||
input_name: {"type": "string"}
|
||||
for input_name in required_inputs
|
||||
},
|
||||
}
|
||||
return Capability(
|
||||
id=cap_id,
|
||||
action_id=action_id,
|
||||
type=CapabilityType.ATOMIC,
|
||||
name=name,
|
||||
input_schema=input_schema,
|
||||
output_schema={"type": "object"},
|
||||
)
|
||||
|
||||
|
||||
def _select(capability: Capability) -> SelectedCapability:
|
||||
return SelectedCapability(capability=capability, score=1.0, confidence_tier="high")
|
||||
|
||||
|
||||
def test_extract_required_inputs_from_node_merges_all_endpoints():
|
||||
service = PipelineService(session=None) # type: ignore[arg-type]
|
||||
node = {
|
||||
"step": 1,
|
||||
"endpoints": [
|
||||
{
|
||||
"input_type": {
|
||||
"type": "object",
|
||||
"required": ["users", "campaignId"],
|
||||
}
|
||||
},
|
||||
{
|
||||
"input_type": {
|
||||
"type": "object",
|
||||
"required": ["segments", "users"],
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
required = service._extract_required_inputs_from_node(node)
|
||||
|
||||
assert required == ["users", "campaignId", "segments"]
|
||||
|
||||
|
||||
def test_normalize_workflow_preserves_multi_endpoint_nodes():
|
||||
capability_a = _build_capability(name="Get users", required_inputs=["users"])
|
||||
capability_b = _build_capability(name="Build segments", required_inputs=["users"])
|
||||
selected = [_select(capability_a), _select(capability_b)]
|
||||
service = PipelineService(session=None) # type: ignore[arg-type]
|
||||
|
||||
raw_graph = {
|
||||
"nodes": [
|
||||
{
|
||||
"step": 1,
|
||||
"name": "Composite-like node",
|
||||
"endpoints": [
|
||||
{
|
||||
"capability_id": str(capability_a.id),
|
||||
},
|
||||
{
|
||||
"capability_id": str(capability_b.id),
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
"edges": [],
|
||||
}
|
||||
|
||||
nodes, edges, issues = service._normalize_workflow(raw_graph, selected)
|
||||
|
||||
assert issues == []
|
||||
assert edges == []
|
||||
assert len(nodes) == 1
|
||||
endpoints = nodes[0]["endpoints"]
|
||||
assert len(endpoints) == 2
|
||||
assert endpoints[0]["capability_id"] == str(capability_a.id)
|
||||
assert endpoints[1]["capability_id"] == str(capability_b.id)
|
||||
assert endpoints[0]["action_id"] == str(capability_a.action_id)
|
||||
assert endpoints[1]["action_id"] == str(capability_b.action_id)
|
||||
|
||||
|
||||
def test_normalize_workflow_flags_invalid_endpoint_capability_refs():
|
||||
capability = _build_capability(name="Get users", required_inputs=["users"])
|
||||
selected = [_select(capability)]
|
||||
service = PipelineService(session=None) # type: ignore[arg-type]
|
||||
|
||||
raw_graph = {
|
||||
"nodes": [
|
||||
{
|
||||
"step": 1,
|
||||
"name": "Node with invalid endpoint",
|
||||
"endpoints": [
|
||||
{"capability_id": str(uuid4())},
|
||||
{"capability_id": str(capability.id)},
|
||||
],
|
||||
}
|
||||
],
|
||||
"edges": [],
|
||||
}
|
||||
|
||||
nodes, _edges, issues = service._normalize_workflow(raw_graph, selected)
|
||||
|
||||
assert "graph:invalid_capability_ref" in issues
|
||||
assert len(nodes) == 1
|
||||
assert len(nodes[0]["endpoints"]) == 1
|
||||
assert nodes[0]["endpoints"][0]["capability_id"] == str(capability.id)
|
||||
Reference in New Issue
Block a user