Builds the proton-vpn skill per ARCHITECTURE.md section 6 with 9 tools: Tools: - proton_vpn_connect — connect with fastest/random/country/city/P2P/Tor/SC selection - proton_vpn_disconnect — disconnect current session - proton_vpn_status — check connection status (parse CLI output) - proton_vpn_servers — list servers with filters (country, features) - proton_vpn_killswitch — enable/disable kill switch - proton_vpn_config — view/modify DNS, NetShield, protocol - proton_vpn_login — initiate browser OAuth login - proton_vpn_logout — clear credentials - proton_vpn_refresh — refresh server list and config Implementation: - Python subprocess wrapper around official protonvpn-cli v1.0+ - Human-readable CLI output parsed into structured JSON - Privilege check (protonvpn group) before privileged operations - 30-60s timeouts with graceful error handling - dispatch() entry point for Hermes tool routing Also includes: - scripts/install.sh — distro-aware dependency installer - references/commands.md — CLI quick reference - .gitignore — exclude __pycache__, env, debug files Deviations from ARCHITECTURE.md noted in docs: - CLI uses 'login' (browser OAuth), not 'init' - No --json output — parsed from tables - Install via Proton repos, not PyPI
23 lines
844 B
Python
23 lines
844 B
Python
#!/usr/bin/env python3
|
|
"""Verify proton-vpn skill module loads and all tools are registered."""
|
|
import sys
|
|
sys.path.insert(0, 'skills/proton-vpn/scripts')
|
|
|
|
import tools
|
|
import json
|
|
|
|
# Verify all tools are in registry
|
|
print("=== Tool Registry ===")
|
|
for name, info in sorted(tools.TOOLS.items()):
|
|
params = info["schema"].get("parameters", {}).get("properties", {})
|
|
print(f" ✓ {name} — {len(params)} params")
|
|
|
|
print(f"\nTotal tools: {len(tools.TOOLS)}")
|
|
|
|
# Test dispatch for error cases (no CLI installed = expected)
|
|
result = json.loads(tools.dispatch('proton_vpn_status'))
|
|
print(f"\nStatus dispatch (expected error — no CLI): success={result.get('success')}")
|
|
print(f" error={result.get('error', '')[:120]}")
|
|
|
|
result2 = json.loads(tools.dispatch('nonexistent'))
|
|
print(f"\nNonexistent tool: error={result2.get('error', '')[:80]}")
|