Files
cleveragents-core/robot/helper_skill_inline.py

183 lines
5.4 KiB
Python

"""Robot Framework helper for inline tool executor smoke tests.
Provides a CLI-style interface for Robot to invoke inline tool
execution, validation, and write-guard checks.
Exit code 0 = success, 1 = failure.
Usage:
python robot/helper_skill_inline.py execute-simple
python robot/helper_skill_inline.py execute-timeout
python robot/helper_skill_inline.py execute-truncate
python robot/helper_skill_inline.py validate-no-code
python robot/helper_skill_inline.py write-guard
"""
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.domain.models.core.skill import ( # noqa: E402
SkillInlineTool,
)
from cleveragents.domain.models.core.tool import ( # noqa: E402
ToolCapability,
ToolSource,
)
from cleveragents.skills.context import SkillContext # noqa: E402
from cleveragents.skills.inline_executor import InlineToolExecutor # noqa: E402
def _cmd_execute_simple() -> int:
"""Test simple inline tool execution."""
tool = SkillInlineTool(
description="Simple print",
source=ToolSource.CUSTOM,
code='print("hello-robot")',
)
ctx = SkillContext(
plan_id="plan-robot-inline",
project_id="proj-robot-inline",
sandbox_path=Path("/tmp/robot-inline-sandbox"),
)
executor = InlineToolExecutor()
result = executor.execute(tool, ctx, {})
if not result.success:
print(f"inline-fail: {result.error_message}")
return 1
if "hello-robot" not in str(result.output):
print(f"inline-fail: unexpected output {result.output}")
return 1
print("inline-execute-ok")
return 0
def _cmd_execute_timeout() -> int:
"""Test inline tool timeout."""
tool = SkillInlineTool(
description="Sleeping tool",
source=ToolSource.CUSTOM,
code="import time; time.sleep(5)",
)
ctx = SkillContext(
plan_id="plan-robot-timeout",
project_id="proj-robot-timeout",
sandbox_path=Path("/tmp/robot-timeout-sandbox"),
)
executor = InlineToolExecutor(max_runtime_seconds=0.1)
result = executor.execute(tool, ctx, {})
if result.success:
print("inline-fail: expected timeout failure")
return 1
if "timed out" not in (result.error_message or ""):
print(f"inline-fail: unexpected error: {result.error_message}")
return 1
print("inline-timeout-ok")
return 0
def _cmd_execute_truncate() -> int:
"""Test inline tool output truncation."""
tool = SkillInlineTool(
description="Large output tool",
source=ToolSource.CUSTOM,
code='print("X" * 2000)',
)
ctx = SkillContext(
plan_id="plan-robot-truncate",
project_id="proj-robot-truncate",
sandbox_path=Path("/tmp/robot-truncate-sandbox"),
)
executor = InlineToolExecutor(max_output_bytes=100)
result = executor.execute(tool, ctx, {})
if not result.success:
print(f"inline-fail: {result.error_message}")
return 1
if not result.truncated:
print("inline-fail: expected truncated=True")
return 1
print("inline-truncate-ok")
return 0
def _cmd_validate_no_code() -> int:
"""Test validation of tool without code."""
tool = SkillInlineTool(
description="No-code tool",
source=ToolSource.CUSTOM,
code=None,
)
executor = InlineToolExecutor()
errors = executor.validate_tool(tool)
if not errors:
print("inline-fail: expected validation errors")
return 1
if not any("non-empty code" in e for e in errors):
print(f"inline-fail: unexpected errors: {errors}")
return 1
print("inline-validate-ok")
return 0
def _cmd_write_guard() -> int:
"""Test write guard blocks execution in read-only context."""
tool = SkillInlineTool(
description="Write tool",
source=ToolSource.CUSTOM,
code='print("writing")',
capability=ToolCapability(writes=True),
)
ctx = SkillContext(
plan_id="plan-robot-guard",
project_id="proj-robot-guard",
sandbox_path=Path("/tmp/robot-guard-sandbox"),
read_only=True,
)
executor = InlineToolExecutor()
result = executor.execute(tool, ctx, {})
if result.success:
print("inline-fail: expected write guard to block")
return 1
if "denied" not in (result.error_message or "").lower():
print(f"inline-fail: unexpected error: {result.error_message}")
return 1
print("inline-guard-ok")
return 0
_COMMANDS = {
"execute-simple": _cmd_execute_simple,
"execute-timeout": _cmd_execute_timeout,
"execute-truncate": _cmd_execute_truncate,
"validate-no-code": _cmd_validate_no_code,
"write-guard": _cmd_write_guard,
}
def main() -> int:
"""Entry point called by Robot Framework ``Run Process``."""
if len(sys.argv) < 2:
print(
"Usage: helper_skill_inline.py "
"<execute-simple|execute-timeout|execute-truncate"
"|validate-no-code|write-guard>"
)
return 1
command = sys.argv[1]
handler = _COMMANDS.get(command)
if handler is None:
print(f"Unknown command: {command}")
return 1
return handler()
if __name__ == "__main__":
sys.exit(main())