fleet-python 0.2.42__tar.gz → 0.2.44__tar.gz

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.

Files changed (81) hide show
  1. {fleet_python-0.2.42 → fleet_python-0.2.44}/PKG-INFO +1 -1
  2. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/__init__.py +9 -7
  3. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/__init__.py +28 -16
  4. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/client.py +161 -69
  5. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/env/client.py +9 -2
  6. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/instance/client.py +1 -1
  7. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/resources/sqlite.py +34 -34
  8. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/tasks.py +42 -41
  9. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/verifiers/verifier.py +3 -3
  10. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/client.py +164 -61
  11. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/env/client.py +9 -2
  12. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/instance/client.py +2 -4
  13. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/models.py +3 -1
  14. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/resources/sqlite.py +37 -43
  15. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/tasks.py +49 -65
  16. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/__init__.py +1 -1
  17. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/db.py +41 -36
  18. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/parse.py +4 -1
  19. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/sql_differ.py +8 -8
  20. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/verifier.py +19 -7
  21. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet_python.egg-info/PKG-INFO +1 -1
  22. {fleet_python-0.2.42 → fleet_python-0.2.44}/pyproject.toml +1 -1
  23. {fleet_python-0.2.42 → fleet_python-0.2.44}/LICENSE +0 -0
  24. {fleet_python-0.2.42 → fleet_python-0.2.44}/README.md +0 -0
  25. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/diff_example.py +0 -0
  26. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/dsl_example.py +0 -0
  27. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example.py +0 -0
  28. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/exampleResume.py +0 -0
  29. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_account.py +0 -0
  30. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_action_log.py +0 -0
  31. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_client.py +0 -0
  32. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_mcp_anthropic.py +0 -0
  33. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_mcp_openai.py +0 -0
  34. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_sync.py +0 -0
  35. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_task.py +0 -0
  36. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_tasks.py +0 -0
  37. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/example_verifier.py +0 -0
  38. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/gemini_example.py +0 -0
  39. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/json_tasks_example.py +0 -0
  40. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/nova_act_example.py +0 -0
  41. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/openai_example.py +0 -0
  42. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/openai_simple_example.py +0 -0
  43. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/query_builder_example.py +0 -0
  44. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/quickstart.py +0 -0
  45. {fleet_python-0.2.42 → fleet_python-0.2.44}/examples/test_cdp_logging.py +0 -0
  46. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/base.py +0 -0
  47. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/env/__init__.py +0 -0
  48. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/exceptions.py +0 -0
  49. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/global_client.py +0 -0
  50. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/instance/__init__.py +0 -0
  51. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/instance/base.py +0 -0
  52. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/models.py +0 -0
  53. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/resources/__init__.py +0 -0
  54. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/resources/base.py +0 -0
  55. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/resources/browser.py +0 -0
  56. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/resources/mcp.py +0 -0
  57. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/verifiers/__init__.py +0 -0
  58. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/_async/verifiers/bundler.py +0 -0
  59. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/base.py +0 -0
  60. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/config.py +0 -0
  61. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/env/__init__.py +0 -0
  62. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/exceptions.py +0 -0
  63. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/global_client.py +0 -0
  64. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/instance/__init__.py +0 -0
  65. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/instance/base.py +0 -0
  66. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/instance/models.py +0 -0
  67. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/resources/__init__.py +0 -0
  68. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/resources/base.py +0 -0
  69. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/resources/browser.py +0 -0
  70. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/resources/mcp.py +0 -0
  71. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/types.py +0 -0
  72. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/bundler.py +0 -0
  73. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/code.py +0 -0
  74. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet/verifiers/decorator.py +0 -0
  75. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet_python.egg-info/SOURCES.txt +0 -0
  76. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet_python.egg-info/dependency_links.txt +0 -0
  77. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet_python.egg-info/requires.txt +0 -0
  78. {fleet_python-0.2.42 → fleet_python-0.2.44}/fleet_python.egg-info/top_level.txt +0 -0
  79. {fleet_python-0.2.42 → fleet_python-0.2.44}/scripts/fix_sync_imports.py +0 -0
  80. {fleet_python-0.2.42 → fleet_python-0.2.44}/scripts/unasync.py +0 -0
  81. {fleet_python-0.2.42 → fleet_python-0.2.44}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.42
