Files
cleveragents-core/robot/helper_skill_cli.py
T
aditya c562557da8
CI / security (pull_request) Successful in 24s
CI / typecheck (pull_request) Successful in 1m1s
CI / quality (pull_request) Successful in 16s
CI / build (pull_request) Successful in 24s
CI / integration_tests (pull_request) Successful in 5m22s
CI / lint (pull_request) Failing after 13s
CI / coverage (pull_request) Has been skipped
CI / unit_tests (pull_request) Successful in 33m12s
CI / docker (pull_request) Has been skipped
feat(cli): add skill commands
2026-02-17 14:44:40 +00:00

242 lines
7.4 KiB
Python

"""Helper script for skill_cli.robot smoke tests.
Each subcommand is a self-contained check that prints a sentinel on success.
"""
from __future__ import annotations
import os
import sys
import tempfile
from datetime import datetime
from pathlib import Path
# Ensure local source tree is importable
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
from typer.testing import CliRunner # noqa: E402
from cleveragents.application.services.skill_service import SkillService # noqa: E402
from cleveragents.cli.commands import skill as skill_mod # noqa: E402
from cleveragents.cli.commands.skill import app as skill_app # noqa: E402
from cleveragents.domain.models.core.skill import Skill # noqa: E402
runner = CliRunner()
_VALID_YAML = """\
name: local/smoke-skill
description: "Smoke test skill"
tools:
- name: builtin/read_file
- name: builtin/list_directory
"""
_COMPOSED_YAML = """\
name: local/composed-smoke
description: "Composed smoke test skill"
tools:
- name: builtin/shell_execute
includes:
- name: local/smoke-skill
"""
def _write_yaml(content: str) -> str:
fd, path = tempfile.mkstemp(suffix=".yaml")
with os.fdopen(fd, "w") as fh:
fh.write(content)
return path
def _fresh_service() -> SkillService:
"""Create and install a fresh SkillService."""
svc = SkillService()
skill_mod._service = svc
return svc
# ---------------------------------------------------------------------------
# Subcommands
# ---------------------------------------------------------------------------
def add_config() -> None:
"""Verify skill add --config works."""
_fresh_service()
path = _write_yaml(_VALID_YAML)
try:
result = runner.invoke(skill_app, ["add", "--config", path])
if result.exit_code == 0 and "Skill Registered" in result.output:
print("skill-cli-add-config-ok")
else:
print(f"FAIL: add returned {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
finally:
Path(path).unlink(missing_ok=True)
def add_duplicate_fails() -> None:
"""Verify that adding a duplicate skill fails without --update."""
svc = _fresh_service()
# Pre-register the skill
skill = Skill(
name="local/smoke-skill",
description="Smoke test skill",
tool_refs=["builtin/read_file"],
)
svc._skills["local/smoke-skill"] = skill
svc._created_at["local/smoke-skill"] = datetime.now()
svc._updated_at["local/smoke-skill"] = datetime.now()
path = _write_yaml(_VALID_YAML)
try:
result = runner.invoke(skill_app, ["add", "--config", path])
if result.exit_code != 0 and "already registered" in result.output:
print("skill-cli-add-duplicate-fails-ok")
else:
print(f"FAIL: expected error, got {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
finally:
Path(path).unlink(missing_ok=True)
def add_update() -> None:
"""Verify skill add --update works."""
svc = _fresh_service()
# Pre-register
skill = Skill(
name="local/smoke-skill",
description="Old description",
tool_refs=["builtin/read_file"],
)
svc._skills["local/smoke-skill"] = skill
svc._created_at["local/smoke-skill"] = datetime.now()
svc._updated_at["local/smoke-skill"] = datetime.now()
path = _write_yaml(_VALID_YAML)
try:
result = runner.invoke(skill_app, ["add", "--config", path, "--update"])
if result.exit_code == 0 and "Skill Updated" in result.output:
print("skill-cli-add-update-ok")
else:
print(f"FAIL: update returned {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
finally:
Path(path).unlink(missing_ok=True)
def show_skill() -> None:
"""Verify skill show works."""
svc = _fresh_service()
skill = Skill(
name="local/smoke-skill",
description="Smoke test skill",
tool_refs=["builtin/read_file", "builtin/list_directory"],
)
svc._skills["local/smoke-skill"] = skill
svc._created_at["local/smoke-skill"] = datetime.now()
svc._updated_at["local/smoke-skill"] = datetime.now()
result = runner.invoke(skill_app, ["show", "local/smoke-skill"])
if result.exit_code == 0 and "Skill Details" in result.output:
print("skill-cli-show-ok")
else:
print(f"FAIL: show returned {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
def tools_skill() -> None:
"""Verify skill tools works."""
svc = _fresh_service()
skill = Skill(
name="local/smoke-skill",
description="Smoke test skill",
tool_refs=["builtin/read_file", "builtin/list_directory"],
)
svc._skills["local/smoke-skill"] = skill
svc._created_at["local/smoke-skill"] = datetime.now()
svc._updated_at["local/smoke-skill"] = datetime.now()
result = runner.invoke(skill_app, ["tools", "local/smoke-skill"])
if result.exit_code == 0 and "Tools for" in result.output:
print("skill-cli-tools-ok")
else:
print(f"FAIL: tools returned {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
def list_skills() -> None:
"""Verify skill list works."""
svc = _fresh_service()
for name in ["local/skill-a", "local/skill-b"]:
skill = Skill(
name=name,
description=f"Test skill {name}",
tool_refs=["builtin/read_file"],
)
svc._skills[name] = skill
svc._created_at[name] = datetime.now()
svc._updated_at[name] = datetime.now()
result = runner.invoke(skill_app, ["list"])
if result.exit_code == 0 and "Summary" in result.output:
print("skill-cli-list-ok")
else:
print(f"FAIL: list returned {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
def remove_skill() -> None:
"""Verify skill remove --yes works."""
svc = _fresh_service()
skill = Skill(
name="local/smoke-skill",
description="Smoke test skill",
tool_refs=["builtin/read_file"],
)
svc._skills["local/smoke-skill"] = skill
svc._created_at["local/smoke-skill"] = datetime.now()
svc._updated_at["local/smoke-skill"] = datetime.now()
result = runner.invoke(skill_app, ["remove", "local/smoke-skill", "--yes"])
if result.exit_code == 0 and "Skill Removed" in result.output:
print("skill-cli-remove-ok")
else:
print(f"FAIL: remove returned {result.exit_code}", file=sys.stderr)
print(result.output, file=sys.stderr)
sys.exit(1)
# ---------------------------------------------------------------------------
# Main dispatcher
# ---------------------------------------------------------------------------
_COMMANDS = {
"add-config": add_config,
"add-duplicate-fails": add_duplicate_fails,
"add-update": add_update,
"show-skill": show_skill,
"tools-skill": tools_skill,
"list-skills": list_skills,
"remove-skill": remove_skill,
}
def main() -> None:
if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
print(f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>", file=sys.stderr)
sys.exit(2)
_COMMANDS[sys.argv[1]]()
if __name__ == "__main__":
main()