futurehouse-client 0.3.20.dev63__py3-none-any.whl → 0.3.20.dev112__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.
- futurehouse_client/__init__.py +8 -0
- futurehouse_client/clients/job_client.py +1 -1
- futurehouse_client/clients/rest_client.py +49 -15
- futurehouse_client/models/app.py +1 -1
- futurehouse_client/models/rest.py +5 -5
- futurehouse_client/utils/world_model_tools.py +52 -0
- futurehouse_client/version.py +2 -2
- {futurehouse_client-0.3.20.dev63.dist-info → futurehouse_client-0.3.20.dev112.dist-info}/METADATA +1 -1
- futurehouse_client-0.3.20.dev112.dist-info/RECORD +21 -0
- futurehouse_client-0.3.20.dev63.dist-info/RECORD +0 -20
- {futurehouse_client-0.3.20.dev63.dist-info → futurehouse_client-0.3.20.dev112.dist-info}/WHEEL +0 -0
- {futurehouse_client-0.3.20.dev63.dist-info → futurehouse_client-0.3.20.dev112.dist-info}/licenses/LICENSE +0 -0
- {futurehouse_client-0.3.20.dev63.dist-info → futurehouse_client-0.3.20.dev112.dist-info}/top_level.txt +0 -0
futurehouse_client/__init__.py
CHANGED
@@ -8,6 +8,11 @@ from .models.app import (
|
|
8
8
|
TaskResponse,
|
9
9
|
TaskResponseVerbose,
|
10
10
|
)
|
11
|
+
from .utils.world_model_tools import (
|
12
|
+
create_world_model_tool,
|
13
|
+
search_world_model_tool,
|
14
|
+
make_world_model_tools,
|
15
|
+
)
|
11
16
|
|
12
17
|
__all__ = [
|
13
18
|
"FinchTaskResponse",
|
@@ -19,4 +24,7 @@ __all__ = [
|
|
19
24
|
"TaskRequest",
|
20
25
|
"TaskResponse",
|
21
26
|
"TaskResponseVerbose",
|
27
|
+
"create_world_model_tool",
|
28
|
+
"search_world_model_tool",
|
29
|
+
"make_world_model_tools",
|
22
30
|
]
|
@@ -73,7 +73,7 @@ class JobNames(StrEnum):
|
|
73
73
|
|
74
74
|
@staticmethod
|
75
75
|
def get_response_object_from_job(job_name: str) -> type[TaskResponse]:
|
76
|
-
return JobNames._get_response_mapping()
|
76
|
+
return JobNames._get_response_mapping().get(job_name, TaskResponse)
|
77
77
|
|
78
78
|
def get_response_object(self) -> type[TaskResponse]:
|
79
79
|
return self._get_response_mapping()[self.name]
|
@@ -111,6 +111,8 @@ class WorldModelFetchError(RestClientError):
|
|
111
111
|
class WorldModelCreationError(RestClientError):
|
112
112
|
"""Raised when there's an error creating a world model."""
|
113
113
|
|
114
|
+
class WorldModelDeletionError(RestClientError):
|
115
|
+
"""Raised when there's an error deleting a world model."""
|
114
116
|
|
115
117
|
class InvalidTaskDescriptionError(Exception):
|
116
118
|
"""Raised when the task description is invalid or empty."""
|
@@ -139,6 +141,7 @@ retry_if_connection_error = retry_if_exception_type((
|
|
139
141
|
DEFAULT_AGENT_TIMEOUT: int = 2400 # seconds
|
140
142
|
|
141
143
|
|
144
|
+
# pylint: disable=too-many-public-methods
|
142
145
|
class RestClient:
|
143
146
|
REQUEST_TIMEOUT: ClassVar[float] = 30.0 # sec
|
144
147
|
MAX_RETRY_ATTEMPTS: ClassVar[int] = 3
|
@@ -1419,15 +1422,9 @@ class RestClient:
|
|
1419
1422
|
if not (world_model_id or name) or (world_model_id and name):
|
1420
1423
|
raise ValueError("Provide either 'world_model_id' or 'name', but not both.")
|
1421
1424
|
|
1422
|
-
params = {
|
1423
|
-
"id": str(world_model_id) if world_model_id else None,
|
1424
|
-
"name": name,
|
1425
|
-
}
|
1426
|
-
# Filter out None values before making the request
|
1427
|
-
params = {k: v for k, v in params.items() if v is not None}
|
1428
|
-
|
1429
1425
|
try:
|
1430
|
-
|
1426
|
+
identifier = str(world_model_id) if world_model_id else name
|
1427
|
+
response = self.client.get(f"/v0.1/world-models/{identifier}")
|
1431
1428
|
response.raise_for_status()
|
1432
1429
|
return WorldModelResponse.model_validate(response.json())
|
1433
1430
|
except HTTPStatusError as e:
|
@@ -1465,14 +1462,9 @@ class RestClient:
|
|
1465
1462
|
if not (world_model_id or name) or (world_model_id and name):
|
1466
1463
|
raise ValueError("Provide either 'world_model_id' or 'name', but not both.")
|
1467
1464
|
|
1468
|
-
params = {
|
1469
|
-
"id": str(world_model_id) if world_model_id else None,
|
1470
|
-
"name": name,
|
1471
|
-
}
|
1472
|
-
params = {k: v for k, v in params.items() if v is not None}
|
1473
|
-
|
1474
1465
|
try:
|
1475
|
-
|
1466
|
+
identifier = str(world_model_id) if world_model_id else name
|
1467
|
+
response = await self.async_client.get(f"/v0.1/world-models/{identifier}")
|
1476
1468
|
response.raise_for_status()
|
1477
1469
|
return WorldModelResponse.model_validate(response.json())
|
1478
1470
|
except HTTPStatusError as e:
|
@@ -1486,6 +1478,25 @@ class RestClient:
|
|
1486
1478
|
except Exception as e:
|
1487
1479
|
raise WorldModelFetchError(f"An unexpected error occurred: {e}") from e
|
1488
1480
|
|
1481
|
+
@retry(
|
1482
|
+
stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
|
1483
|
+
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
|
1484
|
+
retry=retry_if_connection_error,
|
1485
|
+
)
|
1486
|
+
def search_world_models(self, query: str, size: int = 10) -> list[str]:
|
1487
|
+
"""Search for world models.
|
1488
|
+
|
1489
|
+
Args:
|
1490
|
+
query: The search query.
|
1491
|
+
size: The number of results to return.
|
1492
|
+
|
1493
|
+
Returns:
|
1494
|
+
A list of world model names.
|
1495
|
+
"""
|
1496
|
+
response = self.client.get(f"/v0.1/world-models/search/{query}", params={"size": size})
|
1497
|
+
response.raise_for_status()
|
1498
|
+
return response.json()
|
1499
|
+
|
1489
1500
|
@retry(
|
1490
1501
|
stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
|
1491
1502
|
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
|
@@ -1559,7 +1570,30 @@ class RestClient:
|
|
1559
1570
|
f"An unexpected error occurred during world model creation: {e}"
|
1560
1571
|
) from e
|
1561
1572
|
|
1573
|
+
@retry(
|
1574
|
+
stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
|
1575
|
+
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
|
1576
|
+
retry=retry_if_connection_error,
|
1577
|
+
)
|
1578
|
+
async def delete_world_model(self, world_model_id: UUID) -> None:
|
1579
|
+
"""Delete a world model snapshot by its ID.
|
1580
|
+
|
1581
|
+
Args:
|
1582
|
+
world_model_id: The unique ID of the world model snapshot to delete.
|
1562
1583
|
|
1584
|
+
Raises:
|
1585
|
+
WorldModelDeletionError: If the API call fails.
|
1586
|
+
"""
|
1587
|
+
try:
|
1588
|
+
response = await self.async_client.delete(f"/v0.1/world-models/{world_model_id}")
|
1589
|
+
response.raise_for_status()
|
1590
|
+
except HTTPStatusError as e:
|
1591
|
+
raise WorldModelDeletionError(
|
1592
|
+
f"Error deleting world model: {e.response.status_code} - {e.response.text}"
|
1593
|
+
) from e
|
1594
|
+
except Exception as e:
|
1595
|
+
raise WorldModelDeletionError(f"An unexpected error occurred: {e}") from e
|
1596
|
+
|
1563
1597
|
def get_installed_packages() -> dict[str, str]:
|
1564
1598
|
"""Returns a dictionary of installed packages and their versions."""
|
1565
1599
|
return {
|
futurehouse_client/models/app.py
CHANGED
@@ -610,7 +610,7 @@ class RuntimeConfig(BaseModel):
|
|
610
610
|
default=None,
|
611
611
|
description="Optional job identifier for a continued job",
|
612
612
|
)
|
613
|
-
world_model_id: UUID | None = Field(
|
613
|
+
world_model_id: UUID | str | None = Field(
|
614
614
|
default=None,
|
615
615
|
description="Optional world model identifier for the task",
|
616
616
|
)
|
@@ -46,10 +46,10 @@ class WorldModel(BaseModel):
|
|
46
46
|
"""
|
47
47
|
|
48
48
|
content: str
|
49
|
-
prior: UUID | None = None
|
49
|
+
prior: UUID | str | None = None
|
50
50
|
name: str | None = None
|
51
51
|
description: str | None = None
|
52
|
-
trajectory_id: UUID | None = None
|
52
|
+
trajectory_id: UUID | str | None = None
|
53
53
|
model_metadata: JsonValue | None = None
|
54
54
|
|
55
55
|
|
@@ -60,12 +60,12 @@ class WorldModelResponse(BaseModel):
|
|
60
60
|
This model is received from the API.
|
61
61
|
"""
|
62
62
|
|
63
|
-
id: UUID
|
64
|
-
prior: UUID | None
|
63
|
+
id: UUID | str
|
64
|
+
prior: UUID | str | None
|
65
65
|
name: str
|
66
66
|
description: str | None
|
67
67
|
content: str
|
68
|
-
trajectory_id: UUID | None
|
68
|
+
trajectory_id: UUID | str | None
|
69
69
|
email: str | None
|
70
70
|
model_metadata: JsonValue | None
|
71
71
|
enabled: bool
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from futurehouse_client.clients.rest_client import RestClient
|
2
|
+
from futurehouse_client.models.app import Stage
|
3
|
+
from futurehouse_client.models.rest import WorldModel
|
4
|
+
from uuid import UUID
|
5
|
+
from aviary.core import Tool
|
6
|
+
|
7
|
+
|
8
|
+
class WorldModelTools:
|
9
|
+
CLIENT = RestClient(
|
10
|
+
stage = Stage.DEV,
|
11
|
+
api_key="Dk7WJRLpqTFNxp5dYRoj6A.platformv01.eyJqdGkiOiI4ODAyZmZiNy1hNjM2LTRkMWYtYWE4NC1lZTQzYTMzMzRjZGMiLCJzdWIiOiJuN1dJbGU5VDljZ1BkTjd2OUJlM0pEUlpZVTgyIiwiaWF0IjoxNzQ5MDc2NzYzfQ.vThmFNLChP54DZBwB+qeMTB6CvAQ1IVXkTcpB0+efZ0",
|
12
|
+
)
|
13
|
+
|
14
|
+
@staticmethod
|
15
|
+
def create_world_model(name: str, description: str, content: str) -> UUID:
|
16
|
+
"""Create a new world model.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
name: The name of the world model.
|
20
|
+
description: A description of the world model.
|
21
|
+
content: The content/data of the world model.
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
UUID: The ID of the newly created world model.
|
25
|
+
"""
|
26
|
+
world_model = WorldModel(
|
27
|
+
name=name,
|
28
|
+
description=description,
|
29
|
+
content=content,
|
30
|
+
)
|
31
|
+
return WorldModelTools.CLIENT.create_world_model(world_model)
|
32
|
+
|
33
|
+
@staticmethod
|
34
|
+
def search_world_models(query: str) -> list[str]:
|
35
|
+
"""Search for world models using a text query.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
query: The search query string to match against world model content.
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
list[str]: A list of world model IDs that match the search query.
|
42
|
+
"""
|
43
|
+
return WorldModelTools.CLIENT.search_world_models(query, size=1)
|
44
|
+
|
45
|
+
create_world_model_tool = Tool.from_function(WorldModelTools.create_world_model)
|
46
|
+
search_world_model_tool = Tool.from_function(WorldModelTools.search_world_models)
|
47
|
+
|
48
|
+
def make_world_model_tools() -> list[Tool]:
|
49
|
+
return [
|
50
|
+
search_world_model_tool,
|
51
|
+
create_world_model_tool,
|
52
|
+
]
|
futurehouse_client/version.py
CHANGED
@@ -17,5 +17,5 @@ __version__: str
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
18
18
|
version_tuple: VERSION_TUPLE
|
19
19
|
|
20
|
-
__version__ = version = '0.3.20.
|
21
|
-
__version_tuple__ = version_tuple = (0, 3, 20, '
|
20
|
+
__version__ = version = '0.3.20.dev112'
|
21
|
+
__version_tuple__ = version_tuple = (0, 3, 20, 'dev112')
|
{futurehouse_client-0.3.20.dev63.dist-info → futurehouse_client-0.3.20.dev112.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: futurehouse-client
|
3
|
-
Version: 0.3.20.
|
3
|
+
Version: 0.3.20.dev112
|
4
4
|
Summary: A client for interacting with endpoints of the FutureHouse service.
|
5
5
|
Author-email: FutureHouse technical staff <hello@futurehouse.org>
|
6
6
|
License: Apache License
|
@@ -0,0 +1,21 @@
|
|
1
|
+
futurehouse_client/__init__.py,sha256=rRAJFxDI0nDHiMkyB-d7Q8Y2vVKFVnIFwOuRdjClTPw,707
|
2
|
+
futurehouse_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
futurehouse_client/version.py,sha256=nAw6MsWnD67V5v8vArdCA5jF1Rjl2uTamVcuYk2lPQo,530
|
4
|
+
futurehouse_client/clients/__init__.py,sha256=-HXNj-XJ3LRO5XM6MZ709iPs29YpApss0Q2YYg1qMZw,280
|
5
|
+
futurehouse_client/clients/job_client.py,sha256=D51_qTxya6g5Wfg_ZfJdP031TV_YDJeXkGMiYAJ1qRc,11962
|
6
|
+
futurehouse_client/clients/rest_client.py,sha256=hDV1Pr9gemChBKtklnlZlrwSYVUfHEGNGGmVDhoByIw,63015
|
7
|
+
futurehouse_client/models/__init__.py,sha256=5x-f9AoM1hGzJBEHcHAXSt7tPeImST5oZLuMdwp0mXc,554
|
8
|
+
futurehouse_client/models/app.py,sha256=TrfSorJlxyuc9ZzJpd2tL1pzKOp3jNBYRqFMfmmUue0,28954
|
9
|
+
futurehouse_client/models/client.py,sha256=n4HD0KStKLm6Ek9nL9ylP-bkK10yzAaD1uIDF83Qp_A,1828
|
10
|
+
futurehouse_client/models/rest.py,sha256=AwPMcB1ruoqaI8NIhX2ZzN8UuX6XsaQ7uzeSE8EpwKk,1573
|
11
|
+
futurehouse_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
futurehouse_client/utils/auth.py,sha256=tgWELjKfg8eWme_qdcRmc8TjQN9DVZuHHaVXZNHLchk,2960
|
13
|
+
futurehouse_client/utils/general.py,sha256=A_rtTiYW30ELGEZlWCIArO7q1nEmqi8hUlmBRYkMQ_c,767
|
14
|
+
futurehouse_client/utils/module_utils.py,sha256=aFyd-X-pDARXz9GWpn8SSViUVYdSbuy9vSkrzcVIaGI,4955
|
15
|
+
futurehouse_client/utils/monitoring.py,sha256=UjRlufe67kI3VxRHOd5fLtJmlCbVA2Wqwpd4uZhXkQM,8728
|
16
|
+
futurehouse_client/utils/world_model_tools.py,sha256=f-Q1X55HuisYyfTEHhhLMY_VamSMCkdXuHHp_V509bc,1899
|
17
|
+
futurehouse_client-0.3.20.dev112.dist-info/licenses/LICENSE,sha256=oQ9ZHjUi-_6GfP3gs14FlPb0OlGwE1QCCKFGnJ4LD2I,11341
|
18
|
+
futurehouse_client-0.3.20.dev112.dist-info/METADATA,sha256=a4IX4zQbKP51L71qkqjS8--fvdyIGVQZqneJn7DZuLg,26118
|
19
|
+
futurehouse_client-0.3.20.dev112.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
20
|
+
futurehouse_client-0.3.20.dev112.dist-info/top_level.txt,sha256=TRuLUCt_qBnggdFHCX4O_BoCu1j2X43lKfIZC-ElwWY,19
|
21
|
+
futurehouse_client-0.3.20.dev112.dist-info/RECORD,,
|
@@ -1,20 +0,0 @@
|
|
1
|
-
futurehouse_client/__init__.py,sha256=BztM_ntbgmIEjzvnBWcvPhvLjM8xGDFCK0Upf3-nIn8,488
|
2
|
-
futurehouse_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
futurehouse_client/version.py,sha256=isTppsUF5LzE3BUYjhyccnSnZwGsbVa_dNrIiEiEViQ,528
|
4
|
-
futurehouse_client/clients/__init__.py,sha256=-HXNj-XJ3LRO5XM6MZ709iPs29YpApss0Q2YYg1qMZw,280
|
5
|
-
futurehouse_client/clients/job_client.py,sha256=JgB5IUAyCmnhGRsYc3bgKldA-lkM1JLwHRwwUeOCdus,11944
|
6
|
-
futurehouse_client/clients/rest_client.py,sha256=fltCx1kCSZKLD-2QNPmK2PbXPa0q0zW9Q3837xS_6TQ,61554
|
7
|
-
futurehouse_client/models/__init__.py,sha256=5x-f9AoM1hGzJBEHcHAXSt7tPeImST5oZLuMdwp0mXc,554
|
8
|
-
futurehouse_client/models/app.py,sha256=fIWATuetex9GuNzGAWQz-9Dc63ifEFl-Mv-UN7nGSfA,28948
|
9
|
-
futurehouse_client/models/client.py,sha256=n4HD0KStKLm6Ek9nL9ylP-bkK10yzAaD1uIDF83Qp_A,1828
|
10
|
-
futurehouse_client/models/rest.py,sha256=QqOhRT-qTMfLtNge458qyBv6JFZvoQULnGIjjcDvMy8,1543
|
11
|
-
futurehouse_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
-
futurehouse_client/utils/auth.py,sha256=tgWELjKfg8eWme_qdcRmc8TjQN9DVZuHHaVXZNHLchk,2960
|
13
|
-
futurehouse_client/utils/general.py,sha256=A_rtTiYW30ELGEZlWCIArO7q1nEmqi8hUlmBRYkMQ_c,767
|
14
|
-
futurehouse_client/utils/module_utils.py,sha256=aFyd-X-pDARXz9GWpn8SSViUVYdSbuy9vSkrzcVIaGI,4955
|
15
|
-
futurehouse_client/utils/monitoring.py,sha256=UjRlufe67kI3VxRHOd5fLtJmlCbVA2Wqwpd4uZhXkQM,8728
|
16
|
-
futurehouse_client-0.3.20.dev63.dist-info/licenses/LICENSE,sha256=oQ9ZHjUi-_6GfP3gs14FlPb0OlGwE1QCCKFGnJ4LD2I,11341
|
17
|
-
futurehouse_client-0.3.20.dev63.dist-info/METADATA,sha256=4hmqtHLV-eHTN3l8vXmtIW4L6TFAkBDymbjyg7_rBJQ,26117
|
18
|
-
futurehouse_client-0.3.20.dev63.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
19
|
-
futurehouse_client-0.3.20.dev63.dist-info/top_level.txt,sha256=TRuLUCt_qBnggdFHCX4O_BoCu1j2X43lKfIZC-ElwWY,19
|
20
|
-
futurehouse_client-0.3.20.dev63.dist-info/RECORD,,
|
{futurehouse_client-0.3.20.dev63.dist-info → futurehouse_client-0.3.20.dev112.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|