fleet-python 0.2.3__tar.gz → 0.2.5__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.
- {fleet_python-0.2.3 → fleet_python-0.2.5}/PKG-INFO +12 -11
- {fleet_python-0.2.3 → fleet_python-0.2.5}/README.md +10 -10
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/dsl_example.py +2 -1
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/example.py +2 -2
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/json_tasks_example.py +1 -1
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/nova_act_example.py +1 -1
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/openai_example.py +17 -24
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/openai_simple_example.py +11 -12
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet/__init__.py +18 -3
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/base.py +1 -24
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/client.py +5 -73
- fleet_python-0.2.5/fleet/_async/env/__init__.py +0 -0
- fleet_python-0.2.5/fleet/_async/env/client.py +15 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/instance/__init__.py +1 -2
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/instance/base.py +1 -24
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/instance/client.py +4 -21
- fleet_python-0.2.5/fleet/_async/resources/__init__.py +0 -0
- fleet_python-0.2.5/fleet/base.py +51 -0
- fleet_python-0.2.5/fleet/client.py +133 -0
- fleet_python-0.2.5/fleet/env/__init__.py +15 -0
- fleet_python-0.2.5/fleet/env/client.py +15 -0
- fleet_python-0.2.5/fleet/exceptions.py +73 -0
- fleet_python-0.2.5/fleet/instance/__init__.py +26 -0
- fleet_python-0.2.5/fleet/instance/base.py +37 -0
- fleet_python-0.2.5/fleet/instance/client.py +278 -0
- fleet_python-0.2.5/fleet/instance/models.py +141 -0
- fleet_python-0.2.5/fleet/models.py +109 -0
- fleet_python-0.2.5/fleet/playwright.py +289 -0
- fleet_python-0.2.5/fleet/resources/__init__.py +0 -0
- fleet_python-0.2.5/fleet/resources/base.py +26 -0
- fleet_python-0.2.5/fleet/resources/browser.py +41 -0
- fleet_python-0.2.5/fleet/resources/sqlite.py +41 -0
- fleet_python-0.2.5/fleet/verifiers/__init__.py +11 -0
- fleet_python-0.2.5/fleet/verifiers/code.py +1 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet_python.egg-info/PKG-INFO +12 -11
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet_python.egg-info/SOURCES.txt +18 -1
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet_python.egg-info/requires.txt +1 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/pyproject.toml +23 -2
- fleet_python-0.2.5/scripts/unasync.py +28 -0
- fleet_python-0.2.3/fleet/env/__init__.py +0 -3
- fleet_python-0.2.3/fleet/env/client.py +0 -15
- fleet_python-0.2.3/fleet/verifiers/__init__.py +0 -16
- fleet_python-0.2.3/fleet/verifiers/code.py +0 -132
- {fleet_python-0.2.3 → fleet_python-0.2.5}/LICENSE +0 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/examples/quickstart.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/exceptions.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/instance/models.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/models.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/playwright.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/resources/base.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/resources/browser.py +0 -0
- {fleet_python-0.2.3/fleet → fleet_python-0.2.5/fleet/_async}/resources/sqlite.py +0 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet/verifiers/db.py +0 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet/verifiers/sql_differ.py +0 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet_python.egg-info/dependency_links.txt +0 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/fleet_python.egg-info/top_level.txt +0 -0
- {fleet_python-0.2.3 → fleet_python-0.2.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fleet-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Python SDK for Fleet environments
|
|
5
5
|
Author-email: Fleet AI <nic@fleet.so>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -31,6 +31,7 @@ Requires-Dist: black>=22.0.0; extra == "dev"
|
|
|
31
31
|
Requires-Dist: isort>=5.0.0; extra == "dev"
|
|
32
32
|
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
33
33
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
34
|
+
Requires-Dist: unasync>=0.6.0; extra == "dev"
|
|
34
35
|
Provides-Extra: playwright
|
|
35
36
|
Requires-Dist: playwright>=1.40.0; extra == "playwright"
|
|
36
37
|
Dynamic: license-file
|
|
@@ -63,20 +64,20 @@ export FLEET_API_KEY="sk_your_key_here"
|
|
|
63
64
|
import fleet as flt
|
|
64
65
|
|
|
65
66
|
# Create environment by key
|
|
66
|
-
env =
|
|
67
|
+
env = flt.env.make("fira")
|
|
67
68
|
|
|
68
69
|
# Reset environment with seed and options
|
|
69
|
-
|
|
70
|
+
env.reset(
|
|
70
71
|
seed=42,
|
|
71
72
|
timestamp=datetime.now()
|
|
72
73
|
)
|
|
73
74
|
|
|
74
75
|
# Access environment state ('crm' is the resource id for a sqlite database)
|
|
75
76
|
sql = env.state("sqlite://crm")
|
|
76
|
-
|
|
77
|
+
sql.exec("UPDATE customers SET status = 'active' WHERE id = 123")
|
|
77
78
|
|
|
78
79
|
# Clean up
|
|
79
|
-
|
|
80
|
+
env.close()
|
|
80
81
|
```
|
|
81
82
|
|
|
82
83
|
## Environment Management
|
|
@@ -85,10 +86,10 @@ await env.close()
|
|
|
85
86
|
|
|
86
87
|
```python
|
|
87
88
|
# Create environment instance with explicit version
|
|
88
|
-
env =
|
|
89
|
+
env = flt.env.make("fira:v1.2.5")
|
|
89
90
|
|
|
90
91
|
# Create environment instance with default (latest) version
|
|
91
|
-
env =
|
|
92
|
+
env = flt.env.make("fira")
|
|
92
93
|
|
|
93
94
|
```
|
|
94
95
|
|
|
@@ -96,18 +97,18 @@ env = await flt.env.make("fira")
|
|
|
96
97
|
|
|
97
98
|
```python
|
|
98
99
|
# Connect to a running instance
|
|
99
|
-
env =
|
|
100
|
+
env = flt.env.get("env_instance_id")
|
|
100
101
|
|
|
101
102
|
# List all running instances
|
|
102
|
-
instances =
|
|
103
|
+
instances = flt.env.list_instances()
|
|
103
104
|
for instance in instances:
|
|
104
105
|
print(f"Instance: {instance.instance_id}")
|
|
105
106
|
print(f"Type: {instance.environment_type}")
|
|
106
107
|
print(f"Status: {instance.status}")
|
|
107
108
|
|
|
108
109
|
# Filter instances by status (running, pending, stopped, error)
|
|
109
|
-
running_instances =
|
|
110
|
+
running_instances = flt.env.list_instances(status_filter="running")
|
|
110
111
|
|
|
111
112
|
# List available environment types
|
|
112
|
-
available_envs =
|
|
113
|
+
available_envs = flt.env.list_envs()
|
|
113
114
|
```
|
|
@@ -26,20 +26,20 @@ export FLEET_API_KEY="sk_your_key_here"
|
|
|
26
26
|
import fleet as flt
|
|
27
27
|
|
|
28
28
|
# Create environment by key
|
|
29
|
-
env =
|
|
29
|
+
env = flt.env.make("fira")
|
|
30
30
|
|
|
31
31
|
# Reset environment with seed and options
|
|
32
|
-
|
|
32
|
+
env.reset(
|
|
33
33
|
seed=42,
|
|
34
34
|
timestamp=datetime.now()
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
# Access environment state ('crm' is the resource id for a sqlite database)
|
|
38
38
|
sql = env.state("sqlite://crm")
|
|
39
|
-
|
|
39
|
+
sql.exec("UPDATE customers SET status = 'active' WHERE id = 123")
|
|
40
40
|
|
|
41
41
|
# Clean up
|
|
42
|
-
|
|
42
|
+
env.close()
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
## Environment Management
|
|
@@ -48,10 +48,10 @@ await env.close()
|
|
|
48
48
|
|
|
49
49
|
```python
|
|
50
50
|
# Create environment instance with explicit version
|
|
51
|
-
env =
|
|
51
|
+
env = flt.env.make("fira:v1.2.5")
|
|
52
52
|
|
|
53
53
|
# Create environment instance with default (latest) version
|
|
54
|
-
env =
|
|
54
|
+
env = flt.env.make("fira")
|
|
55
55
|
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -59,18 +59,18 @@ env = await flt.env.make("fira")
|
|
|
59
59
|
|
|
60
60
|
```python
|
|
61
61
|
# Connect to a running instance
|
|
62
|
-
env =
|
|
62
|
+
env = flt.env.get("env_instance_id")
|
|
63
63
|
|
|
64
64
|
# List all running instances
|
|
65
|
-
instances =
|
|
65
|
+
instances = flt.env.list_instances()
|
|
66
66
|
for instance in instances:
|
|
67
67
|
print(f"Instance: {instance.instance_id}")
|
|
68
68
|
print(f"Type: {instance.environment_type}")
|
|
69
69
|
print(f"Status: {instance.status}")
|
|
70
70
|
|
|
71
71
|
# Filter instances by status (running, pending, stopped, error)
|
|
72
|
-
running_instances =
|
|
72
|
+
running_instances = flt.env.list_instances(status_filter="running")
|
|
73
73
|
|
|
74
74
|
# List available environment types
|
|
75
|
-
available_envs =
|
|
75
|
+
available_envs = flt.env.list_envs()
|
|
76
76
|
```
|
|
@@ -65,7 +65,7 @@ def validate_new_deal_creation(
|
|
|
65
65
|
async def main():
|
|
66
66
|
# Create a new instance
|
|
67
67
|
print("Creating new Hubspot instance...")
|
|
68
|
-
env = await flt.env.
|
|
68
|
+
env = await flt.env.make_async("hubspot:v1.2.7")
|
|
69
69
|
print(f"New Instance: {env.instance_id}")
|
|
70
70
|
|
|
71
71
|
try:
|
|
@@ -99,6 +99,7 @@ async def main():
|
|
|
99
99
|
)
|
|
100
100
|
"""
|
|
101
101
|
|
|
102
|
+
print("RESOURCES", await env.resources())
|
|
102
103
|
db = env.db()
|
|
103
104
|
insert_result = await db.exec(insert_query)
|
|
104
105
|
print(f"Insert result: {insert_result}")
|
|
@@ -6,11 +6,11 @@ import fleet as flt
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
async def main():
|
|
9
|
-
environments = await flt.env.
|
|
9
|
+
environments = await flt.env.list_envs_async()
|
|
10
10
|
print("Environments:", len(environments))
|
|
11
11
|
|
|
12
12
|
# Create a new instance
|
|
13
|
-
env = await flt.env.
|
|
13
|
+
env = await flt.env.make_async("hubspot:v1.2.7")
|
|
14
14
|
print("New Instance:", env.instance_id)
|
|
15
15
|
|
|
16
16
|
response = await env.reset(seed=42)
|
|
@@ -39,7 +39,7 @@ async def main():
|
|
|
39
39
|
if not file_path.exists():
|
|
40
40
|
raise FileNotFoundError(f"Error: File '{args.json_file}' not found")
|
|
41
41
|
|
|
42
|
-
env = await flt.env.
|
|
42
|
+
env = await flt.env.make_async("fira:v1.2.7")
|
|
43
43
|
print(f"New Instance: {env.urls.app}")
|
|
44
44
|
|
|
45
45
|
successes = 0
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
from openai import AsyncOpenAI
|
|
1
|
+
from openai import OpenAI
|
|
3
2
|
import fleet as flt
|
|
4
3
|
import json
|
|
5
4
|
from typing import Callable
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
client =
|
|
7
|
+
client = OpenAI()
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
def sanitize_message(msg: dict) -> dict:
|
|
@@ -50,7 +49,7 @@ class Agent:
|
|
|
50
49
|
if self.debug:
|
|
51
50
|
print(*args)
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
def handle_item(self, item):
|
|
54
53
|
"""Handle each item; may cause a computer action + screenshot."""
|
|
55
54
|
if self.debug:
|
|
56
55
|
print(f"Handling item of type: {item.get('type')}")
|
|
@@ -66,7 +65,7 @@ class Agent:
|
|
|
66
65
|
|
|
67
66
|
if hasattr(self.computer, name): # if function exists on computer, call it
|
|
68
67
|
method = getattr(self.computer, name)
|
|
69
|
-
|
|
68
|
+
method(**args)
|
|
70
69
|
return [
|
|
71
70
|
{
|
|
72
71
|
"type": "function_call_output",
|
|
@@ -83,9 +82,9 @@ class Agent:
|
|
|
83
82
|
print(f"{action_type}({action_args})")
|
|
84
83
|
|
|
85
84
|
method = getattr(self.computer, action_type)
|
|
86
|
-
|
|
85
|
+
method(**action_args)
|
|
87
86
|
|
|
88
|
-
screenshot_base64 =
|
|
87
|
+
screenshot_base64 = self.computer.screenshot()
|
|
89
88
|
|
|
90
89
|
# if user doesn't ack all safety checks exit with error
|
|
91
90
|
pending_checks = item.get("pending_safety_checks", [])
|
|
@@ -114,7 +113,7 @@ class Agent:
|
|
|
114
113
|
return [call_output]
|
|
115
114
|
return []
|
|
116
115
|
|
|
117
|
-
|
|
116
|
+
def run_full_turn(
|
|
118
117
|
self, input_items, print_steps=True, debug=False, show_images=False
|
|
119
118
|
):
|
|
120
119
|
self.print_steps = print_steps
|
|
@@ -134,7 +133,7 @@ class Agent:
|
|
|
134
133
|
|
|
135
134
|
clean_input = [_clean_item(m) for m in (input_items + new_items)]
|
|
136
135
|
|
|
137
|
-
response =
|
|
136
|
+
response = client.responses.create(
|
|
138
137
|
model=self.model,
|
|
139
138
|
input=clean_input,
|
|
140
139
|
tools=self.tools,
|
|
@@ -173,7 +172,7 @@ class Agent:
|
|
|
173
172
|
new_items.append(item)
|
|
174
173
|
|
|
175
174
|
# Next, perform any local side-effects (browser actions, etc.).
|
|
176
|
-
handled_items =
|
|
175
|
+
handled_items = self.handle_item(item)
|
|
177
176
|
|
|
178
177
|
# If the handler generated additional items (e.g. computer_call_output)
|
|
179
178
|
# we append those *immediately* so the order remains:
|
|
@@ -187,19 +186,13 @@ class Agent:
|
|
|
187
186
|
tools = []
|
|
188
187
|
|
|
189
188
|
|
|
190
|
-
|
|
191
|
-
"""Async version of input()"""
|
|
192
|
-
loop = asyncio.get_event_loop()
|
|
193
|
-
return await loop.run_in_executor(None, input, prompt)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
async def main():
|
|
189
|
+
def main():
|
|
197
190
|
# Create a Fleet environment instance
|
|
198
|
-
instance =
|
|
191
|
+
instance = flt.env.make("hubspot")
|
|
199
192
|
|
|
200
193
|
# Create the Playwright wrapper
|
|
201
194
|
browser = flt.FleetPlaywrightWrapper(instance)
|
|
202
|
-
|
|
195
|
+
browser.start()
|
|
203
196
|
|
|
204
197
|
try:
|
|
205
198
|
agent = Agent(browser, model="computer-use-preview", tools=[])
|
|
@@ -212,9 +205,9 @@ async def main():
|
|
|
212
205
|
|
|
213
206
|
while True:
|
|
214
207
|
try:
|
|
215
|
-
user_input =
|
|
208
|
+
user_input = input("> ")
|
|
216
209
|
items.append({"role": "user", "content": user_input})
|
|
217
|
-
output_items =
|
|
210
|
+
output_items = agent.run_full_turn(
|
|
218
211
|
items, show_images=False, debug=False
|
|
219
212
|
)
|
|
220
213
|
items += output_items
|
|
@@ -225,9 +218,9 @@ async def main():
|
|
|
225
218
|
print(f"Error during interaction: {e}")
|
|
226
219
|
# Continue the loop for other errors
|
|
227
220
|
finally:
|
|
228
|
-
|
|
229
|
-
|
|
221
|
+
browser.close()
|
|
222
|
+
instance.close()
|
|
230
223
|
|
|
231
224
|
|
|
232
225
|
if __name__ == "__main__":
|
|
233
|
-
|
|
226
|
+
main()
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
from openai import AsyncOpenAI
|
|
1
|
+
from openai import OpenAI
|
|
3
2
|
import fleet as flt
|
|
4
3
|
|
|
5
|
-
client =
|
|
4
|
+
client = OpenAI()
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
instance =
|
|
7
|
+
def main():
|
|
8
|
+
instance = flt.env.make("hubspot")
|
|
10
9
|
|
|
11
10
|
browser = flt.FleetPlaywrightWrapper(instance)
|
|
12
|
-
|
|
11
|
+
browser.start()
|
|
13
12
|
|
|
14
13
|
try:
|
|
15
14
|
width, height = browser.get_dimensions()
|
|
@@ -22,7 +21,7 @@ async def main():
|
|
|
22
21
|
}
|
|
23
22
|
]
|
|
24
23
|
|
|
25
|
-
response =
|
|
24
|
+
response = client.responses.create(
|
|
26
25
|
model="computer-use-preview",
|
|
27
26
|
input=[
|
|
28
27
|
{
|
|
@@ -41,21 +40,21 @@ async def main():
|
|
|
41
40
|
if response.output[0].type == "computer_call":
|
|
42
41
|
action = response.output[0].action
|
|
43
42
|
if action.type == "screenshot":
|
|
44
|
-
screenshot_base64 =
|
|
43
|
+
screenshot_base64 = browser.screenshot()
|
|
45
44
|
result = {
|
|
46
45
|
"type": "input_image",
|
|
47
46
|
"image_url": f"data:image/png;base64,{screenshot_base64}",
|
|
48
47
|
"current_url": browser.get_current_url(),
|
|
49
48
|
}
|
|
50
49
|
else:
|
|
51
|
-
result =
|
|
50
|
+
result = browser.execute_computer_action(action)
|
|
52
51
|
|
|
53
52
|
print("Computer action result:")
|
|
54
53
|
print(result)
|
|
55
54
|
finally:
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
browser.close()
|
|
56
|
+
instance.close()
|
|
58
57
|
|
|
59
58
|
|
|
60
59
|
if __name__ == "__main__":
|
|
61
|
-
|
|
60
|
+
main()
|
|
@@ -20,8 +20,11 @@ from .exceptions import (
|
|
|
20
20
|
FleetTimeoutError,
|
|
21
21
|
FleetConfigurationError,
|
|
22
22
|
)
|
|
23
|
-
from .client import Fleet,
|
|
23
|
+
from .client import Fleet, Environment
|
|
24
|
+
from ._async.client import AsyncFleet, AsyncEnvironment
|
|
25
|
+
from .models import InstanceRequest
|
|
24
26
|
from .instance import (
|
|
27
|
+
InstanceClient,
|
|
25
28
|
AsyncInstanceClient,
|
|
26
29
|
ResetRequest,
|
|
27
30
|
ResetResponse,
|
|
@@ -30,7 +33,12 @@ from .instance import (
|
|
|
30
33
|
ChromeStartResponse,
|
|
31
34
|
ChromeStatusResponse,
|
|
32
35
|
)
|
|
33
|
-
from .verifiers import
|
|
36
|
+
from .verifiers import (
|
|
37
|
+
DatabaseSnapshot,
|
|
38
|
+
IgnoreConfig,
|
|
39
|
+
SnapshotDiff,
|
|
40
|
+
TASK_SUCCESSFUL_SCORE,
|
|
41
|
+
)
|
|
34
42
|
from . import env
|
|
35
43
|
|
|
36
44
|
# Optional playwright integration
|
|
@@ -49,7 +57,10 @@ __all__ = [
|
|
|
49
57
|
"FleetTimeoutError",
|
|
50
58
|
"FleetConfigurationError",
|
|
51
59
|
"Fleet",
|
|
60
|
+
"Environment",
|
|
52
61
|
"AsyncFleet",
|
|
62
|
+
"AsyncEnvironment",
|
|
63
|
+
"InstanceClient",
|
|
53
64
|
"AsyncInstanceClient",
|
|
54
65
|
"InstanceRequest",
|
|
55
66
|
"ResetRequest",
|
|
@@ -58,8 +69,12 @@ __all__ = [
|
|
|
58
69
|
"ChromeStartRequest",
|
|
59
70
|
"ChromeStartResponse",
|
|
60
71
|
"ChromeStatusResponse",
|
|
72
|
+
"DatabaseSnapshot",
|
|
73
|
+
"IgnoreConfig",
|
|
74
|
+
"SnapshotDiff",
|
|
75
|
+
"TASK_SUCCESSFUL_SCORE",
|
|
61
76
|
]
|
|
62
77
|
|
|
63
78
|
# Add playwright wrapper to exports if available
|
|
64
79
|
if _PLAYWRIGHT_AVAILABLE:
|
|
65
|
-
__all__.append("FleetPlaywrightWrapper")
|
|
80
|
+
__all__.append("FleetPlaywrightWrapper")
|
|
@@ -28,29 +28,6 @@ class BaseWrapper:
|
|
|
28
28
|
return headers
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class SyncWrapper(BaseWrapper):
|
|
32
|
-
def __init__(self, *, httpx_client: httpx.Client, **kwargs):
|
|
33
|
-
super().__init__(**kwargs)
|
|
34
|
-
self.httpx_client = httpx_client
|
|
35
|
-
|
|
36
|
-
def request(
|
|
37
|
-
self,
|
|
38
|
-
method: str,
|
|
39
|
-
url: str,
|
|
40
|
-
params: Optional[Dict[str, Any]] = None,
|
|
41
|
-
json: Optional[Any] = None,
|
|
42
|
-
**kwargs,
|
|
43
|
-
) -> httpx.Response:
|
|
44
|
-
return self.httpx_client.request(
|
|
45
|
-
method,
|
|
46
|
-
f"{self.base_url}{url}",
|
|
47
|
-
headers=self.get_headers(),
|
|
48
|
-
params=params,
|
|
49
|
-
json=json,
|
|
50
|
-
**kwargs,
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
31
|
class AsyncWrapper(BaseWrapper):
|
|
55
32
|
def __init__(self, *, httpx_client: httpx.AsyncClient, **kwargs):
|
|
56
33
|
super().__init__(**kwargs)
|
|
@@ -71,4 +48,4 @@ class AsyncWrapper(BaseWrapper):
|
|
|
71
48
|
params=params,
|
|
72
49
|
json=json,
|
|
73
50
|
**kwargs,
|
|
74
|
-
)
|
|
51
|
+
)
|
|
@@ -14,17 +14,15 @@
|
|
|
14
14
|
|
|
15
15
|
"""Fleet API Client for making HTTP requests to Fleet services."""
|
|
16
16
|
|
|
17
|
-
import asyncio
|
|
18
17
|
import os
|
|
19
18
|
import httpx
|
|
20
19
|
import logging
|
|
21
20
|
from typing import Optional, List
|
|
22
21
|
|
|
23
|
-
from .base import EnvironmentBase, AsyncWrapper
|
|
22
|
+
from .base import EnvironmentBase, AsyncWrapper
|
|
24
23
|
from .models import InstanceRequest, InstanceRecord, Environment as EnvironmentModel
|
|
25
24
|
|
|
26
25
|
from .instance import (
|
|
27
|
-
InstanceClient,
|
|
28
26
|
AsyncInstanceClient,
|
|
29
27
|
ResetRequest,
|
|
30
28
|
ResetResponse,
|
|
@@ -38,19 +36,6 @@ from .resources.browser import AsyncBrowserResource
|
|
|
38
36
|
logger = logging.getLogger(__name__)
|
|
39
37
|
|
|
40
38
|
|
|
41
|
-
class Environment(EnvironmentBase):
|
|
42
|
-
def __init__(self, httpx_client: Optional[httpx.Client] = None, **kwargs):
|
|
43
|
-
super().__init__(**kwargs)
|
|
44
|
-
self._httpx_client = httpx_client or httpx.Client()
|
|
45
|
-
self._instance: Optional[InstanceClient] = None
|
|
46
|
-
|
|
47
|
-
@property
|
|
48
|
-
def instance(self) -> InstanceClient:
|
|
49
|
-
if self._instance is None:
|
|
50
|
-
self._instance = InstanceClient(self.manager_url, self._httpx_client)
|
|
51
|
-
return self._instance
|
|
52
|
-
|
|
53
|
-
|
|
54
39
|
class AsyncEnvironment(EnvironmentBase):
|
|
55
40
|
def __init__(self, httpx_client: Optional[httpx.AsyncClient] = None, **kwargs):
|
|
56
41
|
super().__init__(**kwargs)
|
|
@@ -92,51 +77,6 @@ class AsyncEnvironment(EnvironmentBase):
|
|
|
92
77
|
return await self.instance.verify_raw(function_code, function_name)
|
|
93
78
|
|
|
94
79
|
|
|
95
|
-
class Fleet:
|
|
96
|
-
def __init__(
|
|
97
|
-
self,
|
|
98
|
-
api_key: Optional[str] = os.getenv("FLEET_API_KEY"),
|
|
99
|
-
base_url: Optional[str] = None,
|
|
100
|
-
httpx_client: Optional[httpx.Client] = None,
|
|
101
|
-
):
|
|
102
|
-
self._httpx_client = httpx_client or httpx.Client(timeout=60.0)
|
|
103
|
-
self.client = SyncWrapper(
|
|
104
|
-
api_key=api_key,
|
|
105
|
-
base_url=base_url,
|
|
106
|
-
httpx_client=self._httpx_client,
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
def environments(self) -> List[EnvironmentModel]:
|
|
110
|
-
response = self.client.request("GET", "/v1/env/")
|
|
111
|
-
return [EnvironmentModel(**env_data) for env_data in response.json()]
|
|
112
|
-
|
|
113
|
-
def environment(self, env_key: str) -> EnvironmentModel:
|
|
114
|
-
response = self.client.request("GET", f"/v1/env/{env_key}")
|
|
115
|
-
return EnvironmentModel(**response.json())
|
|
116
|
-
|
|
117
|
-
def make(self, request: InstanceRequest) -> Environment:
|
|
118
|
-
response = self.client.request(
|
|
119
|
-
"POST", "/v1/env/instances", json=request.model_dump()
|
|
120
|
-
)
|
|
121
|
-
return Environment(**response.json())
|
|
122
|
-
|
|
123
|
-
def instances(self, status: Optional[str] = None) -> List[Environment]:
|
|
124
|
-
params = {}
|
|
125
|
-
if status:
|
|
126
|
-
params["status"] = status
|
|
127
|
-
|
|
128
|
-
response = self.client.request("GET", "/v1/env/instances", params=params)
|
|
129
|
-
return [Environment(**instance_data) for instance_data in response.json()]
|
|
130
|
-
|
|
131
|
-
def instance(self, instance_id: str) -> Environment:
|
|
132
|
-
response = self.client.request("GET", f"/v1/env/instances/{instance_id}")
|
|
133
|
-
return Environment(**response.json())
|
|
134
|
-
|
|
135
|
-
def delete(self, instance_id: str) -> InstanceRecord:
|
|
136
|
-
response = self.client.request("DELETE", f"/v1/env/instances/{instance_id}")
|
|
137
|
-
return InstanceRecord(**response.json())
|
|
138
|
-
|
|
139
|
-
|
|
140
80
|
class AsyncFleet:
|
|
141
81
|
def __init__(
|
|
142
82
|
self,
|
|
@@ -182,20 +122,12 @@ class AsyncFleet:
|
|
|
182
122
|
params["status"] = status
|
|
183
123
|
|
|
184
124
|
response = await self.client.request("GET", "/v1/env/instances", params=params)
|
|
185
|
-
|
|
186
|
-
AsyncEnvironment(**instance_data) for instance_data in response.json()
|
|
187
|
-
]
|
|
188
|
-
await asyncio.gather(*[instance.instance.load() for instance in instances])
|
|
189
|
-
return instances
|
|
125
|
+
return [AsyncEnvironment(**instance_data) for instance_data in response.json()]
|
|
190
126
|
|
|
191
127
|
async def instance(self, instance_id: str) -> AsyncEnvironment:
|
|
192
128
|
response = await self.client.request("GET", f"/v1/env/instances/{instance_id}")
|
|
193
|
-
|
|
194
|
-
await instance.instance.load()
|
|
195
|
-
return instance
|
|
129
|
+
return AsyncEnvironment(**response.json())
|
|
196
130
|
|
|
197
131
|
async def delete(self, instance_id: str) -> InstanceRecord:
|
|
198
|
-
response = await self.client.request(
|
|
199
|
-
|
|
200
|
-
)
|
|
201
|
-
return InstanceRecord(**response.json())
|
|
132
|
+
response = await self.client.request("DELETE", f"/v1/env/instances/{instance_id}")
|
|
133
|
+
return InstanceRecord(**response.json())
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from ..client import AsyncFleet, AsyncEnvironment
|
|
2
|
+
from ..models import Environment as EnvironmentModel
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def make_async(env_key: str) -> AsyncEnvironment:
|
|
7
|
+
return await AsyncFleet().make(env_key)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def list_envs_async() -> List[EnvironmentModel]:
|
|
11
|
+
return await AsyncFleet().list_envs()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def get_async(instance_id: str) -> AsyncEnvironment:
|
|
15
|
+
return await AsyncFleet().instance(instance_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Fleet SDK Environment Module."""
|
|
2
2
|
|
|
3
|
-
from .client import
|
|
3
|
+
from .client import AsyncInstanceClient, ValidatorType
|
|
4
4
|
from .models import (
|
|
5
5
|
ResetRequest,
|
|
6
6
|
ResetResponse,
|
|
@@ -13,7 +13,6 @@ from .models import (
|
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
15
|
"ValidatorType",
|
|
16
|
-
"InstanceClient",
|
|
17
16
|
"AsyncInstanceClient",
|
|
18
17
|
"ResetRequest",
|
|
19
18
|
"ResetResponse",
|
|
@@ -14,29 +14,6 @@ class BaseWrapper:
|
|
|
14
14
|
return headers
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class SyncWrapper(BaseWrapper):
|
|
18
|
-
def __init__(self, *, httpx_client: httpx.Client, **kwargs):
|
|
19
|
-
super().__init__(**kwargs)
|
|
20
|
-
self.httpx_client = httpx_client
|
|
21
|
-
|
|
22
|
-
def request(
|
|
23
|
-
self,
|
|
24
|
-
method: str,
|
|
25
|
-
path: str,
|
|
26
|
-
params: Optional[Dict[str, Any]] = None,
|
|
27
|
-
json: Optional[Any] = None,
|
|
28
|
-
**kwargs,
|
|
29
|
-
) -> httpx.Response:
|
|
30
|
-
return self.httpx_client.request(
|
|
31
|
-
method,
|
|
32
|
-
f"{self.url}{path}",
|
|
33
|
-
headers=self.get_headers(),
|
|
34
|
-
params=params,
|
|
35
|
-
json=json,
|
|
36
|
-
**kwargs,
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
17
|
class AsyncWrapper(BaseWrapper):
|
|
41
18
|
def __init__(self, *, httpx_client: httpx.AsyncClient, **kwargs):
|
|
42
19
|
super().__init__(**kwargs)
|
|
@@ -57,4 +34,4 @@ class AsyncWrapper(BaseWrapper):
|
|
|
57
34
|
params=params,
|
|
58
35
|
json=json,
|
|
59
36
|
**kwargs,
|
|
60
|
-
)
|
|
37
|
+
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Fleet SDK
|
|
1
|
+
"""Fleet SDK Async Instance Client."""
|
|
2
2
|
|
|
3
3
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
4
4
|
import asyncio
|
|
@@ -12,11 +12,11 @@ from ..resources.sqlite import AsyncSQLiteResource
|
|
|
12
12
|
from ..resources.browser import AsyncBrowserResource
|
|
13
13
|
from ..resources.base import Resource
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from ...verifiers import DatabaseSnapshot
|
|
16
16
|
|
|
17
17
|
from ..exceptions import FleetEnvironmentError, FleetAPIError
|
|
18
18
|
|
|
19
|
-
from .base import
|
|
19
|
+
from .base import AsyncWrapper
|
|
20
20
|
from .models import (
|
|
21
21
|
ResetRequest,
|
|
22
22
|
ResetResponse,
|
|
@@ -42,23 +42,6 @@ ValidatorType = Callable[
|
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
class InstanceClient:
|
|
46
|
-
def __init__(
|
|
47
|
-
self,
|
|
48
|
-
url: str,
|
|
49
|
-
httpx_client: Optional[httpx.Client] = None,
|
|
50
|
-
):
|
|
51
|
-
self.base_url = url
|
|
52
|
-
self.client = SyncWrapper(
|
|
53
|
-
url=self.base_url, httpx_client=httpx_client or httpx.Client()
|
|
54
|
-
)
|
|
55
|
-
raise NotImplementedError("SyncManager is not implemented")
|
|
56
|
-
|
|
57
|
-
def reset(self) -> ResetResponse:
|
|
58
|
-
response = self.client.request("POST", "/reset")
|
|
59
|
-
return ResetResponse(**response.json())
|
|
60
|
-
|
|
61
|
-
|
|
62
45
|
class AsyncInstanceClient:
|
|
63
46
|
def __init__(
|
|
64
47
|
self,
|
|
@@ -292,4 +275,4 @@ class AsyncInstanceClient:
|
|
|
292
275
|
|
|
293
276
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
294
277
|
"""Async context manager exit."""
|
|
295
|
-
await self.close()
|
|
278
|
+
await self.close()
|