3
+ Version: 0.2.44
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -46,11 +46,15 @@ from ._async.verifiers import (
46
46
  AsyncVerifierFunction,
47
47
  )
48
48
 
49
- # Import async tasks (default tasks are async for modern usage)
50
- from ._async.tasks import Task, load_tasks as load_tasks_async
49
+ # Import async tasks (default tasks are async for modern usage)
50
+ from ._async.tasks import (
51
+ Task,
52
+ load_tasks as load_tasks_async,
53
+ load_tasks_from_file as load_tasks_from_file_async,
54
+ )
51
55
 
52
56
  # Import sync load_tasks function
53
- from .tasks import load_tasks
57
+ from .tasks import load_tasks, load_tasks_from_file
54
58
 
55
59
  # Import shared types
56
60
  from .types import VerifierFunction
@@ -105,13 +109,11 @@ __all__ = [
105
109
  ]
106
110
 
107
111
 
108
-
109
-
110
112
  def configure(
111
113
  api_key: Optional[str] = None,
112
114
  base_url: Optional[str] = None,
113
- max_retries: int | None = None,
114
- timeout: float | None = None,
115
+ max_retries: Optional[int] = None,
116
+ timeout: Optional[float] = None,
115
117
  ):
116
118
  """Configure global clients (sync and async) once per process.
117
119
 
@@ -73,17 +73,17 @@ __all__ = [
73
73
  "reset_client",
74
74
  # Module-level functions
75
75
  "load_tasks",
76
- "list_envs",
76
+ "list_envs",
77
77
  "list_regions",
78
78
  "environment",
79
79
  "make",
80
80
  "make_for_task",
81
81
  "instances",
82
- "instance",
82
+ "instance",
83
83
  "delete",
84
84
  "load_tasks_from_file",
85
85
  "load_task_array_from_string",
86
- "load_task_from_string",
86
+ "load_task_from_string",
87
87
  "load_task_from_json",
88
88
  "export_tasks",
89
89
  "import_tasks",
@@ -108,9 +108,13 @@ async def environment(env_key: str) -> Environment:
108
108
  return await _async_global_client.get_client().environment(env_key)
109
109
 
110
110
 
111
- async def make(env_key: str, region: Optional[str] = None, env_variables: Optional[Dict[str, Any]] = None) -> AsyncEnv:
111
+ async def make(
112
+ env_key: str,
113
+ region: Optional[str] = None,
114
+ env_variables: Optional[Dict[str, Any]] = None,
115
+ ) -> AsyncEnv:
112
116
  """Create a new environment instance.
113
-
117
+
114
118
  Example:
115
119
  env = await fleet.make("fira")
116
120
  env_with_vars = await fleet.make("fira", env_variables={"LOGGED_IN_NAME": "Alice"})
@@ -123,7 +127,9 @@ async def make_for_task(task: Task) -> AsyncEnv:
123
127
  return await _async_global_client.get_client().make_for_task(task)
124
128
 
125
129
 
126
- async def instances(status: Optional[str] = None, region: Optional[str] = None) -> List[AsyncEnv]:
130
+ async def instances(
131
+ status: Optional[str] = None, region: Optional[str] = None
132
+ ) -> List[AsyncEnv]:
127
133
  """List existing environment instances."""
128
134
  return await _async_global_client.get_client().instances(status, region)
129
135
 
@@ -140,7 +146,7 @@ async def delete(instance_id: str) -> InstanceResponse:
140
146
 
141
147
  async def load_tasks_from_file(filename: str) -> List[Task]:
142
148
  """Load tasks from a JSON file.
143
-
149
+
144
150
  Example:
145
151
  tasks = await fleet.load_tasks_from_file("my_tasks.json")
146
152
  """
@@ -149,16 +155,18 @@ async def load_tasks_from_file(filename: str) -> List[Task]:
149
155
 
150
156
  async def load_task_array_from_string(serialized_tasks: str) -> List[Task]:
151
157
  """Load tasks from a JSON string containing an array of tasks.
152
-
158
+
153
159
  Example:
154
160
  tasks = await fleet.load_task_array_from_string(json_string)
155
161
  """
156
- return await _async_global_client.get_client().load_task_array_from_string(serialized_tasks)
162
+ return await _async_global_client.get_client().load_task_array_from_string(
163
+ serialized_tasks
164
+ )
157
165
 
158
166
 
159
167
  async def load_task_from_string(task_string: str) -> Task:
