agentfense 0.2.1__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.
- agentfense/__init__.py +191 -0
- agentfense/_async/__init__.py +21 -0
- agentfense/_async/client.py +679 -0
- agentfense/_async/sandbox.py +667 -0
- agentfense/_gen/__init__.py +0 -0
- agentfense/_gen/codebase_pb2.py +78 -0
- agentfense/_gen/codebase_pb2.pyi +141 -0
- agentfense/_gen/codebase_pb2_grpc.py +366 -0
- agentfense/_gen/common_pb2.py +47 -0
- agentfense/_gen/common_pb2.pyi +68 -0
- agentfense/_gen/common_pb2_grpc.py +24 -0
- agentfense/_gen/sandbox_pb2.py +123 -0
- agentfense/_gen/sandbox_pb2.pyi +255 -0
- agentfense/_gen/sandbox_pb2_grpc.py +678 -0
- agentfense/_shared.py +238 -0
- agentfense/client.py +751 -0
- agentfense/exceptions.py +333 -0
- agentfense/presets.py +192 -0
- agentfense/sandbox.py +672 -0
- agentfense/types.py +256 -0
- agentfense/utils.py +286 -0
- agentfense-0.2.1.dist-info/METADATA +378 -0
- agentfense-0.2.1.dist-info/RECORD +25 -0
- agentfense-0.2.1.dist-info/WHEEL +5 -0
- agentfense-0.2.1.dist-info/top_level.txt +1 -0
agentfense/_shared.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""Shared utility functions for sync and async clients.
|
|
2
|
+
|
|
3
|
+
This module contains conversion functions between protobuf messages and
|
|
4
|
+
Python dataclasses, used by both synchronous and asynchronous clients.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime, timedelta
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from ._gen import sandbox_pb2
|
|
11
|
+
from ._gen import codebase_pb2
|
|
12
|
+
from ._gen import common_pb2
|
|
13
|
+
from .types import (
|
|
14
|
+
Codebase,
|
|
15
|
+
FileInfo,
|
|
16
|
+
Permission,
|
|
17
|
+
PatternType,
|
|
18
|
+
PermissionRule,
|
|
19
|
+
ResourceLimits,
|
|
20
|
+
RuntimeType,
|
|
21
|
+
Sandbox,
|
|
22
|
+
SandboxStatus,
|
|
23
|
+
Session,
|
|
24
|
+
SessionStatus,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ============================================
|
|
29
|
+
# Permission Conversions
|
|
30
|
+
# ============================================
|
|
31
|
+
|
|
32
|
+
def permission_to_proto(perm: Permission) -> common_pb2.Permission:
|
|
33
|
+
"""Convert Permission enum to protobuf."""
|
|
34
|
+
mapping = {
|
|
35
|
+
Permission.NONE: common_pb2.PERMISSION_NONE,
|
|
36
|
+
Permission.VIEW: common_pb2.PERMISSION_VIEW,
|
|
37
|
+
Permission.READ: common_pb2.PERMISSION_READ,
|
|
38
|
+
Permission.WRITE: common_pb2.PERMISSION_WRITE,
|
|
39
|
+
}
|
|
40
|
+
return mapping.get(perm, common_pb2.PERMISSION_UNSPECIFIED)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def proto_to_permission(perm: common_pb2.Permission) -> Permission:
|
|
44
|
+
"""Convert protobuf Permission to enum."""
|
|
45
|
+
mapping = {
|
|
46
|
+
common_pb2.PERMISSION_NONE: Permission.NONE,
|
|
47
|
+
common_pb2.PERMISSION_VIEW: Permission.VIEW,
|
|
48
|
+
common_pb2.PERMISSION_READ: Permission.READ,
|
|
49
|
+
common_pb2.PERMISSION_WRITE: Permission.WRITE,
|
|
50
|
+
}
|
|
51
|
+
return mapping.get(perm, Permission.NONE)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def pattern_type_to_proto(pt: PatternType) -> common_pb2.PatternType:
|
|
55
|
+
"""Convert PatternType enum to protobuf."""
|
|
56
|
+
mapping = {
|
|
57
|
+
PatternType.GLOB: common_pb2.PATTERN_TYPE_GLOB,
|
|
58
|
+
PatternType.DIRECTORY: common_pb2.PATTERN_TYPE_DIRECTORY,
|
|
59
|
+
PatternType.FILE: common_pb2.PATTERN_TYPE_FILE,
|
|
60
|
+
}
|
|
61
|
+
return mapping.get(pt, common_pb2.PATTERN_TYPE_UNSPECIFIED)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def proto_to_pattern_type(pt: common_pb2.PatternType) -> PatternType:
|
|
65
|
+
"""Convert protobuf PatternType to enum."""
|
|
66
|
+
mapping = {
|
|
67
|
+
common_pb2.PATTERN_TYPE_GLOB: PatternType.GLOB,
|
|
68
|
+
common_pb2.PATTERN_TYPE_DIRECTORY: PatternType.DIRECTORY,
|
|
69
|
+
common_pb2.PATTERN_TYPE_FILE: PatternType.FILE,
|
|
70
|
+
}
|
|
71
|
+
return mapping.get(pt, PatternType.GLOB)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ============================================
|
|
75
|
+
# Status Conversions
|
|
76
|
+
# ============================================
|
|
77
|
+
|
|
78
|
+
def proto_to_status(status: common_pb2.SandboxStatus) -> SandboxStatus:
|
|
79
|
+
"""Convert protobuf SandboxStatus to enum."""
|
|
80
|
+
mapping = {
|
|
81
|
+
common_pb2.SANDBOX_STATUS_PENDING: SandboxStatus.PENDING,
|
|
82
|
+
common_pb2.SANDBOX_STATUS_RUNNING: SandboxStatus.RUNNING,
|
|
83
|
+
common_pb2.SANDBOX_STATUS_STOPPED: SandboxStatus.STOPPED,
|
|
84
|
+
common_pb2.SANDBOX_STATUS_ERROR: SandboxStatus.ERROR,
|
|
85
|
+
}
|
|
86
|
+
return mapping.get(status, SandboxStatus.PENDING)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def proto_to_session_status(status: common_pb2.SessionStatus) -> SessionStatus:
|
|
90
|
+
"""Convert protobuf SessionStatus to enum."""
|
|
91
|
+
mapping = {
|
|
92
|
+
common_pb2.SESSION_STATUS_UNSPECIFIED: SessionStatus.UNKNOWN,
|
|
93
|
+
common_pb2.SESSION_STATUS_ACTIVE: SessionStatus.ACTIVE,
|
|
94
|
+
common_pb2.SESSION_STATUS_CLOSED: SessionStatus.CLOSED,
|
|
95
|
+
}
|
|
96
|
+
return mapping.get(status, SessionStatus.UNKNOWN)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# ============================================
|
|
100
|
+
# Runtime Conversions
|
|
101
|
+
# ============================================
|
|
102
|
+
|
|
103
|
+
def runtime_type_to_proto(rt: RuntimeType) -> sandbox_pb2.RuntimeType:
|
|
104
|
+
"""Convert RuntimeType enum to protobuf."""
|
|
105
|
+
mapping = {
|
|
106
|
+
RuntimeType.BWRAP: sandbox_pb2.RUNTIME_TYPE_BWRAP,
|
|
107
|
+
RuntimeType.DOCKER: sandbox_pb2.RUNTIME_TYPE_DOCKER,
|
|
108
|
+
}
|
|
109
|
+
return mapping.get(rt, sandbox_pb2.RUNTIME_TYPE_UNSPECIFIED)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def proto_to_runtime_type(rt: sandbox_pb2.RuntimeType) -> RuntimeType:
|
|
113
|
+
"""Convert protobuf RuntimeType to enum."""
|
|
114
|
+
mapping = {
|
|
115
|
+
sandbox_pb2.RUNTIME_TYPE_BWRAP: RuntimeType.BWRAP,
|
|
116
|
+
sandbox_pb2.RUNTIME_TYPE_DOCKER: RuntimeType.DOCKER,
|
|
117
|
+
}
|
|
118
|
+
return mapping.get(rt, RuntimeType.BWRAP)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# ============================================
|
|
122
|
+
# Resource Limits Conversions
|
|
123
|
+
# ============================================
|
|
124
|
+
|
|
125
|
+
def resource_limits_to_proto(
|
|
126
|
+
limits: Optional[ResourceLimits],
|
|
127
|
+
) -> Optional[sandbox_pb2.ResourceLimits]:
|
|
128
|
+
"""Convert ResourceLimits to protobuf."""
|
|
129
|
+
if limits is None:
|
|
130
|
+
return None
|
|
131
|
+
return sandbox_pb2.ResourceLimits(
|
|
132
|
+
memory_bytes=limits.memory_bytes or 0,
|
|
133
|
+
cpu_quota=limits.cpu_quota or 0,
|
|
134
|
+
cpu_shares=limits.cpu_shares or 0,
|
|
135
|
+
pids_limit=limits.pids_limit or 0,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def proto_to_resource_limits(
|
|
140
|
+
pb: Optional[sandbox_pb2.ResourceLimits],
|
|
141
|
+
) -> Optional[ResourceLimits]:
|
|
142
|
+
"""Convert protobuf ResourceLimits to dataclass."""
|
|
143
|
+
if pb is None:
|
|
144
|
+
return None
|
|
145
|
+
# Check if any limit is set
|
|
146
|
+
if not any([pb.memory_bytes, pb.cpu_quota, pb.cpu_shares, pb.pids_limit]):
|
|
147
|
+
return None
|
|
148
|
+
return ResourceLimits(
|
|
149
|
+
memory_bytes=pb.memory_bytes if pb.memory_bytes else None,
|
|
150
|
+
cpu_quota=pb.cpu_quota if pb.cpu_quota else None,
|
|
151
|
+
cpu_shares=pb.cpu_shares if pb.cpu_shares else None,
|
|
152
|
+
pids_limit=pb.pids_limit if pb.pids_limit else None,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# ============================================
|
|
157
|
+
# Time Conversions
|
|
158
|
+
# ============================================
|
|
159
|
+
|
|
160
|
+
def timestamp_to_datetime(ts) -> Optional[datetime]:
|
|
161
|
+
"""Convert protobuf Timestamp to datetime."""
|
|
162
|
+
if ts is None or ts.seconds == 0:
|
|
163
|
+
return None
|
|
164
|
+
return datetime.fromtimestamp(ts.seconds + ts.nanos / 1e9)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def duration_to_timedelta(d) -> Optional[timedelta]:
|
|
168
|
+
"""Convert protobuf Duration to timedelta."""
|
|
169
|
+
if d is None:
|
|
170
|
+
return None
|
|
171
|
+
return timedelta(seconds=d.seconds, microseconds=d.nanos / 1000)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# ============================================
|
|
175
|
+
# Complex Object Conversions
|
|
176
|
+
# ============================================
|
|
177
|
+
|
|
178
|
+
def proto_to_sandbox(pb: sandbox_pb2.Sandbox) -> Sandbox:
|
|
179
|
+
"""Convert protobuf Sandbox to Sandbox dataclass."""
|
|
180
|
+
permissions = [
|
|
181
|
+
PermissionRule(
|
|
182
|
+
pattern=p.pattern,
|
|
183
|
+
permission=proto_to_permission(p.permission),
|
|
184
|
+
type=proto_to_pattern_type(p.type),
|
|
185
|
+
priority=p.priority,
|
|
186
|
+
)
|
|
187
|
+
for p in pb.permissions
|
|
188
|
+
]
|
|
189
|
+
return Sandbox(
|
|
190
|
+
id=pb.id,
|
|
191
|
+
codebase_id=pb.codebase_id,
|
|
192
|
+
status=proto_to_status(pb.status),
|
|
193
|
+
permissions=permissions,
|
|
194
|
+
labels=dict(pb.labels),
|
|
195
|
+
runtime=proto_to_runtime_type(pb.runtime),
|
|
196
|
+
image=pb.image if pb.image else None,
|
|
197
|
+
resources=proto_to_resource_limits(pb.resources) if pb.HasField("resources") else None,
|
|
198
|
+
created_at=timestamp_to_datetime(pb.created_at),
|
|
199
|
+
started_at=timestamp_to_datetime(pb.started_at),
|
|
200
|
+
stopped_at=timestamp_to_datetime(pb.stopped_at),
|
|
201
|
+
expires_at=timestamp_to_datetime(pb.expires_at),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def proto_to_codebase(pb: codebase_pb2.Codebase) -> Codebase:
|
|
206
|
+
"""Convert protobuf Codebase to Codebase dataclass."""
|
|
207
|
+
return Codebase(
|
|
208
|
+
id=pb.id,
|
|
209
|
+
name=pb.name,
|
|
210
|
+
owner_id=pb.owner_id,
|
|
211
|
+
size=pb.size,
|
|
212
|
+
file_count=pb.file_count,
|
|
213
|
+
created_at=timestamp_to_datetime(pb.created_at),
|
|
214
|
+
updated_at=timestamp_to_datetime(pb.updated_at),
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def proto_to_file_info(pb: codebase_pb2.FileInfo) -> FileInfo:
|
|
219
|
+
"""Convert protobuf FileInfo to FileInfo dataclass."""
|
|
220
|
+
return FileInfo(
|
|
221
|
+
path=pb.path,
|
|
222
|
+
name=pb.name,
|
|
223
|
+
is_dir=pb.is_dir,
|
|
224
|
+
size=pb.size,
|
|
225
|
+
modified_at=timestamp_to_datetime(pb.modified_at),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def proto_to_session(pb: sandbox_pb2.Session) -> Session:
|
|
230
|
+
"""Convert protobuf Session to Session dataclass."""
|
|
231
|
+
return Session(
|
|
232
|
+
id=pb.id,
|
|
233
|
+
sandbox_id=pb.sandbox_id,
|
|
234
|
+
status=proto_to_session_status(pb.status),
|
|
235
|
+
shell=pb.shell,
|
|
236
|
+
created_at=timestamp_to_datetime(pb.created_at),
|
|
237
|
+
closed_at=timestamp_to_datetime(pb.closed_at),
|
|
238
|
+
)
|