fix(actor): Report the number of nodes and edges in the system
Extract nodes and edges from the route block as top-level keys in
graph_descriptor within _extract_v3_actor() in config.py. The CLI
layer reads graph_descriptor.get("nodes") / .get("edges") directly,
so those keys must be present at the top level — not nested under route.
Reverts the incorrect CLI-layer workaround (drilling into route) that
broke existing tests relying on flat graph_descriptor structures.
Also fixes two regressions introduced by prior attempts:
- Restored key/value and filter/value table headers in the ACMS
index_data_model_and_traversal feature file
- Reverted the ACMS step name from "the count should be" back to
"idx the index count should be" to eliminate the ambiguous step
conflict with security_audit_steps.py
Adds @tdd_issue @tdd_issue_10860 BDD regression scenarios verifying
that a v3 type:graph actor YAML with route.nodes and route.edges
produces a graph_descriptor with correct top-level node/edge counts.
ISSUES CLOSED: #10860
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
@tdd_issue @tdd_issue_10860
|
||||
Feature: Actor graph_descriptor exposes nodes and edges from route block
|
||||
As a developer using graph actors
|
||||
I want nodes and edges from the route block to appear as top-level keys in graph_descriptor
|
||||
So that 'agents actor add' correctly reports node and edge counts
|
||||
|
||||
Scenario: v3 graph actor with nodes and edges in route reports correct counts
|
||||
Given a v3 graph actor blob with a route containing 2 nodes and 1 edge
|
||||
When I parse the actor configuration from the v3 blob
|
||||
Then the parsed graph_descriptor node count should be 2
|
||||
And the parsed graph_descriptor edge count should be 1
|
||||
|
||||
Scenario: v3 graph actor route with no nodes or edges defaults to empty lists
|
||||
Given a v3 graph actor blob with a route containing no nodes or edges
|
||||
When I parse the actor configuration from the v3 blob
|
||||
Then the parsed graph_descriptor node count should be 0
|
||||
And the parsed graph_descriptor edge count should be 0
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Step definitions for actor_config_nodes_edges.feature — regression for issue #10860."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from behave import given, then, when
|
||||
from behave.runner import Context # type: ignore[import-untyped]
|
||||
|
||||
from cleveragents.actor.config import ActorConfiguration
|
||||
|
||||
|
||||
@given("a v3 graph actor blob with a route containing 2 nodes and 1 edge")
|
||||
def step_graph_actor_blob_with_nodes(context: Context) -> None:
|
||||
context.blob = {
|
||||
"type": "graph",
|
||||
"model": "openai/gpt-4",
|
||||
"route": {
|
||||
"nodes": ["start", "end"],
|
||||
"edges": [["start", "end"]],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@given("a v3 graph actor blob with a route containing no nodes or edges")
|
||||
def step_graph_actor_blob_empty(context: Context) -> None:
|
||||
context.blob = {
|
||||
"type": "graph",
|
||||
"model": "openai/gpt-4",
|
||||
"route": {},
|
||||
}
|
||||
|
||||
|
||||
@when("I parse the actor configuration from the v3 blob")
|
||||
def step_parse_actor_config(context: Context) -> None:
|
||||
context.actor_config = ActorConfiguration.from_blob(blob=context.blob)
|
||||
|
||||
|
||||
@then("the parsed graph_descriptor node count should be {count:d}")
|
||||
def step_check_graph_descriptor_nodes(context: Context, count: int) -> None:
|
||||
gd = context.actor_config.graph_descriptor
|
||||
assert gd is not None, "graph_descriptor is None"
|
||||
nodes = gd.get("nodes", [])
|
||||
assert len(nodes) == count, f"Expected {count} nodes, got {len(nodes)}: {nodes}"
|
||||
|
||||
|
||||
@then("the parsed graph_descriptor edge count should be {count:d}")
|
||||
def step_check_graph_descriptor_edges(context: Context, count: int) -> None:
|
||||
gd = context.actor_config.graph_descriptor
|
||||
assert gd is not None, "graph_descriptor is None"
|
||||
edges = gd.get("edges", [])
|
||||
assert len(edges) == count, f"Expected {count} edges, got {len(edges)}: {edges}"
|
||||
@@ -408,10 +408,14 @@ class ActorConfiguration(BaseModel):
|
||||
if isinstance(actor_type, str) and actor_type.lower() == "graph":
|
||||
route_raw = data.get("route")
|
||||
if isinstance(route_raw, dict):
|
||||
nodes_raw = route_raw.get("nodes", [])
|
||||
edges_raw = route_raw.get("edges", [])
|
||||
graph_descriptor = {
|
||||
"type": "graph",
|
||||
"route": route_raw,
|
||||
"model": model_value or "",
|
||||
"nodes": nodes_raw,
|
||||
"edges": edges_raw,
|
||||
}
|
||||
|
||||
return provider_value or "custom", model_value, graph_descriptor, unsafe_flag
|
||||
|
||||
@@ -526,10 +526,8 @@ def _print_actor(
|
||||
options_count = len(blob.get("options", {}) or {})
|
||||
|
||||
graph_descriptor = actor.graph_descriptor or {}
|
||||
route = graph_descriptor.get("route", {}) or {}
|
||||
|
||||
nodes_count = len(route.get("nodes", []) or [])
|
||||
edges_count = len(route.get("edges", []) or [])
|
||||
nodes_count = len(graph_descriptor.get("nodes", []) or [])
|
||||
edges_count = len(graph_descriptor.get("edges", []) or [])
|
||||
|
||||
config_details = (
|
||||
f"[bold]Path:[/bold] {path_str}\n"
|
||||
|
||||
Reference in New Issue
Block a user