fleet-python 0.2.118__tar.gz → 0.2.120__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.
Files changed (147) hide show
  1. fleet_python-0.2.120/PKG-INFO +336 -0
  2. fleet_python-0.2.120/README.md +285 -0
  3. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_task.py +1 -1
  4. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/export_tasks.py +32 -10
  5. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/import_tasks.py +1 -49
  6. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/iterate_verifiers.py +2 -2
  7. fleet_python-0.2.120/examples/task_bundle_editing/download_task.py +178 -0
  8. fleet_python-0.2.120/examples/task_bundle_editing/launch_job.py +160 -0
  9. fleet_python-0.2.120/examples/task_bundle_editing/upload_task.py +333 -0
  10. fleet_python-0.2.120/examples/task_bundle_editing/validate_task.py +267 -0
  11. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/__init__.py +1 -16
  12. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/__init__.py +2 -2
  13. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/base.py +1 -1
  14. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/client.py +128 -111
  15. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/instance/client.py +0 -14
  16. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/models.py +55 -3
  17. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/resources/sqlite.py +4 -9
  18. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/tasks.py +74 -21
  19. fleet_python-0.2.120/fleet/_supabase.py +6 -0
  20. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/agent.py +377 -159
  21. fleet_python-0.2.120/fleet/auth.py +101 -0
  22. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/base.py +19 -6
  23. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/cli.py +160 -9
  24. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/client.py +126 -105
  25. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/instance/client.py +0 -14
  26. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/instance/models.py +0 -75
  27. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/models.py +69 -4
  28. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/resources/sqlite.py +7 -12
  29. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/tasks.py +66 -17
  30. fleet_python-0.2.120/fleet/track/__init__.py +1 -0
  31. fleet_python-0.2.120/fleet/track/api.py +101 -0
  32. fleet_python-0.2.120/fleet/track/cli.py +171 -0
  33. fleet_python-0.2.120/fleet/track/daemon.py +340 -0
  34. fleet_python-0.2.120/fleet/track/install.py +157 -0
  35. fleet_python-0.2.120/fleet/track/merkle.py +167 -0
  36. fleet_python-0.2.120/fleet/track/queue.py +158 -0
  37. fleet_python-0.2.120/fleet/track/scrubber.py +60 -0
  38. fleet_python-0.2.120/fleet/track/sources.py +95 -0
  39. fleet_python-0.2.120/fleet/track/status.py +83 -0
  40. fleet_python-0.2.120/fleet/track/uploader.py +119 -0
  41. fleet_python-0.2.120/fleet/track/watcher.py +108 -0
  42. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/__init__.py +0 -4
  43. fleet_python-0.2.120/fleet_python.egg-info/PKG-INFO +336 -0
  44. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet_python.egg-info/SOURCES.txt +18 -7
  45. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet_python.egg-info/requires.txt +1 -0
  46. {fleet_python-0.2.118 → fleet_python-0.2.120}/pyproject.toml +7 -1
  47. fleet_python-0.2.118/PKG-INFO +0 -145
  48. fleet_python-0.2.118/README.md +0 -95
  49. fleet_python-0.2.118/examples/export_tasks_filtered.py +0 -245
  50. fleet_python-0.2.118/fleet/_async/judge.py +0 -152
  51. fleet_python-0.2.118/fleet/_async/resources/filesystem.py +0 -378
  52. fleet_python-0.2.118/fleet/judge.py +0 -1014
  53. fleet_python-0.2.118/fleet/resources/filesystem.py +0 -378
  54. fleet_python-0.2.118/fleet/verifiers/local_executor.py +0 -371
  55. fleet_python-0.2.118/fleet_python.egg-info/PKG-INFO +0 -145
  56. fleet_python-0.2.118/tests/test_judge_criteria_markers.py +0 -192
  57. {fleet_python-0.2.118 → fleet_python-0.2.120}/LICENSE +0 -0
  58. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/diff_example.py +0 -0
  59. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/dsl_example.py +0 -0
  60. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example.py +0 -0
  61. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/exampleResume.py +0 -0
  62. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_account.py +0 -0
  63. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_action_log.py +0 -0
  64. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_client.py +0 -0
  65. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_mcp_anthropic.py +0 -0
  66. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_mcp_openai.py +0 -0
  67. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_sync.py +0 -0
  68. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_tasks.py +0 -0
  69. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/example_verifier.py +0 -0
  70. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/fetch_tasks.py +0 -0
  71. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/gemini_example.py +0 -0
  72. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/json_tasks_example.py +0 -0
  73. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/nova_act_example.py +0 -0
  74. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/openai_example.py +0 -0
  75. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/openai_simple_example.py +0 -0
  76. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/query_builder_example.py +0 -0
  77. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/quickstart.py +0 -0
  78. {fleet_python-0.2.118 → fleet_python-0.2.120}/examples/test_cdp_logging.py +0 -0
  79. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/env/__init__.py +0 -0
  80. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/env/client.py +0 -0
  81. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/exceptions.py +0 -0
  82. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/global_client.py +0 -0
  83. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/instance/__init__.py +0 -0
  84. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/instance/base.py +0 -0
  85. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/resources/__init__.py +0 -0
  86. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/resources/api.py +0 -0
  87. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/resources/base.py +0 -0
  88. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/resources/browser.py +0 -0
  89. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/resources/mcp.py +0 -0
  90. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/verifiers/__init__.py +0 -0
  91. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/verifiers/bundler.py +0 -0
  92. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/_async/verifiers/verifier.py +0 -0
  93. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/__init__.py +0 -0
  94. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/Dockerfile +0 -0
  95. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/__init__.py +0 -0
  96. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/mcp/main.py +0 -0
  97. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/mcp_server/__init__.py +0 -0
  98. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/mcp_server/main.py +0 -0
  99. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/mcp_server/tools.py +0 -0
  100. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/requirements.txt +0 -0
  101. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/gemini_cua/start.sh +0 -0
  102. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/orchestrator.py +0 -0
  103. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/types.py +0 -0
  104. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/agent/utils.py +0 -0
  105. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/config.py +0 -0
  106. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/env/__init__.py +0 -0
  107. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/env/client.py +0 -0
  108. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/eval/__init__.py +0 -0
  109. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/eval/uploader.py +0 -0
  110. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/exceptions.py +0 -0
  111. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/global_client.py +0 -0
  112. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/instance/__init__.py +0 -0
  113. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/instance/base.py +0 -0
  114. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/proxy/__init__.py +0 -0
  115. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/proxy/proxy.py +0 -0
  116. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/proxy/whitelist.py +0 -0
  117. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/resources/__init__.py +0 -0
  118. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/resources/api.py +0 -0
  119. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/resources/base.py +0 -0
  120. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/resources/browser.py +0 -0
  121. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/resources/mcp.py +0 -0
  122. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/types.py +0 -0
  123. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/utils/__init__.py +0 -0
  124. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/utils/http_logging.py +0 -0
  125. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/utils/logging.py +0 -0
  126. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/utils/playwright.py +0 -0
  127. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/bundler.py +0 -0
  128. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/code.py +0 -0
  129. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/db.py +0 -0
  130. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/decorator.py +0 -0
  131. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/parse.py +0 -0
  132. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/sql_differ.py +0 -0
  133. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet/verifiers/verifier.py +0 -0
  134. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet_python.egg-info/dependency_links.txt +0 -0
  135. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet_python.egg-info/entry_points.txt +0 -0
  136. {fleet_python-0.2.118 → fleet_python-0.2.120}/fleet_python.egg-info/top_level.txt +0 -0
  137. {fleet_python-0.2.118 → fleet_python-0.2.120}/scripts/fix_sync_imports.py +0 -0
  138. {fleet_python-0.2.118 → fleet_python-0.2.120}/scripts/unasync.py +0 -0
  139. {fleet_python-0.2.118 → fleet_python-0.2.120}/setup.cfg +0 -0
  140. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/__init__.py +0 -0
  141. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_app_method.py +0 -0
  142. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_expect_exactly.py +0 -0
  143. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_expect_only.py +0 -0
  144. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_instance_dispatch.py +0 -0
  145. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_sqlite_resource_dual_mode.py +0 -0
  146. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_sqlite_shared_memory_behavior.py +0 -0
  147. {fleet_python-0.2.118 → fleet_python-0.2.120}/tests/test_verifier_from_string.py +0 -0
