fleet-python 0.2.20__py3-none-any.whl → 0.2.22__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 fleet-python might be problematic. Click here for more details.

examples/dsl_example.py CHANGED
@@ -68,7 +68,7 @@ def validate_new_deal_creation(
68
68
  async def main():
69
69
  # Create a new instance
70
70
  print("Creating new Hubspot instance...")
71
- env = await flt.env.make_async("hubspot:v1.2.7")
71
+ env = await flt.env.make_async("hubspot")
72
72
  print(f"New Instance: {env.instance_id}")
73
73
 
74
74
  try:
@@ -85,6 +85,7 @@ async def main():
85
85
  print(f"Message: {response.message}")
86
86
 
87
87
  # Get the database resource
88
+ await env.instance.load()
88
89
  db = env.db()
89
90
 
90
91
  # Take a snapshot before insertion
fleet/__init__.py CHANGED
@@ -24,7 +24,7 @@ from .exceptions import (
24
24
  )
25
25
  from .client import Fleet, Environment
26
26
  from ._async.client import AsyncFleet, AsyncEnv
27
- from .models import InstanceRecord
27
+ from .models import InstanceResponse
28
28
  from .instance.models import Resource, ResetResponse
29
29
 
30
30
  # Import sync verifiers with explicit naming
@@ -34,6 +34,7 @@ from .verifiers import (
34
34
  DatabaseSnapshot,
35
35
  IgnoreConfig,
36
36
  SnapshotDiff,
37
+ TASK_FAILED_SCORE,
37
38
  TASK_SUCCESSFUL_SCORE,
38
39
  )
39
40
 
@@ -80,6 +81,7 @@ __all__ = [
80
81
  "DatabaseSnapshot",
81
82
  "IgnoreConfig",
82
83
  "SnapshotDiff",
84
+ "TASK_FAILED_SCORE",
83
85
  "TASK_SUCCESSFUL_SCORE",
84
86
  # Environment module
85
87
  "env",
fleet/_async/client.py CHANGED
@@ -24,12 +24,13 @@ from typing import List, Optional, Dict
24
24
  from .base import EnvironmentBase, AsyncWrapper
25
25
  from ..models import (
26
26
  InstanceRequest,
27
- InstanceRecord,
27
+ InstanceResponse,
28
28
  Environment as EnvironmentModel,
29
29
  VerifiersCheckResponse,
30
- VerificationResponse,
31
30
  VerifiersExecuteResponse,
31
+ TaskListResponse,
32
32
  )
33
+ from .tasks import Task
33
34
 
34
35
  from .instance import (
35
36
  AsyncInstanceClient,
@@ -102,14 +103,14 @@ class AsyncEnv(EnvironmentBase):
102
103
  async def resources(self) -> List[Resource]:
103
104
  return await self.instance.resources()
104
105
 
105
- async def close(self) -> InstanceRecord:
106
+ async def close(self) -> InstanceResponse:
106
107
  return await _delete_instance(self._load_client, self.instance_id)
107
108
 
108
109
  async def verify(self, validator: ValidatorType) -> ExecuteFunctionResponse:
109
110
  return await self.instance.verify(validator)
110
111
 
111
112
  async def verify_raw(
112
- self, function_code: str, function_name: str
113
+ self, function_code: str, function_name: str | None = None
113
114
  ) -> ExecuteFunctionResponse:
114
115
  return await self.instance.verify_raw(function_code, function_name)
115
116
 
@@ -152,12 +153,14 @@ class AsyncEnv(EnvironmentBase):
152
153
  class AsyncFleet:
153
154
  def __init__(
154
155
  self,
155
- api_key: Optional[str] = os.getenv("FLEET_API_KEY"),
156
+ api_key: Optional[str] = None,
156
157
  base_url: Optional[str] = None,
157
158
  httpx_client: Optional[httpx.AsyncClient] = None,
158
159
  max_retries: int = DEFAULT_MAX_RETRIES,
159
160
  timeout: float = DEFAULT_TIMEOUT,
160
161
  ):
162
+ if api_key is None:
163
+ api_key = os.getenv("FLEET_API_KEY")
161
164
  self._httpx_client = httpx_client or default_httpx_client(max_retries, timeout)
162
165
  self.client = AsyncWrapper(
163
166
  api_key=api_key,
@@ -182,13 +185,13 @@ class AsyncFleet:
182
185
  ) -> AsyncEnv:
183
186
  if ":" in env_key:
184
187
  env_key_part, version = env_key.split(":", 1)
185
- if not version.startswith("v"):
188
+ if not version.startswith("v") and len(version) != 0 and version[0].isdigit():
186
189
  version = f"v{version}"
187
190
  else:
188
191
  env_key_part = env_key
189
192
  version = None
190
193
 
191
- request = InstanceRequest(env_key=env_key_part, version=version, region=region)
194
+ request = InstanceRequest(env_key=env_key_part, version=version, region=region, created_from="sdk")
192
195
  region_base_url = REGION_BASE_URL.get(region)
193
196
  response = await self.client.request(
194
197
  "POST",
@@ -231,14 +234,45 @@ class AsyncFleet:
231
234
  self.client, bundle_data, args, kwargs, timeout
232
235
  )
233
236
 
234
- async def delete(self, instance_id: str) -> InstanceRecord:
237
+ async def delete(self, instance_id: str) -> InstanceResponse:
235
238
  return await _delete_instance(self.client, instance_id)
236
239
 
240
+ async def load_tasks(self, env_key: Optional[str] = None) -> List[Task]:
241
+ """Load tasks for the authenticated team, optionally filtered by environment.
242
+
243
+ Args:
244
+ env_key: Optional environment key to filter tasks by
245
+
246
+ Returns:
247
+ List[Task] containing Task objects
248
+ """
249
+ params = {}
250
+ if env_key is not None:
251
+ params["env_key"] = env_key
252
+
253
+ response = await self.client.request("GET", "/v1/tasks", params=params)
254
+ task_list_response = TaskListResponse(**response.json())
255
+
256
+ # Transform TaskResponse objects to Task objects
257
+ tasks = []
258
+ for task_response in task_list_response.tasks:
259
+ task = Task(
260
+ key=task_response.key,
261
+ prompt=task_response.prompt,
262
+ env_id=task_response.environment_id, # Map environment_id -> env_id
263
+ created_at=task_response.created_at,
264
+ verifier=None, # Keep blank for now as requested
265
+ metadata={} # Default empty metadata
266
+ )
267
+ tasks.append(task)
268
+
269
+ return tasks
270
+
237
271
 
238
272
  # Shared
239
- async def _delete_instance(client: AsyncWrapper, instance_id: str) -> InstanceRecord:
273
+ async def _delete_instance(client: AsyncWrapper, instance_id: str) -> InstanceResponse:
240
274
  response = await client.request("DELETE", f"/v1/env/instances/{instance_id}")
241
- return InstanceRecord(**response.json())
275
+ return InstanceResponse(**response.json())
242
276
 
243
277
 
244
278
  async def _check_bundle_exists(
@@ -258,7 +292,7 @@ async def _execute_verifier_remote(
258
292
  kwargs: dict,
259
293
  timeout: Optional[int] = 30,
260
294
  needs_upload: bool = True,
261
- ) -> VerificationResponse:
295
+ ) -> VerifiersExecuteResponse:
262
296
  # Pickle args and kwargs together
263
297
  # The first arg should be None as a placeholder for env
264
298
  args_with_none = (None,) + args
@@ -12,6 +12,7 @@ from ..resources.browser import AsyncBrowserResource
12
12
  from ..resources.base import Resource
13
13
 
14
14
  from fleet.verifiers import DatabaseSnapshot
15
+ from fleet.verifiers.parse import convert_verifier_string, extract_function_name
15
16
 
16
17
  from ..exceptions import FleetEnvironmentError
17
18
  from ...config import DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT
@@ -107,8 +108,16 @@ class AsyncInstanceClient:
107
108
  return await self.verify_raw(function_code, function_name)
108
109
 
109
110
  async def verify_raw(
110
- self, function_code: str, function_name: str
111
+ self, function_code: str, function_name: str | None = None
111
112
  ) -> ExecuteFunctionResponse:
113
+ try:
114
+ function_code = convert_verifier_string(function_code)
115
+ except:
116
+ pass
117
+
118
+ if function_name is None:
119
+ function_name = extract_function_name(function_code)
120
+
112
121
  response = await self.client.request(
113
122
  "POST",
114
123
  "/execute_verifier_function",
fleet/_async/models.py ADDED
@@ -0,0 +1,321 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: https://orchestrator.fleetai.com/openapi.json
3
+ # timestamp: 2025-08-03T22:47:20+00:00
4
+
5
+ from __future__ import annotations
6
+
7
+ from enum import Enum
8
+ from typing import Any, Dict, List, Optional, Union
9
+
10
+ from pydantic import BaseModel, Field, conint
11
+
12
+
13
+ class CDPDescribeResponse(BaseModel):
14
+ success: bool = Field(..., title='Success')
15
+ url: str = Field(..., title='Url')
16
+ devtools_url: str = Field(..., title='Devtools Url')
17
+
18
+
19
+ class ChromeStartRequest(BaseModel):
20
+ start_page: Optional[str] = Field('about:blank', title='Start Page')
21
+ resolution: Optional[str] = Field('1920x1080', title='Resolution')
22
+
23
+
24
+ class ChromeStartResponse(BaseModel):
25
+ success: bool = Field(..., title='Success')
26
+ message: str = Field(..., title='Message')
27
+
28
+
29
+ class ChromeStatusResponse(BaseModel):
30
+ running: bool = Field(..., title='Running')
31
+ message: str = Field(..., title='Message')
32
+
33
+
34
+ class Environment(BaseModel):
35
+ env_key: str = Field(..., title='Env Key')
36
+ name: str = Field(..., title='Name')
37
+ description: Optional[str] = Field(..., title='Description')
38
+ default_version: Optional[str] = Field(..., title='Default Version')
39
+ versions: Dict[str, str] = Field(..., title='Versions')
40
+
41
+
42
+ class Instance(BaseModel):
43
+ instance_id: str = Field(..., title='Instance Id')
44
+ env_key: str = Field(..., title='Env Key')
45
+ version: str = Field(..., title='Version')
46
+ status: str = Field(..., title='Status')
47
+ subdomain: str = Field(..., title='Subdomain')
48
+ created_at: str = Field(..., title='Created At')
49
+ updated_at: str = Field(..., title='Updated At')
50
+ terminated_at: Optional[str] = Field(None, title='Terminated At')
51
+ team_id: str = Field(..., title='Team Id')
52
+ region: str = Field(..., title='Region')
53
+ env_variables: Optional[Dict[str, Any]] = Field(None, title='Env Variables')
54
+
55
+
56
+ class InstanceRequest(BaseModel):
57
+ env_key: str = Field(..., title='Env Key')
58
+ version: Optional[str] = Field(None, title='Version')
59
+ region: Optional[str] = Field('us-west-1', title='Region')
60
+ seed: Optional[int] = Field(None, title='Seed')
61
+ timestamp: Optional[int] = Field(None, title='Timestamp')
62
+ p_error: Optional[float] = Field(None, title='P Error')
63
+ avg_latency: Optional[float] = Field(None, title='Avg Latency')
64
+ run_id: Optional[str] = Field(None, title='Run Id')
65
+ task_id: Optional[str] = Field(None, title='Task Id')
66
+ force_pull: Optional[bool] = Field(None, title='Force Pull')
67
+ env_variables: Optional[Dict[str, Any]] = Field(None, title='Env Variables')
68
+ created_from: Optional[str] = Field(None, title='Created From')
69
+
70
+
71
+ class InstanceStatus(Enum):
72
+ pending = 'pending'
73
+ running = 'running'
74
+ stopped = 'stopped'
75
+ error = 'error'
76
+
77
+
78
+ class ManagerURLs(BaseModel):
79
+ api: str = Field(..., title='Api')
80
+ docs: str = Field(..., title='Docs')
81
+ reset: str = Field(..., title='Reset')
82
+ diff: str = Field(..., title='Diff')
83
+ snapshot: str = Field(..., title='Snapshot')
84
+ execute_verifier_function: str = Field(..., title='Execute Verifier Function')
85
+ execute_verifier_function_with_upload: str = Field(
86
+ ..., title='Execute Verifier Function With Upload'
87
+ )
88
+
89
+
90
+ class QueryRequest(BaseModel):
91
+ query: str = Field(..., title='Query')
92
+ args: Optional[List] = Field(None, title='Args')
93
+ read_only: Optional[bool] = Field(True, title='Read Only')
94
+
95
+
96
+ class QueryResponse(BaseModel):
97
+ success: bool = Field(..., title='Success')
98
+ columns: Optional[List[str]] = Field(None, title='Columns')
99
+ rows: Optional[List[List]] = Field(None, title='Rows')
100
+ rows_affected: Optional[int] = Field(None, title='Rows Affected')
101
+ last_insert_id: Optional[int] = Field(None, title='Last Insert Id')
102
+ error: Optional[str] = Field(None, title='Error')
103
+ message: str = Field(..., title='Message')
104
+
105
+
106
+ class RecreateResponse(BaseModel):
107
+ success: bool = Field(..., title='Success')
108
+ instance_id: str = Field(..., title='Instance Id')
109
+ env_key: str = Field(..., title='Env Key')
110
+ version: str = Field(..., title='Version')
111
+ recreated_at: str = Field(..., title='Recreated At')
112
+
113
+
114
+ class ResourceMode(Enum):
115
+ ro = 'ro'
116
+ rw = 'rw'
117
+
118
+
119
+ class ResourceType(Enum):
120
+ sqlite = 'sqlite'
121
+ cdp = 'cdp'
122
+
123
+
124
+ class RestoreRequest(BaseModel):
125
+ backup_id: Optional[str] = Field(None, title='Backup Id')
126
+
127
+
128
+ class RestoreResponse(BaseModel):
129
+ success: bool = Field(..., title='Success')
130
+ backup_id: str = Field(..., title='Backup Id')
131
+ source_instance_id: str = Field(..., title='Source Instance Id')
132
+ target_instance_id: str = Field(..., title='Target Instance Id')
133
+ restored_at: str = Field(..., title='Restored At')
134
+
135
+
136
+ class SnapshotResponse(BaseModel):
137
+ success: bool = Field(..., title='Success')
138
+ backup_id: str = Field(..., title='Backup Id')
139
+ instance_id: str = Field(..., title='Instance Id')
140
+ s3_key: str = Field(..., title='S3 Key')
141
+ created_at: str = Field(..., title='Created At')
142
+
143
+
144
+ class TableSchema(BaseModel):
145
+ name: str = Field(..., title='Name')
146
+ sql: str = Field(..., title='Sql')
147
+ columns: List[Dict[str, Any]] = Field(..., title='Columns')
148
+
149
+
150
+ class TaskRequest(BaseModel):
151
+ key: str = Field(..., title='Key')
152
+ prompt: str = Field(..., title='Prompt')
153
+ environment_id: str = Field(..., title='Environment Id')
154
+ verifier_id: Optional[str] = Field(None, title='Verifier Id')
155
+
156
+
157
+ class TaskResponse(BaseModel):
158
+ key: str = Field(..., title='Key')
159
+ prompt: str = Field(..., title='Prompt')
160
+ team_id: str = Field(..., title='Team Id')
161
+ environment_id: str = Field(..., title='Environment Id')
162
+ created_at: str = Field(..., title='Created At')
163
+ verifier_id: Optional[str] = Field(None, title='Verifier Id')
164
+
165
+
166
+ class ValidationError(BaseModel):
167
+ loc: List[Union[str, int]] = Field(..., title='Location')
168
+ msg: str = Field(..., title='Message')
169
+ type: str = Field(..., title='Error Type')
170
+
171
+
172
+ class VerifiersCheckResponse(BaseModel):
173
+ key: Optional[str] = Field(
174
+ None, description='Key of the verifier artifact', title='Key'
175
+ )
176
+ version: Optional[int] = Field(
177
+ None, description='Version of the verifier artifact', title='Version'
178
+ )
179
+ display_src: Optional[str] = Field(
180
+ None, description='Display source code of the verifier', title='Display Src'
181
+ )
182
+ created_at: Optional[str] = Field(
183
+ None, description='Creation timestamp', title='Created At'
184
+ )
185
+ comment: Optional[str] = Field(
186
+ None, description='Comment about the verifier', title='Comment'
187
+ )
188
+ success: bool = Field(
189
+ ..., description='Whether the verification was successful', title='Success'
190
+ )
191
+
192
+
193
+ class VerifiersExecuteRequest(BaseModel):
194
+ key: Optional[str] = Field(
195
+ None, description='Key of the verifier artifact', title='Key'
196
+ )
197
+ sha256: Optional[str] = Field(
198
+ None,
199
+ description='SHA256 hash of the function (auto-generated if bundle is provided)',
200
+ title='Sha256',
201
+ )
202
+ bundle: Optional[str] = Field(
203
+ None, description='Base64 encoded bundle data', title='Bundle'
204
+ )
205
+ args: Optional[str] = Field(
206
+ None, description='Base64 encoded cloudpickled args', title='Args'
207
+ )
208
+ args_array: Optional[List] = Field(
209
+ None,
210
+ description='Array of argument values to pass to the function',
211
+ title='Args Array',
212
+ )
213
+ function_name: Optional[str] = Field(
214
+ 'verify', description='Name of the function to execute', title='Function Name'
215
+ )
216
+ timeout: Optional[conint(ge=1, le=300)] = Field(
217
+ 60, description='Execution timeout in seconds', title='Timeout'
218
+ )
219
+ region: Optional[str] = Field(
220
+ None, description='AWS region for execution', title='Region'
221
+ )
222
+ metadata: Optional[Dict[str, Any]] = Field(
223
+ None, description='Additional metadata', title='Metadata'
224
+ )
225
+ comment: Optional[str] = Field(
226
+ None, description='Comment about the function', title='Comment'
227
+ )
228
+ display_src: Optional[str] = Field(
229
+ None, description='Display source code', title='Display Src'
230
+ )
231
+
232
+
233
+ class VerifiersExecuteResponse(BaseModel):
234
+ key: Optional[str] = Field(
235
+ None, description='Key of the verifier artifact', title='Key'
236
+ )
237
+ version: Optional[int] = Field(
238
+ None, description='Version of the verifier artifact', title='Version'
239
+ )
240
+ display_src: Optional[str] = Field(
241
+ None, description='Display source code of the verifier', title='Display Src'
242
+ )
243
+ created_at: Optional[str] = Field(
244
+ None, description='Creation timestamp', title='Created At'
245
+ )
246
+ comment: Optional[str] = Field(
247
+ None, description='Comment about the verifier', title='Comment'
248
+ )
249
+ success: bool = Field(
250
+ ..., description='Whether the verification was successful', title='Success'
251
+ )
252
+ result: Optional[Any] = Field(
253
+ None, description='The return value of the function', title='Result'
254
+ )
255
+ error: Optional[Dict[str, Any]] = Field(
256
+ None, description='Error details if verification failed', title='Error'
257
+ )
258
+ execution_time_ms: int = Field(
259
+ ..., description='Execution time in milliseconds', title='Execution Time Ms'
260
+ )
261
+ bundle_cache_hit: Optional[bool] = Field(
262
+ False,
263
+ description='Whether the bundle was already cached',
264
+ title='Bundle Cache Hit',
265
+ )
266
+ stdout: Optional[str] = Field(
267
+ None, description='Captured stdout from execution', title='Stdout'
268
+ )
269
+
270
+
271
+ class DescribeResponse(BaseModel):
272
+ success: bool = Field(..., title='Success')
273
+ resource_name: str = Field(..., title='Resource Name')
274
+ tables: Optional[List[TableSchema]] = Field(None, title='Tables')
275
+ error: Optional[str] = Field(None, title='Error')
276
+ message: str = Field(..., title='Message')
277
+
278
+
279
+ class HTTPValidationError(BaseModel):
280
+ detail: Optional[List[ValidationError]] = Field(None, title='Detail')
281
+
282
+
283
+ class InstanceURLs(BaseModel):
284
+ root: str = Field(..., title='Root')
285
+ app: List[str] = Field(..., title='App')
286
+ api: Optional[str] = Field(None, title='Api')
287
+ health: Optional[str] = Field(None, title='Health')
288
+ api_docs: Optional[str] = Field(None, title='Api Docs')
289
+ manager: ManagerURLs
290
+
291
+
292
+ class Resource(BaseModel):
293
+ name: str = Field(..., title='Name')
294
+ type: ResourceType
295
+ mode: ResourceMode
296
+ label: Optional[str] = Field(None, title='Label')
297
+
298
+
299
+ class ResourcesResponse(BaseModel):
300
+ resources: List[Resource] = Field(..., title='Resources')
301
+
302
+
303
+ class TaskListResponse(BaseModel):
304
+ tasks: List[TaskResponse] = Field(..., title='Tasks')
305
+ total: int = Field(..., title='Total')
306
+
307
+
308
+ class InstanceResponse(BaseModel):
309
+ instance_id: str = Field(..., title='Instance Id')
310
+ env_key: str = Field(..., title='Env Key')
311
+ version: str = Field(..., title='Version')
312
+ status: str = Field(..., title='Status')
313
+ subdomain: str = Field(..., title='Subdomain')
314
+ created_at: str = Field(..., title='Created At')
315
+ updated_at: str = Field(..., title='Updated At')
316
+ terminated_at: Optional[str] = Field(None, title='Terminated At')
317
+ team_id: str = Field(..., title='Team Id')
318
+ region: str = Field(..., title='Region')
319
+ env_variables: Optional[Dict[str, Any]] = Field(None, title='Env Variables')
320
+ urls: InstanceURLs
321
+ health: Optional[bool] = Field(None, title='Health')
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
14
14
 
15
15
 
16
16
  # Import types from verifiers module
17
- from ...verifiers.db import IgnoreConfig, _get_row_identifier, _format_row_for_error, _values_equivalent
17
+ from fleet.verifiers.db import IgnoreConfig, _get_row_identifier, _format_row_for_error, _values_equivalent
18
18
 
19
19
 
20
20
  class AsyncDatabaseSnapshot:
@@ -12,8 +12,7 @@ import uuid
12
12
  import logging
13
13
  import hashlib
14
14
  import asyncio
15
- import inspect
16
- from typing import Any, Callable, Dict, Optional, List, TypeVar, Set, Union
15
+ from typing import Any, Callable, Dict, Optional, List, TypeVar, Set
17
16
 
18
17
  from .bundler import FunctionBundler
19
18
  from ..client import AsyncEnv
@@ -44,7 +43,6 @@ class AsyncVerifierFunction:
44
43
  ):
45
44
  self.func = func
46
45
  self.key = key
47
- self.name = key # Keep name for backward compatibility
48
46
  self.verifier_id = verifier_id or str(uuid.uuid4())
49
47
  self.extra_requirements = extra_requirements or []
50
48
  self._bundler = FunctionBundler()
@@ -65,7 +63,7 @@ class AsyncVerifierFunction:
65
63
  self.verifier_id
66
64
  )
67
65
  self._bundle_sha = _get_bundle_sha(self._bundle_data)
68
- logger.debug(f"Created bundle for {self.name} with SHA: {self._bundle_sha}")
66
+ logger.debug(f"Created bundle for {self.key} with SHA: {self._bundle_sha}")
69
67
 
70
68
  return self._bundle_data, self._bundle_sha
71
69
 
@@ -118,7 +116,7 @@ class AsyncVerifierFunction:
118
116
  raise ValueError(f"Verifier function must return a score (number). Got {type(result)}")
119
117
 
120
118
  except Exception as e:
121
- logger.error(f"Error in verifier {self.name}: {e}")
119
+ logger.error(f"Error in verifier {self.key}: {e}")
122
120
  # Return error score 0
123
121
  return 0.0
124
122
 
@@ -126,7 +124,7 @@ class AsyncVerifierFunction:
126
124
  """Remote execution of the verifier function with SHA-based bundle caching."""
127
125
  if self._is_async:
128
126
  raise NotImplementedError(
129
- f"Async verifier '{self.name}' cannot be executed remotely. "
127
+ f"Async verifier '{self.key}' cannot be executed remotely. "
130
128
  "The remote execution environment only supports synchronous functions. "
131
129
  "Please provide a synchronous version of your verifier."
132
130
  )