zetro-sentinel-sdk 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zetro_sentinel_sdk/__init__.py +63 -0
- zetro_sentinel_sdk/cli.py +201 -0
- zetro_sentinel_sdk/client.py +890 -0
- zetro_sentinel_sdk/exceptions.py +44 -0
- zetro_sentinel_sdk/models.py +174 -0
- zetro_sentinel_sdk/skills/__init__.py +1 -0
- zetro_sentinel_sdk/skills/setup-sentinel.md +386 -0
- zetro_sentinel_sdk-0.3.0.dist-info/METADATA +223 -0
- zetro_sentinel_sdk-0.3.0.dist-info/RECORD +12 -0
- zetro_sentinel_sdk-0.3.0.dist-info/WHEEL +5 -0
- zetro_sentinel_sdk-0.3.0.dist-info/entry_points.txt +2 -0
- zetro_sentinel_sdk-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AI Sentinel Python SDK
|
|
3
|
+
|
|
4
|
+
Simple, type-safe SDK for integrating AI Sentinel security into your AI agents.
|
|
5
|
+
|
|
6
|
+
Basic usage:
|
|
7
|
+
from zetro_sentinel_sdk import Sentinel
|
|
8
|
+
|
|
9
|
+
sentinel = Sentinel(api_key="your-api-key")
|
|
10
|
+
|
|
11
|
+
# Scan input
|
|
12
|
+
result = sentinel.scan_input("Hello, how are you?", agent_id="my-agent")
|
|
13
|
+
if not result.allowed:
|
|
14
|
+
print(f"Blocked: {result.reason}")
|
|
15
|
+
|
|
16
|
+
# Authorize tool call
|
|
17
|
+
auth = sentinel.authorize_tool(
|
|
18
|
+
agent_id="my-agent",
|
|
19
|
+
tool_name="send_email",
|
|
20
|
+
user_role="USER",
|
|
21
|
+
user_id="user-123"
|
|
22
|
+
)
|
|
23
|
+
if not auth.allowed:
|
|
24
|
+
print(f"Denied: {auth.reason}")
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
__version__ = "0.3.0"
|
|
28
|
+
|
|
29
|
+
from zetro_sentinel_sdk.client import Sentinel, AsyncSentinel
|
|
30
|
+
from zetro_sentinel_sdk.models import (
|
|
31
|
+
ScanResult,
|
|
32
|
+
AuthorizeResult,
|
|
33
|
+
ActionSourceResult,
|
|
34
|
+
HierarchyResult,
|
|
35
|
+
Incident,
|
|
36
|
+
ToolExecution,
|
|
37
|
+
ToolExecutionList,
|
|
38
|
+
)
|
|
39
|
+
from zetro_sentinel_sdk.exceptions import (
|
|
40
|
+
SentinelError,
|
|
41
|
+
AuthenticationError,
|
|
42
|
+
RateLimitError,
|
|
43
|
+
ValidationError,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
# Client
|
|
48
|
+
"Sentinel",
|
|
49
|
+
"AsyncSentinel",
|
|
50
|
+
# Models
|
|
51
|
+
"ScanResult",
|
|
52
|
+
"AuthorizeResult",
|
|
53
|
+
"ActionSourceResult",
|
|
54
|
+
"HierarchyResult",
|
|
55
|
+
"Incident",
|
|
56
|
+
"ToolExecution",
|
|
57
|
+
"ToolExecutionList",
|
|
58
|
+
# Exceptions
|
|
59
|
+
"SentinelError",
|
|
60
|
+
"AuthenticationError",
|
|
61
|
+
"RateLimitError",
|
|
62
|
+
"ValidationError",
|
|
63
|
+
]
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""AI Sentinel CLI.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
sentinel install-skill Install Claude Code setup wizard skill
|
|
5
|
+
sentinel --version Show version
|
|
6
|
+
sentinel --help Show help
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import shutil
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from zetro_sentinel_sdk import __version__
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_skills_dir() -> Path:
|
|
18
|
+
"""Get the directory containing bundled skills."""
|
|
19
|
+
return Path(__file__).parent / "skills"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_claude_commands_dir() -> Path:
|
|
23
|
+
"""Get the Claude Code commands directory."""
|
|
24
|
+
return Path.home() / ".claude" / "commands"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def install_skill(skill_name: str = "setup-sentinel") -> bool:
|
|
28
|
+
"""
|
|
29
|
+
Install a Claude Code skill to the user's global commands directory.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
skill_name: Name of the skill to install (without .md extension)
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
True if successful, False otherwise
|
|
36
|
+
"""
|
|
37
|
+
skills_dir = get_skills_dir()
|
|
38
|
+
skill_file = skills_dir / f"{skill_name}.md"
|
|
39
|
+
|
|
40
|
+
if not skill_file.exists():
|
|
41
|
+
print(f"Error: Skill '{skill_name}' not found in package.")
|
|
42
|
+
print(f"Available skills:")
|
|
43
|
+
for f in skills_dir.glob("*.md"):
|
|
44
|
+
print(f" - {f.stem}")
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
# Create Claude commands directory if it doesn't exist
|
|
48
|
+
claude_commands_dir = get_claude_commands_dir()
|
|
49
|
+
claude_commands_dir.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
|
|
51
|
+
# Copy the skill file
|
|
52
|
+
dest_file = claude_commands_dir / f"{skill_name}.md"
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
shutil.copy2(skill_file, dest_file)
|
|
56
|
+
print(f"Successfully installed '{skill_name}' skill!")
|
|
57
|
+
print()
|
|
58
|
+
print(f"Location: {dest_file}")
|
|
59
|
+
print()
|
|
60
|
+
print("Usage:")
|
|
61
|
+
print(f" In any project, run: /{skill_name}")
|
|
62
|
+
print()
|
|
63
|
+
print("This will start the AI Sentinel setup wizard that walks you through:")
|
|
64
|
+
print(" 1. Environment detection")
|
|
65
|
+
print(" 2. API key configuration")
|
|
66
|
+
print(" 3. SDK integration")
|
|
67
|
+
print(" 4. Code generation")
|
|
68
|
+
print(" 5. Testing your setup")
|
|
69
|
+
return True
|
|
70
|
+
except PermissionError:
|
|
71
|
+
print(f"Error: Permission denied writing to {dest_file}")
|
|
72
|
+
print("Try running with appropriate permissions.")
|
|
73
|
+
return False
|
|
74
|
+
except Exception as e:
|
|
75
|
+
print(f"Error installing skill: {e}")
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def list_skills() -> None:
|
|
80
|
+
"""List available skills."""
|
|
81
|
+
skills_dir = get_skills_dir()
|
|
82
|
+
print("Available AI Sentinel skills:")
|
|
83
|
+
print()
|
|
84
|
+
for skill_file in skills_dir.glob("*.md"):
|
|
85
|
+
print(f" {skill_file.stem}")
|
|
86
|
+
# Read first line as description
|
|
87
|
+
with open(skill_file) as f:
|
|
88
|
+
first_line = f.readline().strip()
|
|
89
|
+
if first_line.startswith("# "):
|
|
90
|
+
print(f" {first_line[2:]}")
|
|
91
|
+
print()
|
|
92
|
+
print("Install with: sentinel install-skill <name>")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def uninstall_skill(skill_name: str = "setup-sentinel") -> bool:
|
|
96
|
+
"""
|
|
97
|
+
Uninstall a Claude Code skill.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
skill_name: Name of the skill to uninstall
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
True if successful, False otherwise
|
|
104
|
+
"""
|
|
105
|
+
claude_commands_dir = get_claude_commands_dir()
|
|
106
|
+
skill_file = claude_commands_dir / f"{skill_name}.md"
|
|
107
|
+
|
|
108
|
+
if not skill_file.exists():
|
|
109
|
+
print(f"Skill '{skill_name}' is not installed.")
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
skill_file.unlink()
|
|
114
|
+
print(f"Successfully uninstalled '{skill_name}' skill.")
|
|
115
|
+
return True
|
|
116
|
+
except Exception as e:
|
|
117
|
+
print(f"Error uninstalling skill: {e}")
|
|
118
|
+
return False
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def main() -> int:
|
|
122
|
+
"""Main CLI entry point."""
|
|
123
|
+
parser = argparse.ArgumentParser(
|
|
124
|
+
prog="sentinel",
|
|
125
|
+
description="AI Sentinel CLI - Security firewall for AI agents",
|
|
126
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
127
|
+
epilog="""
|
|
128
|
+
Examples:
|
|
129
|
+
sentinel install-skill Install the setup wizard skill
|
|
130
|
+
sentinel install-skill setup-sentinel
|
|
131
|
+
sentinel uninstall-skill Remove the setup wizard skill
|
|
132
|
+
sentinel list-skills List available skills
|
|
133
|
+
|
|
134
|
+
After installing, use /setup-sentinel in Claude Code to start the wizard.
|
|
135
|
+
|
|
136
|
+
Documentation: https://docs.zetro.ai
|
|
137
|
+
Dashboard: https://app.zetro.ai
|
|
138
|
+
"""
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
parser.add_argument(
|
|
142
|
+
"--version", "-v",
|
|
143
|
+
action="version",
|
|
144
|
+
version=f"%(prog)s {__version__}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
subparsers = parser.add_subparsers(dest="command", help="Commands")
|
|
148
|
+
|
|
149
|
+
# install-skill command
|
|
150
|
+
install_parser = subparsers.add_parser(
|
|
151
|
+
"install-skill",
|
|
152
|
+
help="Install Claude Code skill to ~/.claude/commands/"
|
|
153
|
+
)
|
|
154
|
+
install_parser.add_argument(
|
|
155
|
+
"skill",
|
|
156
|
+
nargs="?",
|
|
157
|
+
default="setup-sentinel",
|
|
158
|
+
help="Skill name to install (default: setup-sentinel)"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# uninstall-skill command
|
|
162
|
+
uninstall_parser = subparsers.add_parser(
|
|
163
|
+
"uninstall-skill",
|
|
164
|
+
help="Uninstall a Claude Code skill"
|
|
165
|
+
)
|
|
166
|
+
uninstall_parser.add_argument(
|
|
167
|
+
"skill",
|
|
168
|
+
nargs="?",
|
|
169
|
+
default="setup-sentinel",
|
|
170
|
+
help="Skill name to uninstall (default: setup-sentinel)"
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# list-skills command
|
|
174
|
+
subparsers.add_parser(
|
|
175
|
+
"list-skills",
|
|
176
|
+
help="List available skills"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
args = parser.parse_args()
|
|
180
|
+
|
|
181
|
+
if args.command is None:
|
|
182
|
+
parser.print_help()
|
|
183
|
+
return 0
|
|
184
|
+
|
|
185
|
+
if args.command == "install-skill":
|
|
186
|
+
success = install_skill(args.skill)
|
|
187
|
+
return 0 if success else 1
|
|
188
|
+
|
|
189
|
+
elif args.command == "uninstall-skill":
|
|
190
|
+
success = uninstall_skill(args.skill)
|
|
191
|
+
return 0 if success else 1
|
|
192
|
+
|
|
193
|
+
elif args.command == "list-skills":
|
|
194
|
+
list_skills()
|
|
195
|
+
return 0
|
|
196
|
+
|
|
197
|
+
return 0
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
if __name__ == "__main__":
|
|
201
|
+
sys.exit(main())
|