fleet-python 0.2.2__py3-none-any.whl → 0.2.4__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.
Potentially problematic release.
This version of fleet-python might be problematic. Click here for more details.
- examples/dsl_example.py +108 -92
- examples/example.py +2 -2
- examples/json_tasks_example.py +82 -0
- examples/nova_act_example.py +18 -169
- examples/openai_example.py +89 -311
- examples/openai_simple_example.py +60 -0
- examples/quickstart.py +5 -5
- fleet/__init__.py +32 -3
- fleet/_async/base.py +51 -0
- fleet/_async/client.py +133 -0
- fleet/_async/env/__init__.py +0 -0
- fleet/_async/env/client.py +15 -0
- fleet/_async/exceptions.py +73 -0
- fleet/{manager → _async/instance}/__init__.py +4 -2
- fleet/{manager → _async/instance}/base.py +1 -24
- fleet/{manager → _async/instance}/client.py +44 -24
- fleet/{manager → _async/instance}/models.py +13 -0
- fleet/_async/models.py +109 -0
- fleet/_async/playwright.py +291 -0
- fleet/_async/resources/__init__.py +0 -0
- fleet/_async/resources/base.py +26 -0
- fleet/_async/resources/browser.py +41 -0
- fleet/_async/resources/sqlite.py +41 -0
- fleet/base.py +1 -24
- fleet/client.py +42 -95
- fleet/env/__init__.py +13 -1
- fleet/env/client.py +7 -7
- fleet/instance/__init__.py +26 -0
- fleet/instance/base.py +37 -0
- fleet/instance/client.py +278 -0
- fleet/instance/models.py +141 -0
- fleet/playwright.py +289 -0
- fleet/resources/__init__.py +0 -0
- fleet/resources/base.py +1 -1
- fleet/resources/browser.py +20 -23
- fleet/resources/sqlite.py +13 -13
- fleet/verifiers/__init__.py +10 -3
- fleet/verifiers/code.py +1 -0
- fleet/verifiers/{database_snapshot.py → db.py} +62 -22
- fleet/verifiers/sql_differ.py +1 -1
- {fleet_python-0.2.2.dist-info → fleet_python-0.2.4.dist-info}/METADATA +4 -1
- fleet_python-0.2.4.dist-info/RECORD +48 -0
- {fleet_python-0.2.2.dist-info → fleet_python-0.2.4.dist-info}/top_level.txt +1 -0
- scripts/unasync.py +28 -0
- fleet_python-0.2.2.dist-info/RECORD +0 -27
- {fleet_python-0.2.2.dist-info → fleet_python-0.2.4.dist-info}/WHEEL +0 -0
- {fleet_python-0.2.2.dist-info → fleet_python-0.2.4.dist-info}/licenses/LICENSE +0 -0
fleet/_async/base.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Dict, Any, Optional
|
|
3
|
+
|
|
4
|
+
from .models import InstanceResponse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EnvironmentBase(InstanceResponse):
|
|
8
|
+
@property
|
|
9
|
+
def manager_url(self) -> str:
|
|
10
|
+
return f"{self.urls.manager.api}"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseWrapper:
|
|
14
|
+
def __init__(self, *, api_key: Optional[str], base_url: Optional[str]):
|
|
15
|
+
if api_key is None:
|
|
16
|
+
raise ValueError("api_key is required")
|
|
17
|
+
self.api_key = api_key
|
|
18
|
+
if base_url is None:
|
|
19
|
+
base_url = "https://fleet.new"
|
|
20
|
+
self.base_url = base_url
|
|
21
|
+
|
|
22
|
+
def get_headers(self) -> Dict[str, str]:
|
|
23
|
+
headers: Dict[str, str] = {
|
|
24
|
+
"X-Fleet-SDK-Language": "Python",
|
|
25
|
+
"X-Fleet-SDK-Version": "1.0.0",
|
|
26
|
+
}
|
|
27
|
+
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
28
|
+
return headers
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AsyncWrapper(BaseWrapper):
|
|
32
|
+
def __init__(self, *, httpx_client: httpx.AsyncClient, **kwargs):
|
|
33
|
+
super().__init__(**kwargs)
|
|
34
|
+
self.httpx_client = httpx_client
|
|
35
|
+
|
|
36
|
+
async 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 await 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
|
+
)
|
fleet/_async/client.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Copyright 2025 Fleet AI
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Fleet API Client for making HTTP requests to Fleet services."""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
import httpx
|
|
19
|
+
import logging
|
|
20
|
+
from typing import Optional, List
|
|
21
|
+
|
|
22
|
+
from .base import EnvironmentBase, AsyncWrapper
|
|
23
|
+
from .models import InstanceRequest, InstanceRecord, Environment as EnvironmentModel
|
|
24
|
+
|
|
25
|
+
from .instance import (
|
|
26
|
+
AsyncInstanceClient,
|
|
27
|
+
ResetRequest,
|
|
28
|
+
ResetResponse,
|
|
29
|
+
ValidatorType,
|
|
30
|
+
ExecuteFunctionResponse,
|
|
31
|
+
)
|
|
32
|
+
from .resources.base import Resource
|
|
33
|
+
from .resources.sqlite import AsyncSQLiteResource
|
|
34
|
+
from .resources.browser import AsyncBrowserResource
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class AsyncEnvironment(EnvironmentBase):
|
|
40
|
+
def __init__(self, httpx_client: Optional[httpx.AsyncClient] = None, **kwargs):
|
|
41
|
+
super().__init__(**kwargs)
|
|
42
|
+
self._httpx_client = httpx_client or httpx.AsyncClient(timeout=60.0)
|
|
43
|
+
self._instance: Optional[AsyncInstanceClient] = None
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def instance(self) -> AsyncInstanceClient:
|
|
47
|
+
if self._instance is None:
|
|
48
|
+
self._instance = AsyncInstanceClient(self.manager_url, self._httpx_client)
|
|
49
|
+
return self._instance
|
|
50
|
+
|
|
51
|
+
async def reset(
|
|
52
|
+
self, seed: Optional[int] = None, timestamp: Optional[int] = None
|
|
53
|
+
) -> ResetResponse:
|
|
54
|
+
return await self.instance.reset(ResetRequest(seed=seed, timestamp=timestamp))
|
|
55
|
+
|
|
56
|
+
def db(self, name: str = "current") -> AsyncSQLiteResource:
|
|
57
|
+
return self.instance.db(name)
|
|
58
|
+
|
|
59
|
+
def browser(self, name: str = "cdp") -> AsyncBrowserResource:
|
|
60
|
+
return self.instance.browser(name)
|
|
61
|
+
|
|
62
|
+
def state(self, uri: str) -> Resource:
|
|
63
|
+
return self.instance.state(uri)
|
|
64
|
+
|
|
65
|
+
async def resources(self) -> List[Resource]:
|
|
66
|
+
return await self.instance.resources()
|
|
67
|
+
|
|
68
|
+
async def close(self) -> InstanceRecord:
|
|
69
|
+
return await AsyncFleet().delete(self.instance_id)
|
|
70
|
+
|
|
71
|
+
async def verify(self, validator: ValidatorType) -> ExecuteFunctionResponse:
|
|
72
|
+
return await self.instance.verify(validator)
|
|
73
|
+
|
|
74
|
+
async def verify_raw(
|
|
75
|
+
self, function_code: str, function_name: str
|
|
76
|
+
) -> ExecuteFunctionResponse:
|
|
77
|
+
return await self.instance.verify_raw(function_code, function_name)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class AsyncFleet:
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
api_key: Optional[str] = os.getenv("FLEET_API_KEY"),
|
|
84
|
+
base_url: Optional[str] = None,
|
|
85
|
+
httpx_client: Optional[httpx.AsyncClient] = None,
|
|
86
|
+
):
|
|
87
|
+
self._httpx_client = httpx_client or httpx.AsyncClient(timeout=60.0)
|
|
88
|
+
self.client = AsyncWrapper(
|
|
89
|
+
api_key=api_key,
|
|
90
|
+
base_url=base_url,
|
|
91
|
+
httpx_client=self._httpx_client,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
async def list_envs(self) -> List[EnvironmentModel]:
|
|
95
|
+
response = await self.client.request("GET", "/v1/env/")
|
|
96
|
+
return [EnvironmentModel(**env_data) for env_data in response.json()]
|
|
97
|
+
|
|
98
|
+
async def environment(self, env_key: str) -> EnvironmentModel:
|
|
99
|
+
response = await self.client.request("GET", f"/v1/env/{env_key}")
|
|
100
|
+
return EnvironmentModel(**response.json())
|
|
101
|
+
|
|
102
|
+
async def make(self, env_key: str) -> AsyncEnvironment:
|
|
103
|
+
if ":" in env_key:
|
|
104
|
+
env_key_part, version = env_key.split(":", 1)
|
|
105
|
+
if not version.startswith("v"):
|
|
106
|
+
version = f"v{version}"
|
|
107
|
+
else:
|
|
108
|
+
env_key_part = env_key
|
|
109
|
+
version = None
|
|
110
|
+
|
|
111
|
+
request = InstanceRequest(env_key=env_key_part, version=version)
|
|
112
|
+
response = await self.client.request(
|
|
113
|
+
"POST", "/v1/env/instances", json=request.model_dump()
|
|
114
|
+
)
|
|
115
|
+
instance = AsyncEnvironment(**response.json())
|
|
116
|
+
await instance.instance.load()
|
|
117
|
+
return instance
|
|
118
|
+
|
|
119
|
+
async def instances(self, status: Optional[str] = None) -> List[AsyncEnvironment]:
|
|
120
|
+
params = {}
|
|
121
|
+
if status:
|
|
122
|
+
params["status"] = status
|
|
123
|
+
|
|
124
|
+
response = await self.client.request("GET", "/v1/env/instances", params=params)
|
|
125
|
+
return [AsyncEnvironment(**instance_data) for instance_data in response.json()]
|
|
126
|
+
|
|
127
|
+
async def instance(self, instance_id: str) -> AsyncEnvironment:
|
|
128
|
+
response = await self.client.request("GET", f"/v1/env/instances/{instance_id}")
|
|
129
|
+
return AsyncEnvironment(**response.json())
|
|
130
|
+
|
|
131
|
+
async def delete(self, instance_id: str) -> InstanceRecord:
|
|
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)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Fleet SDK Exception Classes."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FleetError(Exception):
|
|
7
|
+
"""Base exception for all Fleet SDK errors."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
|
|
10
|
+
super().__init__(message)
|
|
11
|
+
self.message = message
|
|
12
|
+
self.details = details or {}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FleetAPIError(FleetError):
|
|
16
|
+
"""Exception raised when Fleet API returns an error."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
message: str,
|
|
21
|
+
status_code: Optional[int] = None,
|
|
22
|
+
response_data: Optional[Dict[str, Any]] = None,
|
|
23
|
+
details: Optional[Dict[str, Any]] = None,
|
|
24
|
+
):
|
|
25
|
+
super().__init__(message, details)
|
|
26
|
+
self.status_code = status_code
|
|
27
|
+
self.response_data = response_data or {}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class FleetTimeoutError(FleetError):
|
|
31
|
+
"""Exception raised when a Fleet operation times out."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, message: str, timeout_duration: Optional[float] = None):
|
|
34
|
+
super().__init__(message)
|
|
35
|
+
self.timeout_duration = timeout_duration
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class FleetAuthenticationError(FleetAPIError):
|
|
39
|
+
"""Exception raised when authentication fails."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, message: str = "Authentication failed"):
|
|
42
|
+
super().__init__(message, status_code=401)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class FleetRateLimitError(FleetAPIError):
|
|
46
|
+
"""Exception raised when rate limit is exceeded."""
|
|
47
|
+
|
|
48
|
+
def __init__(self, message: str = "Rate limit exceeded"):
|
|
49
|
+
super().__init__(message, status_code=429)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class FleetEnvironmentError(FleetError):
|
|
53
|
+
"""Exception raised when environment operations fail."""
|
|
54
|
+
|
|
55
|
+
def __init__(self, message: str, environment_id: Optional[str] = None):
|
|
56
|
+
super().__init__(message)
|
|
57
|
+
self.environment_id = environment_id
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class FleetFacetError(FleetError):
|
|
61
|
+
"""Exception raised when facet operations fail."""
|
|
62
|
+
|
|
63
|
+
def __init__(self, message: str, facet_type: Optional[str] = None):
|
|
64
|
+
super().__init__(message)
|
|
65
|
+
self.facet_type = facet_type
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class FleetConfigurationError(FleetError):
|
|
69
|
+
"""Exception raised when configuration is invalid."""
|
|
70
|
+
|
|
71
|
+
def __init__(self, message: str, config_key: Optional[str] = None):
|
|
72
|
+
super().__init__(message)
|
|
73
|
+
self.config_key = config_key
|
|
@@ -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,
|
|
@@ -8,10 +8,11 @@ from .models import (
|
|
|
8
8
|
ChromeStartRequest,
|
|
9
9
|
ChromeStartResponse,
|
|
10
10
|
ChromeStatusResponse,
|
|
11
|
+
ExecuteFunctionResponse,
|
|
11
12
|
)
|
|
12
13
|
|
|
13
14
|
__all__ = [
|
|
14
|
-
"
|
|
15
|
+
"ValidatorType",
|
|
15
16
|
"AsyncInstanceClient",
|
|
16
17
|
"ResetRequest",
|
|
17
18
|
"ResetResponse",
|
|
@@ -19,4 +20,5 @@ __all__ = [
|
|
|
19
20
|
"ChromeStartRequest",
|
|
20
21
|
"ChromeStartResponse",
|
|
21
22
|
"ChromeStatusResponse",
|
|
23
|
+
"ExecuteFunctionResponse"
|
|
22
24
|
]
|
|
@@ -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,8 +1,9 @@
|
|
|
1
|
-
"""Fleet SDK
|
|
1
|
+
"""Fleet SDK Async Instance Client."""
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
3
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
4
4
|
import asyncio
|
|
5
5
|
import httpx
|
|
6
|
+
import inspect
|
|
6
7
|
import time
|
|
7
8
|
import logging
|
|
8
9
|
from urllib.parse import urlparse
|
|
@@ -11,15 +12,19 @@ from ..resources.sqlite import AsyncSQLiteResource
|
|
|
11
12
|
from ..resources.browser import AsyncBrowserResource
|
|
12
13
|
from ..resources.base import Resource
|
|
13
14
|
|
|
15
|
+
from ...verifiers import DatabaseSnapshot
|
|
16
|
+
|
|
14
17
|
from ..exceptions import FleetEnvironmentError, FleetAPIError
|
|
15
18
|
|
|
16
|
-
from .base import
|
|
19
|
+
from .base import AsyncWrapper
|
|
17
20
|
from .models import (
|
|
18
21
|
ResetRequest,
|
|
19
22
|
ResetResponse,
|
|
20
23
|
Resource as ResourceModel,
|
|
21
24
|
ResourceType,
|
|
22
25
|
HealthResponse,
|
|
26
|
+
ExecuteFunctionRequest,
|
|
27
|
+
ExecuteFunctionResponse,
|
|
23
28
|
)
|
|
24
29
|
|
|
25
30
|
|
|
@@ -31,22 +36,10 @@ RESOURCE_TYPES = {
|
|
|
31
36
|
ResourceType.cdp: AsyncBrowserResource,
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
url: str,
|
|
39
|
-
httpx_client: Optional[httpx.Client] = None,
|
|
40
|
-
):
|
|
41
|
-
self.base_url = url
|
|
42
|
-
self.client = SyncWrapper(
|
|
43
|
-
url=self.base_url, httpx_client=httpx_client or httpx.Client()
|
|
44
|
-
)
|
|
45
|
-
raise NotImplementedError("SyncManager is not implemented")
|
|
46
|
-
|
|
47
|
-
def reset(self) -> ResetResponse:
|
|
48
|
-
response = self.client.request("POST", "/reset")
|
|
49
|
-
return ResetResponse(**response.json())
|
|
39
|
+
ValidatorType = Callable[
|
|
40
|
+
[DatabaseSnapshot, DatabaseSnapshot, Optional[str]],
|
|
41
|
+
int,
|
|
42
|
+
]
|
|
50
43
|
|
|
51
44
|
|
|
52
45
|
class AsyncInstanceClient:
|
|
@@ -57,7 +50,8 @@ class AsyncInstanceClient:
|
|
|
57
50
|
):
|
|
58
51
|
self.base_url = url
|
|
59
52
|
self.client = AsyncWrapper(
|
|
60
|
-
url=self.base_url,
|
|
53
|
+
url=self.base_url,
|
|
54
|
+
httpx_client=httpx_client or httpx.AsyncClient(timeout=60.0),
|
|
61
55
|
)
|
|
62
56
|
self._resources: Optional[List[ResourceModel]] = None
|
|
63
57
|
self._resources_state: Dict[str, Dict[str, Resource]] = {
|
|
@@ -106,15 +100,41 @@ class AsyncInstanceClient:
|
|
|
106
100
|
for resource in resources_by_name.values()
|
|
107
101
|
]
|
|
108
102
|
|
|
103
|
+
async def verify(self, validator: ValidatorType) -> ExecuteFunctionResponse:
|
|
104
|
+
function_code = inspect.getsource(validator)
|
|
105
|
+
function_name = validator.__name__
|
|
106
|
+
return await self.verify_raw(function_code, function_name)
|
|
107
|
+
|
|
108
|
+
async def verify_raw(
|
|
109
|
+
self, function_code: str, function_name: str
|
|
110
|
+
) -> ExecuteFunctionResponse:
|
|
111
|
+
response = await self.client.request(
|
|
112
|
+
"POST",
|
|
113
|
+
"/execute_verifier_function",
|
|
114
|
+
json=ExecuteFunctionRequest(
|
|
115
|
+
function_code=function_code,
|
|
116
|
+
function_name=function_name,
|
|
117
|
+
).model_dump(),
|
|
118
|
+
)
|
|
119
|
+
return ExecuteFunctionResponse(**response.json())
|
|
120
|
+
|
|
109
121
|
async def _load_resources(self) -> None:
|
|
110
122
|
if self._resources is None:
|
|
111
123
|
response = await self.client.request("GET", "/resources")
|
|
112
124
|
if response.status_code != 200:
|
|
113
125
|
self._resources = []
|
|
114
126
|
return
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
|
|
128
|
+
# Handle both old and new response formats
|
|
129
|
+
response_data = response.json()
|
|
130
|
+
if isinstance(response_data, dict) and "resources" in response_data:
|
|
131
|
+
# Old format: {"resources": [...]}
|
|
132
|
+
resources_list = response_data["resources"]
|
|
133
|
+
else:
|
|
134
|
+
# New format: [...]
|
|
135
|
+
resources_list = response_data
|
|
136
|
+
|
|
137
|
+
self._resources = [ResourceModel(**resource) for resource in resources_list]
|
|
118
138
|
for resource in self._resources:
|
|
119
139
|
if resource.type not in self._resources_state:
|
|
120
140
|
self._resources_state[resource.type.value] = {}
|
|
@@ -255,4 +275,4 @@ class AsyncInstanceClient:
|
|
|
255
275
|
|
|
256
276
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
257
277
|
"""Async context manager exit."""
|
|
258
|
-
await self.close()
|
|
278
|
+
await self.close()
|
|
@@ -126,3 +126,16 @@ class Resource(BaseModel):
|
|
|
126
126
|
type: ResourceType
|
|
127
127
|
mode: ResourceMode
|
|
128
128
|
label: Optional[str] = Field(None, title="Label")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ExecuteFunctionRequest(BaseModel):
|
|
132
|
+
function_code: str
|
|
133
|
+
function_name: str
|
|
134
|
+
text_solution: Optional[str] = None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class ExecuteFunctionResponse(BaseModel):
|
|
138
|
+
success: bool
|
|
139
|
+
result: Optional[Any] = None
|
|
140
|
+
error: Optional[str] = None
|
|
141
|
+
message: str
|
fleet/_async/models.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# generated by datamodel-codegen:
|
|
2
|
+
# filename: openapi.json
|
|
3
|
+
# timestamp: 2025-07-08T18:21:47+00:00
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from typing import Dict, List, Optional, Union
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Environment(BaseModel):
|
|
14
|
+
env_key: str = Field(..., title="Env Key")
|
|
15
|
+
name: str = Field(..., title="Name")
|
|
16
|
+
description: Optional[str] = Field(..., title="Description")
|
|
17
|
+
default_version: Optional[str] = Field(..., title="Default Version")
|
|
18
|
+
versions: Dict[str, str] = Field(..., title="Versions")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Instance(BaseModel):
|
|
22
|
+
instance_id: str = Field(..., title="Instance Id")
|
|
23
|
+
env_key: str = Field(..., title="Env Key")
|
|
24
|
+
version: str = Field(..., title="Version")
|
|
25
|
+
status: str = Field(..., title="Status")
|
|
26
|
+
subdomain: str = Field(..., title="Subdomain")
|
|
27
|
+
created_at: str = Field(..., title="Created At")
|
|
28
|
+
updated_at: str = Field(..., title="Updated At")
|
|
29
|
+
terminated_at: Optional[str] = Field(None, title="Terminated At")
|
|
30
|
+
team_id: str = Field(..., title="Team Id")
|
|
31
|
+
region: str = Field(..., title="Region")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class InstanceRequest(BaseModel):
|
|
35
|
+
env_key: str = Field(..., title="Env Key")
|
|
36
|
+
version: Optional[str] = Field(None, title="Version")
|
|
37
|
+
region: Optional[str] = Field("us-east-2", title="Region")
|
|
38
|
+
seed: Optional[int] = Field(None, title="Seed")
|
|
39
|
+
timestamp: Optional[int] = Field(None, title="Timestamp")
|
|
40
|
+
p_error: Optional[float] = Field(None, title="P Error")
|
|
41
|
+
avg_latency: Optional[float] = Field(None, title="Avg Latency")
|
|
42
|
+
run_id: Optional[str] = Field(None, title="Run Id")
|
|
43
|
+
task_id: Optional[str] = Field(None, title="Task Id")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class InstanceStatus(Enum):
|
|
47
|
+
pending = "pending"
|
|
48
|
+
running = "running"
|
|
49
|
+
stopped = "stopped"
|
|
50
|
+
error = "error"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ManagerURLs(BaseModel):
|
|
54
|
+
api: str = Field(..., title="Api")
|
|
55
|
+
docs: str = Field(..., title="Docs")
|
|
56
|
+
reset: str = Field(..., title="Reset")
|
|
57
|
+
diff: str = Field(..., title="Diff")
|
|
58
|
+
snapshot: str = Field(..., title="Snapshot")
|
|
59
|
+
execute_verifier_function: str = Field(..., title="Execute Verifier Function")
|
|
60
|
+
execute_verifier_function_with_upload: str = Field(
|
|
61
|
+
..., title="Execute Verifier Function With Upload"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ValidationError(BaseModel):
|
|
66
|
+
loc: List[Union[str, int]] = Field(..., title="Location")
|
|
67
|
+
msg: str = Field(..., title="Message")
|
|
68
|
+
type: str = Field(..., title="Error Type")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class HTTPValidationError(BaseModel):
|
|
72
|
+
detail: Optional[List[ValidationError]] = Field(None, title="Detail")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class InstanceURLs(BaseModel):
|
|
76
|
+
root: str = Field(..., title="Root")
|
|
77
|
+
app: str = Field(..., title="App")
|
|
78
|
+
api: Optional[str] = Field(None, title="Api")
|
|
79
|
+
health: Optional[str] = Field(None, title="Health")
|
|
80
|
+
api_docs: Optional[str] = Field(None, title="Api Docs")
|
|
81
|
+
manager: ManagerURLs
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class InstanceResponse(BaseModel):
|
|
85
|
+
instance_id: str = Field(..., title="Instance Id")
|
|
86
|
+
env_key: str = Field(..., title="Env Key")
|
|
87
|
+
version: str = Field(..., title="Version")
|
|
88
|
+
status: str = Field(..., title="Status")
|
|
89
|
+
subdomain: str = Field(..., title="Subdomain")
|
|
90
|
+
created_at: str = Field(..., title="Created At")
|
|
91
|
+
updated_at: str = Field(..., title="Updated At")
|
|
92
|
+
terminated_at: Optional[str] = Field(None, title="Terminated At")
|
|
93
|
+
team_id: str = Field(..., title="Team Id")
|
|
94
|
+
region: str = Field(..., title="Region")
|
|
95
|
+
urls: InstanceURLs
|
|
96
|
+
health: Optional[bool] = Field(None, title="Health")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class InstanceRecord(BaseModel):
|
|
100
|
+
instance_id: str
|
|
101
|
+
env_key: str
|
|
102
|
+
version: str
|
|
103
|
+
status: str
|
|
104
|
+
subdomain: str
|
|
105
|
+
created_at: str
|
|
106
|
+
updated_at: str
|
|
107
|
+
terminated_at: Optional[str] = None
|
|
108
|
+
team_id: str
|
|
109
|
+
region: str
|