160
168
  """Load a single task from a JSON string.
161
-
169
+
162
170
  Example:
163
171
  task = await fleet.load_task_from_string(task_json_string)
164
172
  """
@@ -167,16 +175,18 @@ async def load_task_from_string(task_string: str) -> Task:
167
175
 
168
176
  async def load_task_from_json(task_json: dict) -> Task:
169
177
  """Load a single task from a dictionary.
170
-
178
+
171
179
  Example:
172
180
  task = await fleet.load_task_from_json(task_dict)
173
181
  """
174
182
  return await _async_global_client.get_client().load_task_from_json(task_json)
175
183
 
176
184
 
177
- async def export_tasks(env_key: Optional[str] = None, filename: Optional[str] = None) -> Optional[str]:
185
+ async def export_tasks(
186
+ env_key: Optional[str] = None, filename: Optional[str] = None
187
+ ) -> Optional[str]:
178
188
  """Export tasks to a JSON file.
179
-
189
+
180
190
  Example:
181
191
  await fleet.export_tasks("fira", "fira_tasks.json")
182
192
  """
@@ -185,7 +195,7 @@ async def export_tasks(env_key: Optional[str] = None, filename: Optional[str] =
185
195
 
186
196
  async def import_tasks(filename: str):
187
197
  """Import tasks from a JSON file.
188
-
198
+
189
199
  Example:
190
200
  await fleet.import_tasks("tasks.json")
191
201
  """
@@ -200,8 +210,8 @@ async def account() -> AccountResponse:
200
210
  def configure(
201
211
  api_key: Optional[str] = None,
202
212
  base_url: Optional[str] = None,
203
- max_retries: int | None = None,
204
- timeout: float | None = None,
213
+ max_retries: Optional[int] = None,
214
+ timeout: Optional[float] = None,
205
215
  ):
206
216
  """Configure global async client once per process.
207
217
 
@@ -213,9 +223,11 @@ def configure(
213
223
  """
214
224
  if max_retries is None:
215
225
  from ..config import DEFAULT_MAX_RETRIES as _MR
226
+
216
227
  max_retries = _MR
217
228
  if timeout is None:
218
229
  from ..config import DEFAULT_TIMEOUT as _TO
230
+
219
231
  timeout = _TO
220
232
  _async_global_client.configure(
221
233
  api_key=api_key, base_url=base_url, max_retries=max_retries, timeout=timeout
@@ -14,6 +14,7 @@
14
14
 
15
15
  """Fleet API Client for making HTTP requests to Fleet services."""
16
16
 
17
+ import asyncio
17
18
  import base64
18
19
  import cloudpickle
19
20
  import httpx
@@ -129,7 +130,7 @@ class AsyncEnv(EnvironmentBase):
129
130
  return await self.instance.verify(validator)
130
131
 
131
132
  async def verify_raw(
132
- self, function_code: str, function_name: str | None = None
133
+ self, function_code: str, function_name: Optional[str] = None
133
134
  ) -> ExecuteFunctionResponse:
134
135
  return await self.instance.verify_raw(function_code, function_name)
135
136
 
@@ -206,24 +207,39 @@ class AsyncFleet:
206
207
  async def make(
207
208
  self,
208
209
  env_key: str,
210
+ data_key: Optional[str] = None,
209
211
  region: Optional[str] = None,
210
212
  env_variables: Optional[Dict[str, Any]] = None,
211
213
  ) -> AsyncEnv:
212
214
  if ":" in env_key:
213
- env_key_part, version = env_key.split(":", 1)
215
+ env_key_part, env_version = env_key.split(":", 1)
214
216
  if (
215
- not version.startswith("v")
216
- and len(version) != 0
217
- and version[0].isdigit()
217
+ not env_version.startswith("v")
218
+ and len(env_version) != 0
219
+ and env_version[0].isdigit()
218
220
  ):
219
- version = f"v{version}"
221
+ env_version = f"v{env_version}"
220
222
  else:
221
223
  env_key_part = env_key
222
- version = None
224
+ env_version = None
225
+
226
+ if data_key is not None and ":" in data_key:
227
+ data_key_part, data_version = data_key.split(":", 1)
228
+ if (
229
+ not data_version.startswith("v")
230
+ and len(data_version) != 0
231
+ and data_version[0].isdigit()
232
+ ):
233
+ data_version = f"v{data_version}"
234
+ else:
235
+ data_key_part = data_key
236
+ data_version = None
223
237
 
224
238
  request = InstanceRequest(
225
239
  env_key=env_key_part,
226
- version=version,
240
+ env_version=env_version,
241
+ data_key=data_key_part,
242
+ data_version=data_version,
227
243
  region=region,
228
244
  env_variables=env_variables,
229
245
  created_from="sdk",
@@ -286,43 +302,72 @@ class AsyncFleet:
286
302
  with open(filename, "r", encoding="utf-8") as f:
287
303
  tasks_data = f.read()
288
304
 
289
- return self.load_task_array_from_string(tasks_data)
305
+ return await self.load_task_array_from_string(tasks_data)
290
306
 
291
- async def load_task_array_from_string(
292
- self, serialized_tasks: List[Dict]
293
- ) -> List[Task]:
307
+ async def load_task_array_from_string(self, serialized_tasks: str) -> List[Task]:
294
308
  tasks = []
295
309
 
296
- json_tasks = json.loads(serialized_tasks)
310
+ parsed_data = json.loads(serialized_tasks)
311
+ if isinstance(parsed_data, list):
312
+ json_tasks = parsed_data
313
+ elif isinstance(parsed_data, dict) and "tasks" in parsed_data:
314
+ json_tasks = parsed_data["tasks"]
315
+ else:
316
+ raise ValueError(
317
+ "Invalid JSON structure: expected array or object with 'tasks' key"
318
+ )
319
+
297
320
  for json_task in json_tasks:
298
- parsed_task = self.load_task_from_json(json_task)
321
+ parsed_task = await self.load_task_from_json(json_task)
299
322
  tasks.append(parsed_task)
300
323
  return tasks
301
324
 
302
325
  async def load_task_from_string(self, task_string: str) -> Task:
303
326
  task_json = json.loads(task_string)
304
- return self.load_task_from_json(task_json)
327
+ return await self.load_task_from_json(task_json)
305
328
 
306
329
  async def load_task_from_json(self, task_json: Dict) -> Task:
330
+ verifier = None
331
+ verifier_code = task_json.get("verifier_func") or task_json.get("verifier_code")
332
+
333
+ # Try to find verifier_id in multiple locations
334
+ verifier_id = task_json.get("verifier_id")
335
+ if (
336
+ not verifier_id
337
+ and "metadata" in task_json
338
+ and isinstance(task_json["metadata"], dict)
339
+ ):
340
+ verifier_metadata = task_json["metadata"].get("verifier", {})
341
+ if isinstance(verifier_metadata, dict):
342
+ verifier_id = verifier_metadata.get("verifier_id")
343
+
344
+ # If no verifier_id found, use the task key/id as fallback
345
+ if not verifier_id:
346
+ verifier_id = task_json.get("key", task_json.get("id"))
347
+
307
348
  try:
308
- if "verifier_id" in task_json and task_json["verifier_id"]:
309
- verifier = self._create_verifier_from_data(
310
- verifier_id=task_json["verifier_id"],
311
- verifier_key=task_json["key"],
312
- verifier_code=task_json["verifier_func"],
349
+ if verifier_id and verifier_code:
350
+ verifier = await self._create_verifier_from_data(
351
+ verifier_id=verifier_id,
352
+ verifier_key=task_json.get("key", task_json.get("id")),
353
+ verifier_code=verifier_code,
313
354
  verifier_sha=task_json.get("verifier_sha", ""),
314
355
  )
315
356
  except Exception as e:
316
- logger.warning(f"Failed to create verifier {task_json['key']}: {e}")
357
+ logger.warning(
358
+ f"Failed to create verifier {task_json.get('key', task_json.get('id'))}: {e}"
359
+ )
317
360
 
318
361
  task = Task(
319
- key=task_json["key"],
362
+ key=task_json.get("key", task_json.get("id")),
320
363
  prompt=task_json["prompt"],
321
- env_id=task_json["env_id"], # Use env_id from the data
322
- created_at=task_json["created_at"],
364
+ env_id=task_json.get(
365
+ "env_id", task_json.get("env_key")
366
+ ), # Use env_id or fallback to env_key
367
+ created_at=task_json.get("created_at"),
323
368
  version=task_json.get("version"),
324
369
  env_variables=task_json.get("env_variables", {}),
325
- verifier_func=task_json.get("verifier_func"), # Set verifier code
370
+ verifier_func=verifier_code, # Set verifier code
326
371
  verifier=verifier, # Use created verifier or None
327
372
  metadata=task_json.get("metadata", {}), # Default empty metadata
328
373
  )
@@ -357,48 +402,99 @@ class AsyncFleet:
357
402
  response = await self.client.request("GET", "/v1/tasks", params=params)
358
403
  task_list_response = TaskListResponse(**response.json())
359
404
 
360
- # Transform TaskResponse objects to Task objects
361
- tasks = []
362
- for task_response in task_list_response.tasks:
363
- # Create verifier function if verifier data is present
364
- verifier = None
365
- verifier_func = task_response.verifier_func
405
+ # Prepare verifier loading coroutines with concurrency limit
406
+ verifier_coroutines = []
407
+ task_responses_with_indices = []
408
+ semaphore = asyncio.Semaphore(100) # Limit to 10 concurrent operations
366
409
 
410
+ for idx, task_response in enumerate(task_list_response.tasks):
367
411
  if task_response.verifier:
368
412
  embedded_code = task_response.verifier.code or ""
369
413
  is_embedded_error = embedded_code.strip().startswith(
370
414
  "<error loading code:"
371
415
  )
372
- if not is_embedded_error:
373
- # Only override if the embedded code looks valid
374
- verifier_func = embedded_code
375
- # Create VerifierFunction from the embedded data
376
- try:
377
- verifier = await self._create_verifier_from_data(
378
- verifier_id=task_response.verifier.verifier_id,
379
- verifier_key=task_response.verifier.key,
380
- verifier_code=embedded_code,
381
- verifier_sha=task_response.verifier.sha256,
382
- )
383
- except Exception as e:
384
- logger.warning(
385
- f"Failed to create verifier {task_response.verifier.key}: {e}"
386
- )
387
- else:
388
- # Fallback: try fetching by ID if embedded code failed to load
389
- try:
390
- logger.warning(
391
- f"Embedded verifier code missing for {task_response.verifier.key} (NoSuchKey). "
392
- f"Attempting to refetch by id {task_response.verifier.verifier_id}"
393
- )
394
- verifier = await self._load_verifier(
395
- task_response.verifier.verifier_id
396
- )
397
- except Exception as e:
398
- logger.warning(
399
- f"Refetch by verifier id failed for {task_response.verifier.key}: {e}. "
400
- "Leaving verifier unset."
401
- )
416
+
417
+ async def create_verifier_with_fallback(tr, emb_code, is_error):
418
+ """Create verifier with fallback logic."""
419
+ async with semaphore: # Acquire semaphore before operation
420
+ if not is_error:
421
+ # Try to create from embedded data
422
+ try:
423
+ return await self._create_verifier_from_data(
424
+ verifier_id=tr.verifier.verifier_id,
425
+ verifier_key=tr.verifier.key,
426
+ verifier_code=emb_code,
427
+ verifier_sha=tr.verifier.sha256,
428
+ )
429
+ except Exception as e:
430
+ logger.warning(
431
+ f"Failed to create verifier {tr.verifier.key}: {e}"
432
+ )
433
+ return None
434
+ else:
435
+ # Fallback: try fetching by ID
436
+ try:
437
+ logger.warning(
438
+ f"Embedded verifier code missing for {tr.verifier.key} (NoSuchKey). "
439
+ f"Attempting to refetch by id {tr.verifier.verifier_id}"
440
+ )
441
+ return await self._load_verifier(
442
+ tr.verifier.verifier_id
443
+ )
444
+ except Exception as e:
445
+ logger.warning(
446
+ f"Refetch by verifier id failed for {tr.verifier.key}: {e}. "
447
+ "Leaving verifier unset."
448
+ )
449
+ return None
450
+
451
+ # Add the coroutine for parallel execution
452
+ verifier_coroutines.append(
453
+ create_verifier_with_fallback(
454
+ task_response, embedded_code, is_embedded_error
455
+ )
456
+ )
457
+ task_responses_with_indices.append((idx, task_response))
458
+ else:
459
+ # No verifier needed
460
+ verifier_coroutines.append(None)
461
+ task_responses_with_indices.append((idx, task_response))
462
+
463
+ # Execute all verifier loading in parallel
464
+ if verifier_coroutines:
465
+ verifier_results = await asyncio.gather(
466
+ *[
467
+ coro if coro is not None else asyncio.sleep(0)
468
+ for coro in verifier_coroutines
469
+ ],
470
+ return_exceptions=True,
471
+ )
472
+ else:
473
+ verifier_results = []
474
+
475
+ # Build tasks with results
476
+ tasks = []
477
+ for (idx, task_response), verifier_result in zip(
478
+ task_responses_with_indices, verifier_results
479
+ ):
480
+ # Handle verifier result
481
+ verifier = None
482
+ verifier_func = task_response.verifier_func
483
+
484
+ if task_response.verifier:
485
+ # Process verifier result
486
+ if isinstance(verifier_result, Exception):
487
+ logger.warning(
488
+ f"Verifier loading failed for {task_response.key}: {verifier_result}"
489
+ )
490
+ elif verifier_result is not None:
491
+ verifier = verifier_result
492
+ embedded_code = task_response.verifier.code or ""
493
+ is_embedded_error = embedded_code.strip().startswith(
494
+ "<error loading code:"
495
+ )
496
+ if not is_embedded_error:
497
+ verifier_func = embedded_code
402
498
 
403
499
  task = Task(
404
500
  key=task_response.key,
@@ -507,7 +603,7 @@ class AsyncFleet:
507
603
  self,
508
604
  task_key: str,
509
605
  prompt: Optional[str] = None,
510
- verifier_code: Optional[str] = None
606
+ verifier_code: Optional[str] = None,
511
607
  ) -> TaskResponse:
512
608
  """Update an existing task.
513
609
 
@@ -519,10 +615,7 @@ class AsyncFleet:
519
615
  Returns:
520
616
  TaskResponse containing the updated task details
521
617
  """
522
- payload = TaskUpdateRequest(
523
- prompt=prompt,
524
- verifier_code=verifier_code
525
- )
618
+ payload = TaskUpdateRequest(prompt=prompt, verifier_code=verifier_code)
526
619
  response = await self.client.request(
527
620
  "PUT", f"/v1/tasks/{task_key}", json=payload.model_dump(exclude_none=True)
528
621
  )
@@ -542,8 +635,7 @@ class AsyncFleet:
542
635
  Returns:
543
636
  AsyncVerifierFunction created from the verifier code
544
637
  """
545
- from ..tasks import verifier_from_string
546
- from .verifiers.verifier import AsyncVerifierFunction
638
+ from .tasks import verifier_from_string
547
639
 
548
640
  # Use verifier_from_string to create the verifier
549
641
  verifier_func = verifier_from_string(
@@ -568,7 +660,7 @@ class AsyncFleet:
568
660
  AsyncVerifierFunction created from the verifier code
569
661
  """
570
662
  # Fetch verifier from API
571
- response = await self.client.request("GET", f"/v1/verifier/{verifier_id}")
663
+ response = await self.client.request("GET", f"/v1/verifiers/{verifier_id}")
572
664
  verifier_data = response.json()
573
665
 
574
666
  # Use the common method to create verifier
@@ -3,8 +3,15 @@ from ...models import Environment as EnvironmentModel, AccountResponse
3
3
  from typing import List, Optional, Dict, Any
4
4
 
5
5
 
6
- async def make_async(env_key: str, region: Optional[str] = None, env_variables: Optional[Dict[str, Any]] = None) -> AsyncEnv:
7
- return await AsyncFleet().make(env_key, region=region, env_variables=env_variables)
6
+ async def make_async(
7
+ env_key: str,
8
+ data_key: Optional[str] = None,
9
+ region: Optional[str] = None,
10
+ env_variables: Optional[Dict[str, Any]] = None,
11
+ ) -> AsyncEnv:
12
+ return await AsyncFleet().make(
13
+ env_key, data_key=data_key, region=region, env_variables=env_variables
14
+ )
8
15
 
9
16
 
10
17
  async def make_for_task_async(task: Task) -> AsyncEnv:
@@ -108,7 +108,7 @@ class AsyncInstanceClient:
108
108
  return await self.verify_raw(function_code, function_name)
109
109
 
110
110
  async def verify_raw(
111
- self, function_code: str, function_name: str | None = None
111
+ self, function_code: str, function_name: Optional[str] = None
112
112
  ) -> ExecuteFunctionResponse:
113
113
  try:
114
114
  function_code = convert_verifier_string(function_code)