"""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 " "" ) 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())