hopx-ai 0.1.10__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.

Potentially problematic release.


This version of hopx-ai might be problematic. Click here for more details.

hopx_ai/models.py ADDED
@@ -0,0 +1,274 @@
1
+ """
2
+ Data models for Bunnyshell Sandboxes SDK.
3
+
4
+ This module combines hand-crafted models (SandboxInfo, Template) with
5
+ auto-generated models from OpenAPI spec for type safety and maintainability.
6
+
7
+ Auto-generated models are re-exported for convenience with backward-compatible names.
8
+ """
9
+
10
+ from datetime import datetime
11
+ from typing import Optional, List, Dict, Any
12
+ from pydantic import BaseModel, Field
13
+
14
+ # Import auto-generated models
15
+ from ._generated.models import (
16
+ # Execution models (auto-generated)
17
+ ExecuteResponse as _ExecuteResponse,
18
+ ExecuteRequest as _ExecuteRequest,
19
+ RichOutput as _RichOutput,
20
+ Language,
21
+
22
+ # File models (auto-generated)
23
+ FileInfo as _FileInfo,
24
+ FileListResponse,
25
+ FileContentResponse,
26
+ FileWriteRequest,
27
+ FileResponse,
28
+
29
+ # Command models (auto-generated)
30
+ CommandResponse as _CommandResponse,
31
+
32
+ # Desktop models (auto-generated)
33
+ VNCInfo as _VNCInfo,
34
+ WindowInfo as _WindowInfo,
35
+ RecordingInfo as _RecordingInfo,
36
+ DisplayInfo as _DisplayInfo,
37
+ ScreenshotResponse,
38
+
39
+ # Error models (auto-generated)
40
+ ErrorResponse,
41
+ Code as ErrorCode, # Generated as "Code", export as "ErrorCode"
42
+
43
+ # Metrics models (auto-generated)
44
+ MetricsSnapshot,
45
+ SystemMetrics,
46
+ HealthResponse,
47
+ InfoResponse as _InfoResponse,
48
+ )
49
+
50
+
51
+ # =============================================================================
52
+ # ENHANCED MODELS (Auto-generated + Convenience Methods for DX)
53
+ # =============================================================================
54
+
55
+ class RichOutput(_RichOutput):
56
+ """
57
+ Rich output from code execution (plots, DataFrames, etc.).
58
+
59
+ Auto-generated from OpenAPI spec with convenience methods added.
60
+ """
61
+
62
+ def __repr__(self) -> str:
63
+ return f"<RichOutput type={self.type}>"
64
+
65
+
66
+ class ExecutionResult(_ExecuteResponse):
67
+ """
68
+ Result of code execution.
69
+
70
+ Auto-generated from OpenAPI spec (ExecuteResponse) with convenience methods.
71
+ This is an alias for backward compatibility while adding DX improvements.
72
+ """
73
+
74
+ # Add rich_outputs field (from /execute/rich endpoint, not in base ExecuteResponse)
75
+ rich_outputs: Optional[List[RichOutput]] = Field(default=None, description="Rich outputs (plots, etc.)")
76
+
77
+ @property
78
+ def rich_count(self) -> int:
79
+ """Number of rich outputs."""
80
+ return len(self.rich_outputs) if self.rich_outputs else 0
81
+
82
+ def __repr__(self) -> str:
83
+ status = "✅" if self.success else "❌"
84
+ exec_time = self.execution_time if self.execution_time is not None else 0.0
85
+ return f"<ExecutionResult {status} time={exec_time:.3f}s rich={self.rich_count}>"
86
+
87
+
88
+ class CommandResult(_CommandResponse):
89
+ """
90
+ Result of command execution.
91
+
92
+ Auto-generated from OpenAPI spec (CommandResponse) with convenience methods.
93
+ """
94
+
95
+ @property
96
+ def success(self) -> bool:
97
+ """Whether command succeeded (exit code 0)."""
98
+ return self.exit_code == 0
99
+
100
+ def __repr__(self) -> str:
101
+ status = "✅" if self.success else "❌"
102
+ return f"<CommandResult {status} exit={self.exit_code} time={self.execution_time:.3f}s>"
103
+
104
+
105
+ class FileInfo(_FileInfo):
106
+ """
107
+ File or directory information.
108
+
109
+ Auto-generated from OpenAPI spec with convenience methods.
110
+ """
111
+
112
+ @property
113
+ def is_file(self) -> bool:
114
+ """Whether this is a file (not directory)."""
115
+ return not self.is_directory
116
+
117
+ @property
118
+ def is_dir(self) -> bool:
119
+ """Alias for is_directory (backward compat)."""
120
+ return self.is_directory
121
+
122
+ @property
123
+ def size_kb(self) -> float:
124
+ """Size in kilobytes."""
125
+ return self.size / 1024
126
+
127
+ @property
128
+ def size_mb(self) -> float:
129
+ """Size in megabytes."""
130
+ return self.size / (1024 * 1024)
131
+
132
+ def __repr__(self) -> str:
133
+ type_icon = "📁" if self.is_directory else "📄"
134
+ return f"<FileInfo {type_icon} {self.name} ({self.size} bytes)>"
135
+
136
+
137
+ class VNCInfo(_VNCInfo):
138
+ """VNC server information with convenience properties."""
139
+
140
+ @property
141
+ def running(self) -> bool:
142
+ """Whether VNC server is running (always True if we have this info)."""
143
+ return True
144
+
145
+
146
+ class WindowInfo(_WindowInfo):
147
+ """Window information with convenience properties."""
148
+ pass
149
+
150
+
151
+ class RecordingInfo(_RecordingInfo):
152
+ """Screen recording information with convenience properties."""
153
+
154
+ @property
155
+ def is_recording(self) -> bool:
156
+ """Whether recording is in progress."""
157
+ return self.status == "recording"
158
+
159
+ @property
160
+ def is_ready(self) -> bool:
161
+ """Whether recording is ready to download."""
162
+ return self.status == "stopped"
163
+
164
+
165
+ class DisplayInfo(_DisplayInfo):
166
+ """Display information with convenience properties."""
167
+
168
+ @property
169
+ def resolution(self) -> str:
170
+ """Resolution as string (e.g., '1920x1080')."""
171
+ return f"{self.width}x{self.height}"
172
+
173
+
174
+ # =============================================================================
175
+ # HAND-CRAFTED MODELS (Not in Agent API - for Sandbox Management)
176
+ # =============================================================================
177
+
178
+ class Resources(BaseModel):
179
+ """Resource specifications."""
180
+
181
+ vcpu: int = Field(..., description="Number of vCPUs")
182
+ memory_mb: int = Field(..., description="Memory in MB")
183
+ disk_mb: int = Field(..., description="Disk size in MB")
184
+
185
+
186
+ class SandboxInfo(BaseModel):
187
+ """Sandbox information."""
188
+
189
+ sandbox_id: str = Field(..., description="Sandbox ID")
190
+ template_id: Optional[str] = Field(None, description="Template ID")
191
+ template_name: Optional[str] = Field(None, description="Template name")
192
+ organization_id: int = Field(..., description="Organization ID")
193
+ node_id: Optional[str] = Field(None, description="Node ID where VM is running")
194
+ region: Optional[str] = Field(None, description="Region")
195
+ status: str = Field(..., description="Sandbox status (running, stopped, paused, creating)")
196
+ public_host: str = Field(..., description="Public URL to access sandbox")
197
+ resources: Optional[Resources] = Field(None, description="Resource allocation")
198
+ started_at: Optional[datetime] = Field(None, description="When sandbox started")
199
+ end_at: Optional[datetime] = Field(None, description="When sandbox will be terminated")
200
+ created_at: Optional[datetime] = Field(None, description="Creation timestamp")
201
+
202
+ def __repr__(self) -> str:
203
+ return f"<SandboxInfo {self.sandbox_id}: {self.status}>"
204
+
205
+ def __str__(self) -> str:
206
+ return f"SandboxInfo(sandbox_id={self.sandbox_id}, status={self.status}, url={self.public_host})"
207
+
208
+
209
+ class TemplateResources(BaseModel):
210
+ """Template resource specifications."""
211
+
212
+ vcpu: Optional[int] = None
213
+ memory_mb: Optional[int] = None
214
+ disk_gb: Optional[int] = None
215
+
216
+
217
+ class Template(BaseModel):
218
+ """VM template."""
219
+
220
+ id: str = Field(..., description="Template ID")
221
+ name: str = Field(..., description="Template name (slug)")
222
+ display_name: str = Field(..., description="Display name")
223
+ description: Optional[str] = Field(None, description="Description")
224
+ category: Optional[str] = Field(None, description="Category")
225
+ language: Optional[str] = Field(None, description="Primary language")
226
+ icon: Optional[str] = Field(None, description="Icon URL or emoji")
227
+ default_resources: Optional[TemplateResources] = None
228
+ min_resources: Optional[TemplateResources] = None
229
+ max_resources: Optional[TemplateResources] = None
230
+ features: List[str] = Field(default_factory=list)
231
+ tags: List[str] = Field(default_factory=list)
232
+ popularity_score: Optional[int] = None
233
+ docs_url: Optional[str] = None
234
+ is_active: bool = Field(default=True)
235
+
236
+ def __repr__(self) -> str:
237
+ return f"<Template {self.name}: {self.display_name}>"
238
+
239
+
240
+ # =============================================================================
241
+ # EXPORTS
242
+ # =============================================================================
243
+
244
+ __all__ = [
245
+ # Enhanced models (auto-generated + convenience)
246
+ "ExecutionResult",
247
+ "CommandResult",
248
+ "FileInfo",
249
+ "RichOutput",
250
+ "VNCInfo",
251
+ "WindowInfo",
252
+ "RecordingInfo",
253
+ "DisplayInfo",
254
+
255
+ # Hand-crafted models
256
+ "SandboxInfo",
257
+ "Template",
258
+ "Resources",
259
+ "TemplateResources",
260
+
261
+ # Auto-generated models (direct exports)
262
+ "Language",
263
+ "ErrorResponse",
264
+ "ErrorCode",
265
+ "MetricsSnapshot",
266
+ "SystemMetrics",
267
+ "HealthResponse",
268
+ "FileListResponse",
269
+ "FileContentResponse",
270
+ "FileWriteRequest",
271
+ "FileResponse",
272
+ "ScreenshotResponse",
273
+ ]
274
+
@@ -0,0 +1,270 @@
1
+ """
2
+ Data models for Bunnyshell Sandboxes SDK.
3
+
4
+ This module combines hand-crafted models (SandboxInfo, Template) with
5
+ auto-generated models from OpenAPI spec for type safety and maintainability.
6
+
7
+ Auto-generated models are re-exported for convenience with backward-compatible names.
8
+ """
9
+
10
+ from datetime import datetime
11
+ from typing import Optional, List, Dict, Any
12
+ from pydantic import BaseModel, Field
13
+
14
+ # Import auto-generated models
15
+ from ._generated.models import (
16
+ # Execution models (auto-generated)
17
+ ExecuteResponse as _ExecuteResponse,
18
+ ExecuteRequest as _ExecuteRequest,
19
+ RichOutput as _RichOutput,
20
+ Language,
21
+
22
+ # File models (auto-generated)
23
+ FileInfo as _FileInfo,
24
+ FileListResponse,
25
+ FileContentResponse,
26
+ FileWriteRequest,
27
+ FileResponse,
28
+
29
+ # Command models (auto-generated)
30
+ CommandResponse as _CommandResponse,
31
+
32
+ # Desktop models (auto-generated)
33
+ VNCInfo as _VNCInfo,
34
+ WindowInfo as _WindowInfo,
35
+ RecordingInfo as _RecordingInfo,
36
+ DisplayInfo as _DisplayInfo,
37
+ ScreenshotResponse,
38
+
39
+ # Error models (auto-generated)
40
+ ErrorResponse,
41
+ ErrorCode,
42
+
43
+ # Metrics models (auto-generated)
44
+ MetricsSnapshot,
45
+ SystemMetrics,
46
+ HealthResponse,
47
+ InfoResponse as _InfoResponse,
48
+ )
49
+
50
+
51
+ # =============================================================================
52
+ # ENHANCED MODELS (Auto-generated + Convenience Methods for DX)
53
+ # =============================================================================
54
+
55
+ class RichOutput(_RichOutput):
56
+ """
57
+ Rich output from code execution (plots, DataFrames, etc.).
58
+
59
+ Auto-generated from OpenAPI spec with convenience methods added.
60
+ """
61
+
62
+ def __repr__(self) -> str:
63
+ return f"<RichOutput type={self.type}>"
64
+
65
+
66
+ class ExecutionResult(_ExecuteResponse):
67
+ """
68
+ Result of code execution.
69
+
70
+ Auto-generated from OpenAPI spec (ExecuteResponse) with convenience methods.
71
+ This is an alias for backward compatibility while adding DX improvements.
72
+ """
73
+
74
+ @property
75
+ def rich_count(self) -> int:
76
+ """Number of rich outputs."""
77
+ return len(self.rich_outputs) if self.rich_outputs else 0
78
+
79
+ def __repr__(self) -> str:
80
+ status = "✅" if self.success else "❌"
81
+ return f"<ExecutionResult {status} time={self.execution_time:.3f}s rich={self.rich_count}>"
82
+
83
+
84
+ class CommandResult(_CommandResponse):
85
+ """
86
+ Result of command execution.
87
+
88
+ Auto-generated from OpenAPI spec (CommandResponse) with convenience methods.
89
+ """
90
+
91
+ @property
92
+ def success(self) -> bool:
93
+ """Whether command succeeded (exit code 0)."""
94
+ return self.exit_code == 0
95
+
96
+ def __repr__(self) -> str:
97
+ status = "✅" if self.success else "❌"
98
+ return f"<CommandResult {status} exit={self.exit_code} time={self.execution_time:.3f}s>"
99
+
100
+
101
+ class FileInfo(_FileInfo):
102
+ """
103
+ File or directory information.
104
+
105
+ Auto-generated from OpenAPI spec with convenience methods.
106
+ """
107
+
108
+ @property
109
+ def is_file(self) -> bool:
110
+ """Whether this is a file (not directory)."""
111
+ return not self.is_directory
112
+
113
+ @property
114
+ def is_dir(self) -> bool:
115
+ """Alias for is_directory (backward compat)."""
116
+ return self.is_directory
117
+
118
+ @property
119
+ def size_kb(self) -> float:
120
+ """Size in kilobytes."""
121
+ return self.size / 1024
122
+
123
+ @property
124
+ def size_mb(self) -> float:
125
+ """Size in megabytes."""
126
+ return self.size / (1024 * 1024)
127
+
128
+ def __repr__(self) -> str:
129
+ type_icon = "📁" if self.is_directory else "📄"
130
+ return f"<FileInfo {type_icon} {self.name} ({self.size} bytes)>"
131
+
132
+
133
+ class VNCInfo(_VNCInfo):
134
+ """VNC server information with convenience properties."""
135
+
136
+ @property
137
+ def running(self) -> bool:
138
+ """Whether VNC server is running (always True if we have this info)."""
139
+ return True
140
+
141
+
142
+ class WindowInfo(_WindowInfo):
143
+ """Window information with convenience properties."""
144
+ pass
145
+
146
+
147
+ class RecordingInfo(_RecordingInfo):
148
+ """Screen recording information with convenience properties."""
149
+
150
+ @property
151
+ def is_recording(self) -> bool:
152
+ """Whether recording is in progress."""
153
+ return self.status == "recording"
154
+
155
+ @property
156
+ def is_ready(self) -> bool:
157
+ """Whether recording is ready to download."""
158
+ return self.status == "stopped"
159
+
160
+
161
+ class DisplayInfo(_DisplayInfo):
162
+ """Display information with convenience properties."""
163
+
164
+ @property
165
+ def resolution(self) -> str:
166
+ """Resolution as string (e.g., '1920x1080')."""
167
+ return f"{self.width}x{self.height}"
168
+
169
+
170
+ # =============================================================================
171
+ # HAND-CRAFTED MODELS (Not in Agent API - for Sandbox Management)
172
+ # =============================================================================
173
+
174
+ class Resources(BaseModel):
175
+ """Resource specifications."""
176
+
177
+ vcpu: int = Field(..., description="Number of vCPUs")
178
+ memory_mb: int = Field(..., description="Memory in MB")
179
+ disk_mb: int = Field(..., description="Disk size in MB")
180
+
181
+
182
+ class SandboxInfo(BaseModel):
183
+ """Sandbox information."""
184
+
185
+ sandbox_id: str = Field(..., description="Sandbox ID")
186
+ template_id: Optional[str] = Field(None, description="Template ID")
187
+ template_name: Optional[str] = Field(None, description="Template name")
188
+ organization_id: int = Field(..., description="Organization ID")
189
+ node_id: Optional[str] = Field(None, description="Node ID where VM is running")
190
+ region: Optional[str] = Field(None, description="Region")
191
+ status: str = Field(..., description="Sandbox status (running, stopped, paused, creating)")
192
+ public_host: str = Field(..., description="Public URL to access sandbox")
193
+ resources: Optional[Resources] = Field(None, description="Resource allocation")
194
+ started_at: Optional[datetime] = Field(None, description="When sandbox started")
195
+ end_at: Optional[datetime] = Field(None, description="When sandbox will be terminated")
196
+ created_at: Optional[datetime] = Field(None, description="Creation timestamp")
197
+
198
+ def __repr__(self) -> str:
199
+ return f"<SandboxInfo {self.sandbox_id}: {self.status}>"
200
+
201
+ def __str__(self) -> str:
202
+ return f"SandboxInfo(sandbox_id={self.sandbox_id}, status={self.status}, url={self.public_host})"
203
+
204
+
205
+ class TemplateResources(BaseModel):
206
+ """Template resource specifications."""
207
+
208
+ vcpu: Optional[int] = None
209
+ memory_mb: Optional[int] = None
210
+ disk_gb: Optional[int] = None
211
+
212
+
213
+ class Template(BaseModel):
214
+ """VM template."""
215
+
216
+ id: str = Field(..., description="Template ID")
217
+ name: str = Field(..., description="Template name (slug)")
218
+ display_name: str = Field(..., description="Display name")
219
+ description: Optional[str] = Field(None, description="Description")
220
+ category: Optional[str] = Field(None, description="Category")
221
+ language: Optional[str] = Field(None, description="Primary language")
222
+ icon: Optional[str] = Field(None, description="Icon URL or emoji")
223
+ default_resources: Optional[TemplateResources] = None
224
+ min_resources: Optional[TemplateResources] = None
225
+ max_resources: Optional[TemplateResources] = None
226
+ features: List[str] = Field(default_factory=list)
227
+ tags: List[str] = Field(default_factory=list)
228
+ popularity_score: Optional[int] = None
229
+ docs_url: Optional[str] = None
230
+ is_active: bool = Field(default=True)
231
+
232
+ def __repr__(self) -> str:
233
+ return f"<Template {self.name}: {self.display_name}>"
234
+
235
+
236
+ # =============================================================================
237
+ # EXPORTS
238
+ # =============================================================================
239
+
240
+ __all__ = [
241
+ # Enhanced models (auto-generated + convenience)
242
+ "ExecutionResult",
243
+ "CommandResult",
244
+ "FileInfo",
245
+ "RichOutput",
246
+ "VNCInfo",
247
+ "WindowInfo",
248
+ "RecordingInfo",
249
+ "DisplayInfo",
250
+
251
+ # Hand-crafted models
252
+ "SandboxInfo",
253
+ "Template",
254
+ "Resources",
255
+ "TemplateResources",
256
+
257
+ # Auto-generated models (direct exports)
258
+ "Language",
259
+ "ErrorResponse",
260
+ "ErrorCode",
261
+ "MetricsSnapshot",
262
+ "SystemMetrics",
263
+ "HealthResponse",
264
+ "FileListResponse",
265
+ "FileContentResponse",
266
+ "FileWriteRequest",
267
+ "FileResponse",
268
+ "ScreenshotResponse",
269
+ ]
270
+