Files
cleveragents-core/robot/helper_actor_examples.py
freemo e03fd2956d
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / lint (pull_request) Failing after 18s
CI / helm (pull_request) Successful in 24s
CI / typecheck (pull_request) Failing after 52s
CI / security (pull_request) Failing after 53s
CI / coverage (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / unit_tests (pull_request) Failing after 1m48s
CI / docker (pull_request) Has been skipped
CI / quality (pull_request) Successful in 3m42s
CI / e2e_tests (pull_request) Failing after 13m56s
CI / integration_tests (pull_request) Failing after 21m12s
CI / status-check (pull_request) Failing after 2s
test(actors): fix actor examples missing provider fields and incorrect name
Add missing provider: field to all actor examples in examples/actors/.
Fix llm_with_tools.yaml actor name from assistants/file_analyzer to
local/assistants-file_analyzer (custom actors must use local/ namespace
and cannot contain two slashes).

Add validate-all command to helper_actor_examples.py that uses ActorLoader
to validate all examples via business logic checks. Add integration test
Validate All Actor Examples Import Without Errors to actor_examples.robot
that confirms every example in examples/actors/ can be imported without
errors.

ISSUES CLOSED: #1504
2026-04-02 23:31:25 +00:00

281 lines
8.4 KiB
Python

"""Robot Framework helper for actor YAML examples validation.
Provides CLI-style interface for Robot to validate actor examples,
check patterns, and verify documentation completeness.
Usage:
python robot/helper_actor_examples.py validate <yaml_file>
python robot/helper_actor_examples.py validate-invalid <yaml_file>
python robot/helper_actor_examples.py count-examples <directory>
python robot/helper_actor_examples.py check-pattern <yaml_file> <pattern>
python robot/helper_actor_examples.py check-docs <doc_file>
python robot/helper_actor_examples.py check-doc-patterns <doc_file>
python robot/helper_actor_examples.py validate-all <directory>
"""
from __future__ import annotations
import sys
from pathlib import Path
# Ensure the src directory is on the import path.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
from cleveragents.actor.loader import ActorLoader # noqa: E402
from cleveragents.actor.schema import ActorConfigSchema, ActorType # noqa: E402
def validate_actor(yaml_path: str) -> int:
"""Validate actor YAML and print details."""
try:
config = ActorConfigSchema.from_yaml_file(yaml_path)
print("actor-ok")
print(f"name:{config.name}")
print(f"type:{config.type.value}")
if config.tools:
print("has-tools")
if config.skills:
print("has-skills")
if config.route:
print("has-route")
if config.env_vars:
print("has-env-vars")
if config.memory:
print("has-memory")
if config.context_view:
print(f"context-view:{config.context_view.value}")
return 0
except Exception as exc:
print(f"actor-fail: {exc}")
return 1
def validate_invalid_actor(yaml_path: str) -> int:
"""Expect validation to fail."""
try:
ActorConfigSchema.from_yaml_file(yaml_path)
print("unexpected-success")
return 1
except Exception as exc:
print("expected-fail")
error_msg = str(exc).lower()
if "namespace" in error_msg or "name" in error_msg:
print("namespace")
if "model" in error_msg:
print("model")
if "tool" in error_msg:
print("tool")
if "route" in error_msg:
print("route")
return 0
def count_examples(directory: str) -> int:
"""Count YAML example files."""
try:
examples_dir = Path(directory)
yaml_files = list(examples_dir.glob("*.yaml"))
print(f"example-count:{len(yaml_files)}")
return 0
except Exception as exc:
print(f"count-fail: {exc}")
return 1
def check_pattern(yaml_path: str, pattern: str) -> int:
"""Check if actor follows a specific pattern."""
try:
config = ActorConfigSchema.from_yaml_file(yaml_path)
if pattern == "strategist":
# Strategist pattern: large context, read-only tools, memory enabled
if config.memory and config.memory.enabled:
print("has-memory")
if config.context_view:
print(f"context-view:{config.context_view.value}")
print(f"pattern-ok:{pattern}")
elif pattern == "tool-only":
# Tool-only pattern: no model, has tools
if config.type == ActorType.TOOL:
print("pattern-ok:tool-only")
if not config.model:
print("no-model")
elif pattern == "graph":
# Graph pattern: has route with entry/exit nodes
if config.route:
print("pattern-ok:graph")
if config.route.entry_node:
print("has-entry-node")
if config.route.exit_nodes:
print("has-exit-nodes")
elif pattern == "hierarchical":
# Hierarchical pattern: graph with subgraph nodes
if config.route:
print("pattern-ok:hierarchical")
# Check for subgraph nodes
from cleveragents.actor.schema import NodeType
subgraph_nodes = [
node
for node in config.route.nodes
if node.type == NodeType.SUBGRAPH
]
if subgraph_nodes:
print("has-subgraph")
return 0
except Exception as exc:
print(f"pattern-check-fail: {exc}")
return 1
def check_docs(doc_file: str) -> int:
"""Check if documentation references all example files."""
try:
doc_path = Path(doc_file)
doc_content = doc_path.read_text()
example_files = [
"simple_llm.yaml",
"llm_with_tools.yaml",
"estimator.yaml",
"tool_collection.yaml",
"simple_graph.yaml",
"graph_workflow.yaml",
]
for filename in example_files:
if filename in doc_content:
print(f"doc-references:{filename}")
return 0
except Exception as exc:
print(f"doc-check-fail: {exc}")
return 1
def check_doc_patterns(doc_file: str) -> int:
"""Check if documentation includes all required patterns."""
try:
doc_path = Path(doc_file)
doc_content = doc_path.read_text().lower()
patterns = [
"strategist",
"executor",
"reviewer",
"tool-only",
"validation",
"hierarchical",
]
for pattern in patterns:
if pattern in doc_content:
print(f"has-pattern:{pattern}")
return 0
except Exception as exc:
print(f"doc-pattern-check-fail: {exc}")
return 1
def validate_all_examples(directory: str) -> int:
"""Validate all actor examples in a directory via ActorLoader business logic.
Uses ActorLoader (which applies ActorConfigSchema validation) to discover
and validate every YAML file in the given directory. Prints one
``actor-imported:<name>`` line per successfully loaded actor and a final
``all-examples-ok:<count>`` summary line. Returns 1 on any failure.
"""
try:
examples_dir = Path(directory)
loader = ActorLoader(search_roots=[examples_dir])
actors = loader.discover()
for actor in actors:
print(f"actor-imported:{actor.name}")
print(f"all-examples-ok:{len(actors)}")
return 0
except Exception as exc:
print(f"validate-all-fail: {exc}")
return 1
def main() -> int:
"""Entry point called by Robot Framework ``Run Process``."""
if len(sys.argv) < 2:
print(
"Usage: helper_actor_examples.py <command> [args...]\n"
"Commands:\n"
" validate <file>\n"
" validate-invalid <file>\n"
" count-examples <directory>\n"
" check-pattern <file> <pattern>\n"
" check-docs <doc_file>\n"
" check-doc-patterns <doc_file>\n"
" validate-all <directory>"
)
return 1
command = sys.argv[1]
if command == "validate":
if len(sys.argv) < 3:
print("Usage: validate <yaml_file>")
return 1
return validate_actor(sys.argv[2])
if command == "validate-invalid":
if len(sys.argv) < 3:
print("Usage: validate-invalid <yaml_file>")
return 1
return validate_invalid_actor(sys.argv[2])
if command == "count-examples":
if len(sys.argv) < 3:
print("Usage: count-examples <directory>")
return 1
return count_examples(sys.argv[2])
if command == "check-pattern":
if len(sys.argv) < 4:
print("Usage: check-pattern <yaml_file> <pattern>")
return 1
return check_pattern(sys.argv[2], sys.argv[3])
if command == "check-docs":
if len(sys.argv) < 3:
print("Usage: check-docs <doc_file>")
return 1
return check_docs(sys.argv[2])
if command == "check-doc-patterns":
if len(sys.argv) < 3:
print("Usage: check-doc-patterns <doc_file>")
return 1
return check_doc_patterns(sys.argv[2])
if command == "validate-all":
if len(sys.argv) < 3:
print("Usage: validate-all <directory>")
return 1
return validate_all_examples(sys.argv[2])
print(f"Unknown command: {command}")
return 1
if __name__ == "__main__":
sys.exit(main())