fleet-python 0.2.66b2__py3-none-any.whl → 0.2.105__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.
- examples/export_tasks.py +16 -5
- examples/export_tasks_filtered.py +245 -0
- examples/fetch_tasks.py +230 -0
- examples/import_tasks.py +140 -8
- examples/iterate_verifiers.py +725 -0
- fleet/__init__.py +128 -5
- fleet/_async/__init__.py +27 -3
- fleet/_async/base.py +24 -9
- fleet/_async/client.py +938 -41
- fleet/_async/env/client.py +60 -3
- fleet/_async/instance/client.py +52 -7
- fleet/_async/models.py +15 -0
- fleet/_async/resources/api.py +200 -0
- fleet/_async/resources/sqlite.py +1801 -46
- fleet/_async/tasks.py +122 -25
- fleet/_async/verifiers/bundler.py +22 -21
- fleet/_async/verifiers/verifier.py +25 -19
- fleet/agent/__init__.py +32 -0
- fleet/agent/gemini_cua/Dockerfile +45 -0
- fleet/agent/gemini_cua/__init__.py +10 -0
- fleet/agent/gemini_cua/agent.py +759 -0
- fleet/agent/gemini_cua/mcp/main.py +108 -0
- fleet/agent/gemini_cua/mcp_server/__init__.py +5 -0
- fleet/agent/gemini_cua/mcp_server/main.py +105 -0
- fleet/agent/gemini_cua/mcp_server/tools.py +178 -0
- fleet/agent/gemini_cua/requirements.txt +5 -0
- fleet/agent/gemini_cua/start.sh +30 -0
- fleet/agent/orchestrator.py +854 -0
- fleet/agent/types.py +49 -0
- fleet/agent/utils.py +34 -0
- fleet/base.py +34 -9
- fleet/cli.py +1061 -0
- fleet/client.py +1060 -48
- fleet/config.py +1 -1
- fleet/env/__init__.py +16 -0
- fleet/env/client.py +60 -3
- fleet/eval/__init__.py +15 -0
- fleet/eval/uploader.py +231 -0
- fleet/exceptions.py +8 -0
- fleet/instance/client.py +53 -8
- fleet/instance/models.py +1 -0
- fleet/models.py +303 -0
- fleet/proxy/__init__.py +25 -0
- fleet/proxy/proxy.py +453 -0
- fleet/proxy/whitelist.py +244 -0
- fleet/resources/api.py +200 -0
- fleet/resources/sqlite.py +1845 -46
- fleet/tasks.py +113 -20
- fleet/utils/__init__.py +7 -0
- fleet/utils/http_logging.py +178 -0
- fleet/utils/logging.py +13 -0
- fleet/utils/playwright.py +440 -0
- fleet/verifiers/bundler.py +22 -21
- fleet/verifiers/db.py +985 -1
- fleet/verifiers/decorator.py +1 -1
- fleet/verifiers/verifier.py +25 -19
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/METADATA +28 -1
- fleet_python-0.2.105.dist-info/RECORD +115 -0
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/WHEEL +1 -1
- fleet_python-0.2.105.dist-info/entry_points.txt +2 -0
- tests/test_app_method.py +85 -0
- tests/test_expect_exactly.py +4148 -0
- tests/test_expect_only.py +2593 -0
- tests/test_instance_dispatch.py +607 -0
- tests/test_sqlite_resource_dual_mode.py +263 -0
- tests/test_sqlite_shared_memory_behavior.py +117 -0
- fleet_python-0.2.66b2.dist-info/RECORD +0 -81
- tests/test_verifier_security.py +0 -427
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/licenses/LICENSE +0 -0
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/top_level.txt +0 -0
fleet/resources/api.py
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""API Resource for making HTTP requests to the app's API endpoint."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional, Union
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from .base import Resource
|
|
7
|
+
from ..instance.models import Resource as ResourceModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class APIResponse:
|
|
11
|
+
"""Simple wrapper around httpx.Response with a requests-like interface."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, response: httpx.Response):
|
|
14
|
+
self._response = response
|
|
15
|
+
self.status_code: int = response.status_code
|
|
16
|
+
self.headers: httpx.Headers = response.headers
|
|
17
|
+
self.text: str = response.text
|
|
18
|
+
self.content: bytes = response.content
|
|
19
|
+
self.url: str = str(response.url)
|
|
20
|
+
self.ok: bool = response.is_success
|
|
21
|
+
|
|
22
|
+
def json(self) -> Any:
|
|
23
|
+
"""Parse response body as JSON."""
|
|
24
|
+
return self._response.json()
|
|
25
|
+
|
|
26
|
+
def raise_for_status(self) -> "APIResponse":
|
|
27
|
+
"""Raise an HTTPStatusError if the response has an error status code."""
|
|
28
|
+
self._response.raise_for_status()
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
def __repr__(self) -> str:
|
|
32
|
+
return f"<APIResponse [{self.status_code}]>"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class APIResource(Resource):
|
|
36
|
+
"""HTTP client for making requests to the app's API endpoint.
|
|
37
|
+
|
|
38
|
+
Provides a requests-like interface for interacting with the app's REST API.
|
|
39
|
+
|
|
40
|
+
Example:
|
|
41
|
+
api = env.api()
|
|
42
|
+
response = api.get("/users/1")
|
|
43
|
+
print(response.status_code) # 200
|
|
44
|
+
print(response.json()) # {"id": 1, "name": "John"}
|
|
45
|
+
|
|
46
|
+
# With headers/auth
|
|
47
|
+
response = api.post(
|
|
48
|
+
"/users",
|
|
49
|
+
json={"name": "Jane"},
|
|
50
|
+
headers={"Authorization": "Bearer xxx"}
|
|
51
|
+
)
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
resource: ResourceModel,
|
|
57
|
+
base_url: str,
|
|
58
|
+
client: Optional[httpx.Client] = None,
|
|
59
|
+
):
|
|
60
|
+
super().__init__(resource)
|
|
61
|
+
self.base_url = base_url.rstrip("/")
|
|
62
|
+
self._client = client or httpx.Client()
|
|
63
|
+
|
|
64
|
+
def _build_url(self, path: str) -> str:
|
|
65
|
+
"""Build full URL from base_url and path."""
|
|
66
|
+
if path.startswith("/"):
|
|
67
|
+
return f"{self.base_url}{path}"
|
|
68
|
+
return f"{self.base_url}/{path}"
|
|
69
|
+
|
|
70
|
+
def request(
|
|
71
|
+
self,
|
|
72
|
+
method: str,
|
|
73
|
+
path: str,
|
|
74
|
+
*,
|
|
75
|
+
params: Optional[Dict[str, Any]] = None,
|
|
76
|
+
json: Optional[Any] = None,
|
|
77
|
+
data: Optional[Dict[str, Any]] = None,
|
|
78
|
+
headers: Optional[Dict[str, str]] = None,
|
|
79
|
+
cookies: Optional[Dict[str, str]] = None,
|
|
80
|
+
timeout: Optional[float] = None,
|
|
81
|
+
**kwargs: Any,
|
|
82
|
+
) -> APIResponse:
|
|
83
|
+
"""Make an HTTP request.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
method: HTTP method (GET, POST, PUT, PATCH, DELETE, etc.)
|
|
87
|
+
path: URL path (relative to base_url)
|
|
88
|
+
params: Query parameters
|
|
89
|
+
json: JSON body (will be serialized)
|
|
90
|
+
data: Form data
|
|
91
|
+
headers: Request headers
|
|
92
|
+
cookies: Request cookies
|
|
93
|
+
timeout: Request timeout in seconds
|
|
94
|
+
**kwargs: Additional arguments passed to httpx
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
APIResponse with status_code, headers, text, content, json() method
|
|
98
|
+
"""
|
|
99
|
+
url = self._build_url(path)
|
|
100
|
+
response = self._client.request(
|
|
101
|
+
method,
|
|
102
|
+
url,
|
|
103
|
+
params=params,
|
|
104
|
+
json=json,
|
|
105
|
+
data=data,
|
|
106
|
+
headers=headers,
|
|
107
|
+
cookies=cookies,
|
|
108
|
+
timeout=timeout,
|
|
109
|
+
**kwargs,
|
|
110
|
+
)
|
|
111
|
+
return APIResponse(response)
|
|
112
|
+
|
|
113
|
+
def get(
|
|
114
|
+
self,
|
|
115
|
+
path: str,
|
|
116
|
+
*,
|
|
117
|
+
params: Optional[Dict[str, Any]] = None,
|
|
118
|
+
headers: Optional[Dict[str, str]] = None,
|
|
119
|
+
**kwargs: Any,
|
|
120
|
+
) -> APIResponse:
|
|
121
|
+
"""Make a GET request."""
|
|
122
|
+
return self.request("GET", path, params=params, headers=headers, **kwargs)
|
|
123
|
+
|
|
124
|
+
def post(
|
|
125
|
+
self,
|
|
126
|
+
path: str,
|
|
127
|
+
*,
|
|
128
|
+
json: Optional[Any] = None,
|
|
129
|
+
data: Optional[Dict[str, Any]] = None,
|
|
130
|
+
params: Optional[Dict[str, Any]] = None,
|
|
131
|
+
headers: Optional[Dict[str, str]] = None,
|
|
132
|
+
**kwargs: Any,
|
|
133
|
+
) -> APIResponse:
|
|
134
|
+
"""Make a POST request."""
|
|
135
|
+
return self.request(
|
|
136
|
+
"POST", path, json=json, data=data, params=params, headers=headers, **kwargs
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def put(
|
|
140
|
+
self,
|
|
141
|
+
path: str,
|
|
142
|
+
*,
|
|
143
|
+
json: Optional[Any] = None,
|
|
144
|
+
data: Optional[Dict[str, Any]] = None,
|
|
145
|
+
params: Optional[Dict[str, Any]] = None,
|
|
146
|
+
headers: Optional[Dict[str, str]] = None,
|
|
147
|
+
**kwargs: Any,
|
|
148
|
+
) -> APIResponse:
|
|
149
|
+
"""Make a PUT request."""
|
|
150
|
+
return self.request(
|
|
151
|
+
"PUT", path, json=json, data=data, params=params, headers=headers, **kwargs
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def patch(
|
|
155
|
+
self,
|
|
156
|
+
path: str,
|
|
157
|
+
*,
|
|
158
|
+
json: Optional[Any] = None,
|
|
159
|
+
data: Optional[Dict[str, Any]] = None,
|
|
160
|
+
params: Optional[Dict[str, Any]] = None,
|
|
161
|
+
headers: Optional[Dict[str, str]] = None,
|
|
162
|
+
**kwargs: Any,
|
|
163
|
+
) -> APIResponse:
|
|
164
|
+
"""Make a PATCH request."""
|
|
165
|
+
return self.request(
|
|
166
|
+
"PATCH", path, json=json, data=data, params=params, headers=headers, **kwargs
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def delete(
|
|
170
|
+
self,
|
|
171
|
+
path: str,
|
|
172
|
+
*,
|
|
173
|
+
params: Optional[Dict[str, Any]] = None,
|
|
174
|
+
headers: Optional[Dict[str, str]] = None,
|
|
175
|
+
**kwargs: Any,
|
|
176
|
+
) -> APIResponse:
|
|
177
|
+
"""Make a DELETE request."""
|
|
178
|
+
return self.request("DELETE", path, params=params, headers=headers, **kwargs)
|
|
179
|
+
|
|
180
|
+
def head(
|
|
181
|
+
self,
|
|
182
|
+
path: str,
|
|
183
|
+
*,
|
|
184
|
+
params: Optional[Dict[str, Any]] = None,
|
|
185
|
+
headers: Optional[Dict[str, str]] = None,
|
|
186
|
+
**kwargs: Any,
|
|
187
|
+
) -> APIResponse:
|
|
188
|
+
"""Make a HEAD request."""
|
|
189
|
+
return self.request("HEAD", path, params=params, headers=headers, **kwargs)
|
|
190
|
+
|
|
191
|
+
def options(
|
|
192
|
+
self,
|
|
193
|
+
path: str,
|
|
194
|
+
*,
|
|
195
|
+
params: Optional[Dict[str, Any]] = None,
|
|
196
|
+
headers: Optional[Dict[str, str]] = None,
|
|
197
|
+
**kwargs: Any,
|
|
198
|
+
) -> APIResponse:
|
|
199
|
+
"""Make an OPTIONS request."""
|
|
200
|
+
return self.request("OPTIONS", path, params=params, headers=headers, **kwargs)
|