@@ -0,0 +1,336 @@
1
+ Metadata-Version: 2.4
2
+ Name: fleet-python
3
+ Version: 0.2.120
4
+ Summary: Python SDK for Fleet environments
5
+ Author-email: Fleet AI <nic@fleet.so>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://fleetai.com
8
+ Project-URL: Documentation, https://docs.fleetai.com
9
+ Project-URL: Repository, https://github.com/fleet-ai/fleet-sdk
10
+ Project-URL: Issues, https://github.com/fleet-ai/fleet-sdk/issues
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: aiohttp>=3.8.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Requires-Dist: httpx>=0.27.0
25
+ Requires-Dist: httpx-retries>=0.4.0
26
+ Requires-Dist: typing-extensions>=4.0.0
27
+ Requires-Dist: modulegraph2>=0.2.0
28
+ Requires-Dist: cloudpickle==3.1.1
29
+ Provides-Extra: cli
30
+ Requires-Dist: typer>=0.9.0; extra == "cli"
31
+ Requires-Dist: rich>=10.0.0; extra == "cli"
32
+ Requires-Dist: watchdog>=4.0.0; extra == "cli"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
35
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
36
+ Requires-Dist: black>=22.0.0; extra == "dev"
37
+ Requires-Dist: isort>=5.0.0; extra == "dev"
38
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
39
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
40
+ Requires-Dist: unasync>=0.6.0; extra == "dev"
41
+ Requires-Dist: python-dotenv>=1.1.1; extra == "dev"
42
+ Requires-Dist: typer>=0.9.0; extra == "dev"
43
+ Requires-Dist: rich>=10.0.0; extra == "dev"
44
+ Provides-Extra: playwright
45
+ Requires-Dist: playwright>=1.40.0; extra == "playwright"
46
+ Provides-Extra: eval
47
+ Requires-Dist: aiohttp>=3.9.0; extra == "eval"
48
+ Requires-Dist: google-genai>=1.0.0; extra == "eval"
49
+ Requires-Dist: mcp==1.24.0; python_version >= "3.10" and extra == "eval"
50
+ Dynamic: license-file
51
+
52
+ # Fleet SDK
53
+
54
+ [![PyPI version](https://img.shields.io/pypi/v/fleet-python.svg)](https://pypi.org/project/fleet-python/)
55
+ [![Python versions](https://img.shields.io/pypi/pyversions/fleet-python.svg)](https://pypi.org/project/fleet-python/)
56
+ [![License](https://img.shields.io/pypi/l/fleet-python.svg)](https://pypi.org/project/fleet-python/)
57
+
58
+ The Fleet Python SDK provides programmatic access to Fleet's environment infrastructure.
59
+
60
+ ## Installation
61
+
62
+ ```bash
63
+ pip install fleet-python
64
+ ```
65
+
66
+ ## API Key Setup
67
+
68
+ Get your API key from the [Fleet Dashboard](https://fleetai.com/dashboard/api-keys), then set it as an environment variable:
69
+
70
+ ```bash
71
+ export FLEET_API_KEY="sk_your_key_here"
72
+ ```
73
+
74
+ ## Tasks
75
+
76
+ A **Task** represents a unit of work for an agent to complete within an environment. Each task combines:
77
+
78
+ - **Prompt**: Instructions describing what needs to be done
79
+ - **Environment**: The environment configuration (`env_key`, `data_key`, `env_variables`)
80
+ - **Verifier**: Code that validates task completion and returns a score (0.0 to 1.0)
81
+
82
+ Tasks provide all the configuration needed to spin up an environment and verify an agent's work.
83
+
84
+ ### Task Properties
85
+
86
+ | Property | Description |
87
+ | --------------- | ----------------------------------------------------- |
88
+ | `key` | Unique task identifier |
89
+ | `prompt` | Instructions for the agent |
90
+ | `env_key` | Environment identifier (e.g., `"hubspot:v1.2"`) |
91
+ | `data_key` | Data configuration identifier |
92
+ | `env_variables` | Environment variables for the task |
93
+ | `metadata` | Additional info (e.g., `avg_steps` for task difficulty) |
94
+
95
+ ## Quick Start
96
+
97
+ ```python
98
+ import fleet
99
+
100
+ async def main():
101
+ # Load a task
102
+ tasks = await fleet.load_tasks_async(
103
+ keys=["task_abcdef"]
104
+ )
105
+ task = tasks[0]
106
+
107
+ # Create an environment from the task
108
+ env = await fleet.env.make_async(
109
+ env_key=task.env_key,
110
+ data_key=task.data_key,
111
+ env_variables=task.env_variables,
112
+ ttl_seconds=7200,
113
+ run_id="run-123",
114
+ )
115
+
116
+ # Access the environment URL
117
+ print(env.urls.app[0])
118
+
119
+ # ... interact with the environment ...
120
+
121
+ # Verify task completion
122
+ result = await task.verify_detailed_async(env.instance_id)
123
+ print(result)
124
+
125
+ # Clean up
126
+ await env.close()
127
+ ```
128
+
129
+ ## Loading Tasks
130
+
131
+ ### By Task Keys
132
+
133
+ ```python
134
+ tasks = await fleet.load_tasks_async(
135
+ keys=["task_abcdef"]
136
+ )
137
+ ```
138
+
139
+ ### By Project Key
140
+
141
+ ```python
142
+ tasks = await fleet.load_tasks_async(project_key="my-project")
143
+ ```
144
+
145
+ ## Creating Environments
146
+
147
+ ```python
148
+ env = await fleet.env.make_async(
149
+ env_key=task.env_key,
150
+ data_key=task.data_key,
151
+ env_variables=task.env_variables,
152
+ ttl_seconds=7200,
153
+ run_id="run-123",
154
+ )
155
+ ```
156
+
157
+ ### With Heartbeats (Optional)
158
+
159
+ Optionally enable heartbeats to keep environments alive during long-running operations:
160
+
161
+ ```python
162
+ env = await fleet.env.make_async(
163
+ env_key=task.env_key,
164
+ data_key=task.data_key,
165
+ env_variables=task.env_variables,
166
+ ttl_seconds=10800,
167
+ heartbeat_interval=30, # seconds
168
+ )
169
+ ```
170
+
171
+ Send heartbeats to keep the environment alive:
172
+
173
+ ```python
174
+ # Via the environment object
175
+ await env.heartbeat()
176
+
177
+ # Or via instance ID
178
+ await fleet.env.heartbeat_async(instance_id)
179
+ ```
180
+
181
+ Heartbeats are optional. If `heartbeat_interval` is not set, the instance lifetime is controlled solely by `ttl_seconds`. If heartbeats are enabled and missed 3 consecutive times, the instance will be terminated. Heartbeats take precedence over the TTL.
182
+
183
+ ## Instance Management
184
+
185
+ ### List Instances
186
+
187
+ ```python
188
+ # List all instances for a run
189
+ instances = await fleet.env.list_instances_async(run_id="run-123")
190
+
191
+ # List all instances for your profile
192
+ instances = await fleet.env.list_instances_async(profile_id="self")
193
+ ```
194
+
195
+ ### Close Instances
196
+
197
+ ```python
198
+ # Close all instances for a run
199
+ await fleet.env.close_all_async(run_id="run-123")
200
+
201
+ # Close all instances for your profile
202
+ await fleet.env.close_all_async(profile_id="self")
203
+
204
+ # Close a specific instance by ID
205
+ await fleet.env.close_async("bc8954c2")
206
+ ```
207
+
208
+ `"self"` is an alias for the profile associated with your `FLEET_API_KEY`.
209
+
210
+ ## Account Information
211
+
212
+ View your current account details including team info, instance limits, and profile ID:
213
+
214
+ ```python
215
+ account = await fleet.env.account_async()
216
+ ```
217
+
218
+ Returns:
219
+
220
+ ```json
221
+ {
222
+ "team_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
223
+ "team_name": "My Team",
224
+ "instance_limit": 32000,
225
+ "instance_count": 924,
226
+ "profile_id": "11111111-2222-3333-4444-555555555555",
227
+ "profile_name": "Jane Doe"
228
+ }
229
+ ```
230
+
231
+ ## Run Tracking
232
+
233
+ Track active and past runs:
234
+
235
+ ```python
236
+ # List active runs
237
+ runs = await fleet.env.list_runs_async()
238
+
239
+ # List all runs (active and inactive)
240
+ runs = await fleet.env.list_runs_async(status="all")
241
+
242
+ # Filter by profile
243
+ runs = await fleet.env.list_runs_async(profile_id="self")
244
+ ```
245
+
246
+ Returns:
247
+
248
+ ```json
249
+ [
250
+ {
251
+ "run_id": "run-123",
252
+ "running_count": 0,
253
+ "total_count": 4,
254
+ "first_created_at": "2025-10-24T09:48:47.152387",
255
+ "last_created_at": "2025-10-24T09:55:19.284294",
256
+ "profile_id": "11111111-2222-3333-4444-555555555555"
257
+ }
258
+ ]
259
+ ```
260
+
261
+ ## Task Verification
262
+
263
+ Verify task completion and get detailed results:
264
+
265
+ ```python
266
+ result = await task.verify_detailed_async(env.instance_id)
267
+ print(result)
268
+ ```
269
+
270
+ Returns:
271
+
272
+ ```json
273
+ {
274
+ "key": "task_abcdef",
275
+ "version": 4,
276
+ "success": true,
277
+ "result": 1.0,
278
+ "error": null,
279
+ "execution_time_ms": 2291,
280
+ "stdout": ""
281
+ }
282
+ ```
283
+
284
+ On failure, `stdout` contains detailed verification errors:
285
+
286
+ ```json
287
+ {
288
+ "key": "task_abcdef",
289
+ "version": 4,
290
+ "success": true,
291
+ "result": 0,
292
+ "error": null,
293
+ "execution_time_ms": 2291,
294
+ "stdout": "Verification errors: [\"Expected field to be 'value', got None\", \"Form not marked as complete\"]"
295
+ }
296
+ ```
297
+
298
+ ## Complete Example
299
+
300
+ ```python
301
+ import fleet
302
+ import asyncio
303
+
304
+ async def main():
305
+ # Load tasks from a project
306
+ tasks = await fleet.load_tasks_async(project_key="my-project")
307
+
308
+ for task in tasks:
309
+ # Create environment
310
+ env = await fleet.env.make_async(
311
+ env_key=task.env_key,
312
+ data_key=task.data_key,
313
+ env_variables=task.env_variables,
314
+ ttl_seconds=7200,
315
+ run_id="my-evaluation-run",
316
+ )
317
+
318
+ try:
319
+ # Access the environment URL
320
+ print(env.urls.app[0])
321
+
322
+ # ... run your agent ...
323
+
324
+ # Verify task completion
325
+ result = await task.verify_detailed_async(env.instance_id)
326
+ print(f"Task {task.key}: score={result['result']}")
327
+
328
+ finally:
329
+ await env.close()
330
+
331
+ # Clean up all instances from this run
332
+ await fleet.env.close_all_async(run_id="my-evaluation-run")
333
+
334
+ if __name__ == "__main__":
335
+ asyncio.run(main())
336
+ ```
@@ -0,0 +1,285 @@
1
+ # Fleet SDK
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/fleet-python.svg)](https://pypi.org/project/fleet-python/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/fleet-python.svg)](https://pypi.org/project/fleet-python/)
5
+ [![License](https://img.shields.io/pypi/l/fleet-python.svg)](https://pypi.org/project/fleet-python/)
6
+
7
+ The Fleet Python SDK provides programmatic access to Fleet's environment infrastructure.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install fleet-python
13
+ ```
14
+
15
+ ## API Key Setup
16
+
17
+ Get your API key from the [Fleet Dashboard](https://fleetai.com/dashboard/api-keys), then set it as an environment variable:
18
+
19
+ ```bash
20
+ export FLEET_API_KEY="sk_your_key_here"
21
+ ```
22
+
23
+ ## Tasks
24
+
25
+ A **Task** represents a unit of work for an agent to complete within an environment. Each task combines:
26
+
27
+ - **Prompt**: Instructions describing what needs to be done
28
+ - **Environment**: The environment configuration (`env_key`, `data_key`, `env_variables`)
29
+ - **Verifier**: Code that validates task completion and returns a score (0.0 to 1.0)
30
+
31
+ Tasks provide all the configuration needed to spin up an environment and verify an agent's work.
32
+
33
+ ### Task Properties
34
+
35
+ | Property | Description |
36
+ | --------------- | ----------------------------------------------------- |
37
+ | `key` | Unique task identifier |
38
+ | `prompt` | Instructions for the agent |
39
+ | `env_key` | Environment identifier (e.g., `"hubspot:v1.2"`) |
40
+ | `data_key` | Data configuration identifier |
41
+ | `env_variables` | Environment variables for the task |
42
+ | `metadata` | Additional info (e.g., `avg_steps` for task difficulty) |
43
+
44
+ ## Quick Start
45
+
46
+ ```python
47
+ import fleet
48
+
49
+ async def main():
50
+ # Load a task
51
+ tasks = await fleet.load_tasks_async(
52
+ keys=["task_abcdef"]
53
+ )
54
+ task = tasks[0]
55
+
56
+ # Create an environment from the task
57
+ env = await fleet.env.make_async(
58
+ env_key=task.env_key,
59
+ data_key=task.data_key,
60
+ env_variables=task.env_variables,
61
+ ttl_seconds=7200,
62
+ run_id="run-123",
63
+ )
64
+
65
+ # Access the environment URL
66
+ print(env.urls.app[0])
67
+
68
+ # ... interact with the environment ...
69
+
70
+ # Verify task completion
71
+ result = await task.verify_detailed_async(env.instance_id)
72
+ print(result)
73
+
74
+ # Clean up
75
+ await env.close()
76
+ ```
77
+
78
+ ## Loading Tasks
79
+
80
+ ### By Task Keys
81
+
82
+ ```python
83
+ tasks = await fleet.load_tasks_async(
84
+ keys=["task_abcdef"]
85
+ )
86
+ ```
87
+
88
+ ### By Project Key
89
+
90
+ ```python
91
+ tasks = await fleet.load_tasks_async(project_key="my-project")
92
+ ```
93
+
94
+ ## Creating Environments
95
+
96
+ ```python
97
+ env = await fleet.env.make_async(
98
+ env_key=task.env_key,
99
+ data_key=task.data_key,
100
+ env_variables=task.env_variables,
101
+ ttl_seconds=7200,
102
+ run_id="run-123",
103
+ )
104
+ ```
105
+
106
+ ### With Heartbeats (Optional)
107
+
108
+ Optionally enable heartbeats to keep environments alive during long-running operations:
109
+
110
+ ```python
111
+ env = await fleet.env.make_async(
112
+ env_key=task.env_key,
113
+ data_key=task.data_key,
114
+ env_variables=task.env_variables,
115
+ ttl_seconds=10800,
116
+ heartbeat_interval=30, # seconds
117
+ )
118
+ ```
119
+
120
+ Send heartbeats to keep the environment alive:
121
+
122
+ ```python
123
+ # Via the environment object
124
+ await env.heartbeat()
125
+
126
+ # Or via instance ID
127
+ await fleet.env.heartbeat_async(instance_id)
128
+ ```
129
+
130
+ Heartbeats are optional. If `heartbeat_interval` is not set, the instance lifetime is controlled solely by `ttl_seconds`. If heartbeats are enabled and missed 3 consecutive times, the instance will be terminated. Heartbeats take precedence over the TTL.
131
+
132
+ ## Instance Management
133
+
134
+ ### List Instances
135
+
136
+ ```python
137
+ # List all instances for a run
138
+ instances = await fleet.env.list_instances_async(run_id="run-123")
139
+
140
+ # List all instances for your profile
141
+ instances = await fleet.env.list_instances_async(profile_id="self")
142
+ ```
143
+
144
+ ### Close Instances
145
+
146
+ ```python
147
+ # Close all instances for a run
148
+ await fleet.env.close_all_async(run_id="run-123")
149
+
150
+ # Close all instances for your profile
151
+ await fleet.env.close_all_async(profile_id="self")
152
+
153
+ # Close a specific instance by ID
154
+ await fleet.env.close_async("bc8954c2")
155
+ ```
156
+
157
+ `"self"` is an alias for the profile associated with your `FLEET_API_KEY`.
158
+
159
+ ## Account Information
160
+
161
+ View your current account details including team info, instance limits, and profile ID:
162
+
163
+ ```python
164
+ account = await fleet.env.account_async()
165
+ ```
166
+
167
+ Returns:
168
+
169
+ ```json
170
+ {
171
+ "team_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
172
+ "team_name": "My Team",
173
+ "instance_limit": 32000,
174
+ "instance_count": 924,
175
+ "profile_id": "11111111-2222-3333-4444-555555555555",
176
+ "profile_name": "Jane Doe"
177
+ }
178
+ ```
179
+
180
+ ## Run Tracking
181
+
182
+ Track active and past runs:
183
+
184
+ ```python
185
+ # List active runs
186
+ runs = await fleet.env.list_runs_async()
187
+
188
+ # List all runs (active and inactive)
189
+ runs = await fleet.env.list_runs_async(status="all")
190
+
191
+ # Filter by profile
192
+ runs = await fleet.env.list_runs_async(profile_id="self")
193
+ ```
194
+
195
+ Returns:
196
+
197
+ ```json
198
+ [
199
+ {
200
+ "run_id": "run-123",
201
+ "running_count": 0,
202
+ "total_count": 4,
203
+ "first_created_at": "2025-10-24T09:48:47.152387",
204
+ "last_created_at": "2025-10-24T09:55:19.284294",
205
+ "profile_id": "11111111-2222-3333-4444-555555555555"
206
+ }
207
+ ]
208
+ ```
209
+
210
+ ## Task Verification
211
+
212
+ Verify task completion and get detailed results:
213
+
214
+ ```python
215
+ result = await task.verify_detailed_async(env.instance_id)
216
+ print(result)
217
+ ```
218
+
219
+ Returns:
220
+
221
+ ```json
222
+ {
223
+ "key": "task_abcdef",
224
+ "version": 4,
225
+ "success": true,
226
+ "result": 1.0,
227
+ "error": null,
228
+ "execution_time_ms": 2291,
229
+ "stdout": ""
230
+ }
231
+ ```
232
+
233
+ On failure, `stdout` contains detailed verification errors:
234
+
235
+ ```json
236
+ {
237
+ "key": "task_abcdef",
238
+ "version": 4,
239
+ "success": true,
240
+ "result": 0,
241
+ "error": null,
242
+ "execution_time_ms": 2291,
243
+ "stdout": "Verification errors: [\"Expected field to be 'value', got None\", \"Form not marked as complete\"]"
244
+ }
245
+ ```
246
+
247
+ ## Complete Example
248
+
249
+ ```python
250
+ import fleet
251
+ import asyncio
252
+
253
+ async def main():
254
+ # Load tasks from a project
255
+ tasks = await fleet.load_tasks_async(project_key="my-project")
256
+
257
+ for task in tasks:
258
+ # Create environment
259
+ env = await fleet.env.make_async(
260
+ env_key=task.env_key,
261
+ data_key=task.data_key,
262
+ env_variables=task.env_variables,
263
+ ttl_seconds=7200,
264
+ run_id="my-evaluation-run",
265
+ )
266
+
267
+ try:
268
+ # Access the environment URL
269
+ print(env.urls.app[0])
270
+
271
+ # ... run your agent ...
272
+
273
+ # Verify task completion
274
+ result = await task.verify_detailed_async(env.instance_id)
275
+ print(f"Task {task.key}: score={result['result']}")
276
+
277
+ finally:
278
+ await env.close()
279
+
280
+ # Clean up all instances from this run
281
+ await fleet.env.close_all_async(run_id="my-evaluation-run")
282
+
283
+ if __name__ == "__main__":
284
+ asyncio.run(main())
285
+ ```
@@ -112,7 +112,7 @@ async def main():
112
112
  print(f"Task definition:")
113
113
  print(f" Key: {task.key}")
114
114
  print(f" Prompt: {task.prompt}")
115
- print(f" Environment: {task.env_id}")
115
+ print(f" Environment: {task.env_key}")
116
116
  print(
117
117
  f" Verifier: {task.verifier.key if hasattr(task.verifier, 'key') else 'create_bug_issue'}"
118
118
  )
@@ -38,6 +38,12 @@ def main():
38
38
  help="Output JSON filename (defaults to {team_id}.json)",
39
39
  default=None,
40
40
  )
41
+ parser.add_argument(
42
+ "--skip-missing-verifiers",
43
+ "-s",
44
+ action="store_true",
45
+ help="Skip tasks missing verifier_func instead of erroring",
46
+ )
41
47
 
42
48
  args = parser.parse_args()
43
49
 
@@ -91,16 +97,32 @@ def main():
91
97
  missing_verifier.append(task.key)
92
98
 
93
99
  if missing_verifier:
94
- print(f"\n✗ Error: {len(missing_verifier)} task(s) missing verifier_func:")
95
- for key in missing_verifier[:10]: # Show first 10
96
- print(f" - {key}")
97
- if len(missing_verifier) > 10:
98
- print(f" ... and {len(missing_verifier) - 10} more")
99
- raise ValueError(
100
- "All tasks must have a verifier_func. Cannot export tasks without verifiers."
101
- )
102
-
103
- print("✓ All tasks have verifier_func")
100
+ if args.skip_missing_verifiers:
101
+ print(
102
+ f"\n⚠ Skipping {len(missing_verifier)} task(s) missing verifier_func:"
103
+ )
104
+ for key in missing_verifier[:10]: # Show first 10
105
+ print(f" - {key}")
106
+ if len(missing_verifier) > 10:
107
+ print(f" ... and {len(missing_verifier) - 10} more")
108
+ # Filter out tasks without verifiers
109
+ tasks = [task for task in tasks if task.verifier_func]
110
+ print(f"\n{len(tasks)} task(s) remaining after filtering")
111
+ if not tasks:
112
+ raise ValueError(
113
+ "No tasks remaining after filtering. Nothing to export."
114
+ )
115
+ else:
116
+ print(f"\n✗ Error: {len(missing_verifier)} task(s) missing verifier_func:")
117
+ for key in missing_verifier[:10]: # Show first 10
118
+ print(f" - {key}")
119
+ if len(missing_verifier) > 10:
120
+ print(f" ... and {len(missing_verifier) - 10} more")
121
+ raise ValueError(
122
+ "All tasks must have a verifier_func. Cannot export tasks without verifiers."
123
+ )
124
+ else:
125
+ print("✓ All tasks have verifier_func")
104
126
 
105
127
  # Determine output filename
106
128
  output_file = args.output or f"{account.team_id}.json"