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.
Files changed (70) hide show
  1. examples/export_tasks.py +16 -5
  2. examples/export_tasks_filtered.py +245 -0
  3. examples/fetch_tasks.py +230 -0
  4. examples/import_tasks.py +140 -8
  5. examples/iterate_verifiers.py +725 -0
  6. fleet/__init__.py +128 -5
  7. fleet/_async/__init__.py +27 -3
  8. fleet/_async/base.py +24 -9
  9. fleet/_async/client.py +938 -41
  10. fleet/_async/env/client.py +60 -3
  11. fleet/_async/instance/client.py +52 -7
  12. fleet/_async/models.py +15 -0
  13. fleet/_async/resources/api.py +200 -0
  14. fleet/_async/resources/sqlite.py +1801 -46
  15. fleet/_async/tasks.py +122 -25
  16. fleet/_async/verifiers/bundler.py +22 -21
  17. fleet/_async/verifiers/verifier.py +25 -19
  18. fleet/agent/__init__.py +32 -0
  19. fleet/agent/gemini_cua/Dockerfile +45 -0
  20. fleet/agent/gemini_cua/__init__.py +10 -0
  21. fleet/agent/gemini_cua/agent.py +759 -0
  22. fleet/agent/gemini_cua/mcp/main.py +108 -0
  23. fleet/agent/gemini_cua/mcp_server/__init__.py +5 -0
  24. fleet/agent/gemini_cua/mcp_server/main.py +105 -0
  25. fleet/agent/gemini_cua/mcp_server/tools.py +178 -0
  26. fleet/agent/gemini_cua/requirements.txt +5 -0
  27. fleet/agent/gemini_cua/start.sh +30 -0
  28. fleet/agent/orchestrator.py +854 -0
  29. fleet/agent/types.py +49 -0
  30. fleet/agent/utils.py +34 -0
  31. fleet/base.py +34 -9
  32. fleet/cli.py +1061 -0
  33. fleet/client.py +1060 -48
  34. fleet/config.py +1 -1
  35. fleet/env/__init__.py +16 -0
  36. fleet/env/client.py +60 -3
  37. fleet/eval/__init__.py +15 -0
  38. fleet/eval/uploader.py +231 -0
  39. fleet/exceptions.py +8 -0
  40. fleet/instance/client.py +53 -8
  41. fleet/instance/models.py +1 -0
  42. fleet/models.py +303 -0
  43. fleet/proxy/__init__.py +25 -0
  44. fleet/proxy/proxy.py +453 -0
  45. fleet/proxy/whitelist.py +244 -0
  46. fleet/resources/api.py +200 -0
  47. fleet/resources/sqlite.py +1845 -46
  48. fleet/tasks.py +113 -20
  49. fleet/utils/__init__.py +7 -0
  50. fleet/utils/http_logging.py +178 -0
  51. fleet/utils/logging.py +13 -0
  52. fleet/utils/playwright.py +440 -0
  53. fleet/verifiers/bundler.py +22 -21
  54. fleet/verifiers/db.py +985 -1
  55. fleet/verifiers/decorator.py +1 -1
  56. fleet/verifiers/verifier.py +25 -19
  57. {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/METADATA +28 -1
  58. fleet_python-0.2.105.dist-info/RECORD +115 -0
  59. {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/WHEEL +1 -1
  60. fleet_python-0.2.105.dist-info/entry_points.txt +2 -0
  61. tests/test_app_method.py +85 -0
  62. tests/test_expect_exactly.py +4148 -0
  63. tests/test_expect_only.py +2593 -0
  64. tests/test_instance_dispatch.py +607 -0
  65. tests/test_sqlite_resource_dual_mode.py +263 -0
  66. tests/test_sqlite_shared_memory_behavior.py +117 -0
  67. fleet_python-0.2.66b2.dist-info/RECORD +0 -81
  68. tests/test_verifier_security.py +0 -427
  69. {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/licenses/LICENSE +0 -0
  70. {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)