3d2cd05f56
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 28s
CI / quality (pull_request) Successful in 16s
CI / security (pull_request) Successful in 51s
CI / build (pull_request) Successful in 21s
CI / integration_tests (pull_request) Successful in 9m6s
CI / unit_tests (pull_request) Failing after 26m29s
CI / coverage (pull_request) Successful in 8m38s
CI / docker (pull_request) Has been skipped
202 lines
6.1 KiB
Python
202 lines
6.1 KiB
Python
"""Robot Framework helper for Tool/Validation domain model smoke tests.
|
|
|
|
Provides a CLI-style interface for Robot to invoke model creation and
|
|
YAML config loading. Exit code 0 = success, 1 = failure.
|
|
|
|
Usage:
|
|
python robot/helper_tool_model.py create-tool
|
|
python robot/helper_tool_model.py create-validation
|
|
python robot/helper_tool_model.py load-tool-yaml <yaml_file>
|
|
python robot/helper_tool_model.py load-validation-yaml <yaml_file>
|
|
python robot/helper_tool_model.py validate-constraints
|
|
python robot/helper_tool_model.py validate-invalid-tool
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
# 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.domain.models.core.tool import ( # noqa: E402
|
|
Tool,
|
|
ToolCapability,
|
|
ToolSource,
|
|
ToolType,
|
|
Validation,
|
|
ValidationMode,
|
|
)
|
|
|
|
|
|
def _cmd_create_tool() -> int:
|
|
"""Create a minimal Tool and verify fields."""
|
|
tool = Tool(
|
|
name="smoke/robot-tool",
|
|
description="Robot smoke test tool",
|
|
source=ToolSource.BUILTIN,
|
|
)
|
|
assert tool.name == "smoke/robot-tool"
|
|
assert tool.namespace == "smoke"
|
|
assert tool.short_name == "robot-tool"
|
|
assert tool.source == ToolSource.BUILTIN
|
|
assert tool.tool_type == ToolType.TOOL
|
|
assert tool.timeout == 300
|
|
print(f"tool-model-ok: {tool.name}")
|
|
return 0
|
|
|
|
|
|
def _cmd_create_validation() -> int:
|
|
"""Create a Validation and verify forced constraints."""
|
|
val = Validation(
|
|
name="smoke/robot-val",
|
|
description="Robot smoke validation",
|
|
source=ToolSource.BUILTIN,
|
|
)
|
|
assert val.tool_type == ToolType.VALIDATION
|
|
assert val.capability.read_only is True
|
|
assert val.capability.writes is False
|
|
assert val.capability.checkpointable is False
|
|
assert val.mode == ValidationMode.REQUIRED
|
|
print(f"validation-model-ok: {val.name}")
|
|
return 0
|
|
|
|
|
|
def _cmd_load_tool_yaml(yaml_path: str) -> int:
|
|
"""Load a Tool from a YAML config file and verify."""
|
|
path = Path(yaml_path)
|
|
if not path.exists():
|
|
print(f"tool-yaml-fail: file not found: {yaml_path}")
|
|
return 1
|
|
with path.open() as f:
|
|
config: dict[str, Any] = yaml.safe_load(f)
|
|
tool = Tool.from_config(config)
|
|
cli_dict = tool.as_cli_dict()
|
|
assert "name" in cli_dict
|
|
assert "source" in cli_dict
|
|
assert "capability" in cli_dict
|
|
print(f"tool-yaml-ok: {tool.name} source={tool.source.value}")
|
|
return 0
|
|
|
|
|
|
def _cmd_load_validation_yaml(yaml_path: str) -> int:
|
|
"""Load a Validation from a YAML config file and verify."""
|
|
path = Path(yaml_path)
|
|
if not path.exists():
|
|
print(f"validation-yaml-fail: file not found: {yaml_path}")
|
|
return 1
|
|
with path.open() as f:
|
|
config: dict[str, Any] = yaml.safe_load(f)
|
|
val = Validation.from_config(config)
|
|
assert val.tool_type == ToolType.VALIDATION
|
|
assert val.capability.read_only is True
|
|
assert val.capability.writes is False
|
|
cli_dict = val.as_cli_dict()
|
|
assert "mode" in cli_dict
|
|
print(f"validation-yaml-ok: {val.name} mode={val.mode.value}")
|
|
return 0
|
|
|
|
|
|
def _cmd_validate_constraints() -> int:
|
|
"""Verify that Validation forces read_only and blocks writes."""
|
|
val = Validation(
|
|
name="smoke/constraint-check",
|
|
description="Constraint test",
|
|
source=ToolSource.BUILTIN,
|
|
capability=ToolCapability(writes=True, checkpointable=True),
|
|
)
|
|
# Validation must force these even when given writable capability
|
|
assert val.capability.read_only is True, "Validation must force read_only=True"
|
|
assert val.capability.writes is False, "Validation must force writes=False"
|
|
assert val.capability.checkpointable is False, (
|
|
"Validation must force checkpointable=False"
|
|
)
|
|
print("validate-constraints-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_validate_invalid_tool() -> int:
|
|
"""Verify that invalid tool config is rejected."""
|
|
from pydantic import ValidationError
|
|
|
|
# Test: invalid name pattern
|
|
try:
|
|
Tool(
|
|
name="no-namespace",
|
|
description="Bad name",
|
|
source=ToolSource.BUILTIN,
|
|
)
|
|
print("validate-invalid-unexpected-success: bad name accepted")
|
|
return 1
|
|
except ValidationError:
|
|
pass
|
|
|
|
# Test: custom source without code
|
|
try:
|
|
Tool(
|
|
name="local/test",
|
|
description="Missing code",
|
|
source=ToolSource.CUSTOM,
|
|
)
|
|
print("validate-invalid-unexpected-success: missing code accepted")
|
|
return 1
|
|
except ValidationError:
|
|
pass
|
|
|
|
# Test: read_only with writes
|
|
try:
|
|
ToolCapability(read_only=True, writes=True)
|
|
print("validate-invalid-unexpected-success: read_only+writes accepted")
|
|
return 1
|
|
except ValidationError:
|
|
pass
|
|
|
|
print("validate-invalid-ok")
|
|
return 0
|
|
|
|
|
|
def main() -> int:
|
|
"""Entry point called by Robot Framework ``Run Process``."""
|
|
if len(sys.argv) < 2:
|
|
print(
|
|
"Usage: helper_tool_model.py "
|
|
"<create-tool|create-validation|load-tool-yaml|"
|
|
"load-validation-yaml|validate-constraints|validate-invalid-tool> "
|
|
"[args...]"
|
|
)
|
|
return 1
|
|
|
|
command = sys.argv[1]
|
|
|
|
if command == "create-tool":
|
|
return _cmd_create_tool()
|
|
if command == "create-validation":
|
|
return _cmd_create_validation()
|
|
if command == "load-tool-yaml":
|
|
if len(sys.argv) < 3:
|
|
print("Usage: helper_tool_model.py load-tool-yaml <file>")
|
|
return 1
|
|
return _cmd_load_tool_yaml(sys.argv[2])
|
|
if command == "load-validation-yaml":
|
|
if len(sys.argv) < 3:
|
|
print("Usage: helper_tool_model.py load-validation-yaml <file>")
|
|
return 1
|
|
return _cmd_load_validation_yaml(sys.argv[2])
|
|
if command == "validate-constraints":
|
|
return _cmd_validate_constraints()
|
|
if command == "validate-invalid-tool":
|
|
return _cmd_validate_invalid_tool()
|
|
|
|
print(f"Unknown command: {command}")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|