futurehouse-client 0.0.1__py3-none-any.whl → 0.0.2__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.
@@ -1,9 +1,9 @@
1
1
  from .clients.job_client import JobClient, JobNames
2
2
  from .clients.rest_client import JobResponse, JobResponseVerbose, PQAJobResponse
3
- from .clients.rest_client import RestClient as Client
3
+ from .clients.rest_client import RestClient as FutureHouseClient
4
4
 
5
5
  __all__ = [
6
- "Client",
6
+ "FutureHouseClient",
7
7
  "JobClient",
8
8
  "JobNames",
9
9
  "JobResponse",
@@ -1,9 +1,9 @@
1
1
  from .job_client import JobClient, JobNames
2
2
  from .rest_client import JobResponse, JobResponseVerbose, PQAJobResponse
3
- from .rest_client import RestClient as CrowClient
3
+ from .rest_client import RestClient as FutureHouseClient
4
4
 
5
5
  __all__ = [
6
- "CrowClient",
6
+ "FutureHouseClient",
7
7
  "JobClient",
8
8
  "JobNames",
9
9
  "JobResponse",
@@ -19,7 +19,7 @@ logger = logging.getLogger(__name__)
19
19
 
20
20
 
21
21
  class JobNames(StrEnum):
22
- """Enum of available crow jobs."""
22
+ """Enum of available jobs."""
23
23
 
24
24
  CROW = "job-futurehouse-paperqa2"
25
25
  FALCON = "job-futurehouse-paperqa2-deep"
@@ -29,6 +29,7 @@ from futurehouse_client.clients import JobNames
29
29
  from futurehouse_client.models.app import (
30
30
  APIKeyPayload,
31
31
  AuthType,
32
+ # TODO: Rename this to JobDeploymentConfig. But other parts of the code depend on this name, so I'm not changing it now
32
33
  CrowDeploymentConfig,
33
34
  JobRequest,
34
35
  Stage,
@@ -73,7 +74,7 @@ JWT_TOKEN_CACHE_EXPIRY: int = 300 # seconds
73
74
 
74
75
 
75
76
  class JobResponse(BaseModel):
76
- """Base class for job responses. This holds attributes shared over all crows."""
77
+ """Base class for job responses. This holds attributes shared over all futurehouse jobs."""
77
78
 
78
79
  model_config = ConfigDict(extra="ignore")
79
80
 
@@ -81,7 +82,7 @@ class JobResponse(BaseModel):
81
82
  task: str
82
83
  user: str
83
84
  created_at: datetime
84
- crow: str
85
+ job_name: str
85
86
  public: bool
86
87
  shared_with: list[str]
87
88
  build_owner: str | None = None
@@ -95,6 +96,9 @@ class JobResponse(BaseModel):
95
96
  # Extract fields from environment frame state
96
97
  if not isinstance(data, dict):
97
98
  return data
99
+ data["job_name"] = data.get(
100
+ "crow"
101
+ ) # TODO: remove this once we have the new job_name field.
98
102
  if not (env_frame := data.get("environment_frame", {})):
99
103
  return data
100
104
  state = env_frame.get("state", {}).get("state", {})
@@ -340,7 +344,7 @@ class RestClient:
340
344
  def get_job(
341
345
  self, job_id: str | None = None, history: bool = False, verbose: bool = False
342
346
  ) -> "JobResponse":
343
- """Get details for a specific crow job."""
347
+ """Get details for a specific job."""
344
348
  try:
345
349
  job_id = job_id or self.trajectory_id
346
350
  response = self.client.get(
@@ -352,7 +356,7 @@ class RestClient:
352
356
  if verbose:
353
357
  return verbose_response
354
358
  if any(
355
- JobNames.from_string(job_name) in verbose_response.crow
359
+ JobNames.from_string(job_name) in verbose_response.job_name
356
360
  for job_name in ["crow", "falcon", "owl", "dummy"]
357
361
  ):
358
362
  return PQAJobResponse(**response.json())
@@ -368,7 +372,7 @@ class RestClient:
368
372
  retry=retry_if_exception_type(Timeout),
369
373
  )
370
374
  def create_job(self, job_data: JobRequest | dict[str, Any]):
371
- """Create a new crow job."""
375
+ """Create a new futurehouse job."""
372
376
  if isinstance(job_data, dict):
373
377
  job_data = JobRequest.model_validate(job_data)
374
378
 
@@ -401,6 +405,7 @@ class RestClient:
401
405
  return response.json()
402
406
 
403
407
  # TODO: Refactor later so we don't have to ignore PLR0915
408
+ # TODO: Rename this to create_job. I'm not doing it now to avoid breaking the infrastructure.
404
409
  @retry(
405
410
  stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
406
411
  wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: futurehouse-client
3
+ Version: 0.0.2
4
+ Summary: A client for interacting with endpoints of the FutureHouse service.
5
+ Author-email: FutureHouse technical staff <hello@futurehouse.org>
6
+ Classifier: Operating System :: OS Independent
7
+ Classifier: Programming Language :: Python :: 3 :: Only
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python
11
+ Requires-Python: <3.13,>=3.11
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: cloudpickle
14
+ Requires-Dist: dm-tree<0.1.9
15
+ Requires-Dist: fhaviary
16
+ Requires-Dist: httpx
17
+ Requires-Dist: ldp>=0.22.0
18
+ Requires-Dist: pydantic
19
+ Requires-Dist: python-dotenv
20
+ Requires-Dist: tenacity
21
+ Provides-Extra: dev
22
+ Requires-Dist: black; extra == "dev"
23
+ Requires-Dist: jupyter; extra == "dev"
24
+ Requires-Dist: jupyterlab; extra == "dev"
25
+ Requires-Dist: mypy; extra == "dev"
26
+ Requires-Dist: notebook; extra == "dev"
27
+ Requires-Dist: pre-commit; extra == "dev"
28
+ Requires-Dist: pylint; extra == "dev"
29
+ Requires-Dist: pylint-per-file-ignores; extra == "dev"
30
+ Requires-Dist: pylint-pydantic; extra == "dev"
31
+ Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: pytest-rerunfailures; extra == "dev"
33
+ Requires-Dist: pytest-subtests; extra == "dev"
34
+ Requires-Dist: pytest-timeout; extra == "dev"
35
+ Requires-Dist: pytest-xdist; extra == "dev"
36
+ Requires-Dist: ruff; extra == "dev"
37
+ Requires-Dist: setuptools_scm; extra == "dev"
38
+
39
+ # FutureHouse Platform API Documentation
40
+
41
+ Documentation and tutorials for crow-client, a client for interacting with endpoints of the FutureHouse crow service.
42
+
43
+ > FutureHouse's mascot is the crow. Therefore, some objects are named after the crow as a homage.
44
+
45
+ <!--TOC-->
46
+
47
+ - [Installation](#installation)
48
+ - [Quickstart](#quickstart)
49
+ - [Functionalities](#functionalities)
50
+ - [Stages](#stages)
51
+ - [Authentication](#authentication)
52
+ - [Job submission](#job-submission)
53
+ - [Job Continuation](#job-continuation)
54
+ - [Job retrieval](#job-retrieval)
55
+
56
+ <!--TOC-->
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ uv pip install crow-client
62
+ ```
63
+
64
+ ## Quickstart
65
+
66
+ ```python
67
+ from crow_client import CrowClient, JobNames
68
+ from pathlib import Path
69
+ from aviary.core import DummyEnv
70
+ import ldp
71
+
72
+ client = CrowClient(
73
+ stage=Stage.DEV,
74
+ auth_type=AuthType.API_KEY,
75
+ api_key="your_api_key",
76
+ )
77
+
78
+ job_data = {
79
+ "name": JobNames.CROW,
80
+ "query": "Has anyone tested therapeutic exerkines in humans or NHPs?",
81
+ }
82
+
83
+ job_run_id = client.create_job(job_data)
84
+
85
+ job_status = client.get_job(job_run_id)
86
+ ```
87
+
88
+ A quickstart example can be found in the [crow_client_notebook.ipynb](./docs/crow_client_notebook.ipynb) file, where we show how to submit and retrieve a job task, pass runtime configuration to the agent, and ask follow-up questions to the previous job.
89
+
90
+ ## Functionalities
91
+
92
+ Crow-client implements a RestClient (called `CrowClient`) with the following functionalities:
93
+
94
+ - [Authentication](#authtype): `auth_client`
95
+ - [Job submission](#job-submission): `create_job(JobRequest)`
96
+ - [Job status](#job-status): `get_job(job_id)`
97
+
98
+ To create a `CrowClient`, you need to pass the following parameters:
99
+ | Parameter | Type | Default | Description |
100
+ | --- | --- | --- | --- |
101
+ | stage | Stage | Stage.DEV | Where the job will be submitted? |
102
+ | organization | str \| None | None | Which organization to use? |
103
+ | auth_type | AuthType | AuthType.API_KEY | Which authentication method to use? |
104
+ | api_key | str \| None | None | The API key to use for authentication, if using auth_type=AuthType.API_KEY. |
105
+
106
+ To instantiate a Client, we can use the following code:
107
+
108
+ ```python
109
+ from crow_client import CrowClient
110
+ from crow_client.models import Stage, AuthType
111
+
112
+ client = CrowClient(
113
+ stage=Stage.DEV,
114
+ organization="your_organization",
115
+ auth_type=AuthType.API_KEY,
116
+ api_key="your_api_key",
117
+ )
118
+ ```
119
+
120
+ ### Stages
121
+
122
+ The stage is where your job will be submitted. This parameter can be one of the following:
123
+ | Name | Description |
124
+ | --- | --- |
125
+ | Stage.DEV | Development environment at https://dev.api.platform.futurehouse.org |
126
+ | Stage.PROD | Production environment at https://api.platform.futurehouse.org |
127
+
128
+ ## Authentication
129
+
130
+ In order to use the `CrowClient`, you need to authenticate yourself. Authentication is done by providing an API key, which can be obtained directly from your [profile page in the FutureHouse platform](https://platform.futurehouse.org/profile).
131
+
132
+ ## Job submission
133
+
134
+ `CrowClient` can be used to submit jobs to the FutureHouse platform. Using a `CrowClient` instance, you can submit jobs to the platform by calling the `create_job` method, which receives a `JobRequest` (or a dictionary with `kwargs`) and returns the job id.
135
+ Aiming to make the submission of jobs as simple as possible, we have created a `JobNames` enum that contains the available job types.
136
+
137
+ The available supported jobs are:
138
+ | Alias | Job Name | Task type | Description |
139
+ | --- | --- | --- | --- |
140
+ | `JobNames.CROW` | `job-futurehouse-paperqa2` | Fast Search | Ask a question of scientific data sources, and receive a high-accuracy, cited response. Built with [PaperQA2](https://github.com/Future-House/paper-qa). |
141
+ | `JobNames.FALCON` | `job-futurehouse-paperqa2-deep` | Deep Search | Use a plethora of sources to deeply research. Receive a detailed, structured report as a response. |
142
+ | `JobNames.OWL` | `job-futurehouse-hasanyone` | Precedent Search | Formerly known as HasAnyone, query if anyone has ever done something in science. |
143
+ | `JobNames.DUMMY` | `job-futurehouse-dummy` | Dummy Task | This is a dummy task. Mainly for testing purposes. |
144
+
145
+ Using `JobNames`, the client automatically adapts the job name to the current stage.
146
+ The job submission looks like this:
147
+
148
+ ```python
149
+ from crow_client import CrowClient, JobNames
150
+ from crow_client.models import AuthType, Stage
151
+
152
+ client = CrowClient(
153
+ stage=Stage.DEV,
154
+ auth_type=AuthType.API_KEY,
155
+ api_key="your_api_key",
156
+ )
157
+
158
+ job_data = {
159
+ "name": JobNames.CROW,
160
+ "query": "Has anyone tested therapeutic exerkines in humans or NHPs?",
161
+ }
162
+
163
+ job_id = client.create_job(job_data)
164
+ ```
165
+
166
+ `JobRequest` has the following fields:
167
+
168
+ | Field | Type | Description |
169
+ | -------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- |
170
+ | id | UUID | Optional job identifier. A UUID will be generated if not provided |
171
+ | name | str | Name of the job to execute eg. `job-futurehouse-paperqa2`, or using the `JobNames` for convenience: `JobNames.CROW` |
172
+ | query | str | Query or task to be executed by the job |
173
+ | runtime_config | RuntimeConfig | Optional runtime parameters for the job |
174
+
175
+ `runtime_config` can receive a `AgentConfig` object with the desired kwargs. Check the available `AgentConfig` fields in the [LDP documentation](https://github.com/Future-House/ldp/blob/main/src/ldp/agent/agent.py#L87). Besides the `AgentConfig` object, we can also pass `timeout` and `max_steps` to limit the execution time and the number of steps the agent can take.
176
+ Other especialised configurations are also available but are outside the scope of this documentation.
177
+
178
+ ## Job Continuation
179
+
180
+ Once a job is submitted and the answer is returned, FutureHouse platform allow you to ask follow-up questions to the previous job.
181
+ It is also possible through the platform API.
182
+ To accomplish that, we can use the `runtime_config` we discussed in the [Job submission](#job-submission) section.
183
+
184
+ ```python
185
+ from crow_client import CrowClient, JobNames
186
+ from crow_client.models import AuthType, Stage
187
+
188
+ client = CrowClient(
189
+ stage=Stage.DEV,
190
+ auth_type=AuthType.API_KEY,
191
+ api_key="your_api_key",
192
+ )
193
+
194
+ job_data = {"name": JobNames.CROW, "query": "How many species of birds are there?"}
195
+
196
+ job_id = client.create_job(job_data)
197
+
198
+ continued_job_data = {
199
+ "name": JobNames.CROW,
200
+ "query": "From the previous answer, specifically,how many species of crows are there?",
201
+ "runtime_config": {"continued_job_id": job_id},
202
+ }
203
+
204
+ continued_job_id = client.create_job(continued_job_data)
205
+ ```
206
+
207
+ ## Job retrieval
208
+
209
+ Once a job is submitted, you can retrieve it by calling the `get_job` method, which receives a job id and returns a `JobResponse` object.
210
+
211
+ ```python
212
+ from crow_client import CrowClient
213
+ from crow_client.models import AuthType
214
+
215
+ client = CrowClient(
216
+ auth_type=AuthType.API_KEY,
217
+ api_key="your_api_key",
218
+ )
219
+
220
+ job_id = "job_id"
221
+
222
+ job_status = client.get_job(job_id)
223
+ ```
224
+
225
+ `job_status` contains information about the job. For instance, its `status`, `task`, `environment_name` and `agent_name`, and other fields specific to the job.
@@ -0,0 +1,14 @@
1
+ futurehouse_client/__init__.py,sha256=QhDraw1J-DNc2kEq8E3iMIMokbllTHuVEOXgUCIT8qc,338
2
+ futurehouse_client/clients/__init__.py,sha256=JpqWhXNRo4-xe9-SA_9QI5Z5P3xlJ-b4STGaljQpj3k,314
3
+ futurehouse_client/clients/job_client.py,sha256=RNgdSJVI1vjQSypdfswHX0Gvv_XnKG4bZjklf3WdSuk,8828
4
+ futurehouse_client/clients/rest_client.py,sha256=Qu6Ui-ot_pAJG-55Ll_IjOWLOkFELDaTObLkay7vxEY,25101
5
+ futurehouse_client/models/__init__.py,sha256=VBKYb_2kmxtDwp9LvTL7BEFyioekggQsrQg5I_dhZoI,342
6
+ futurehouse_client/models/app.py,sha256=_MO31xvKJaAztWz4KrV13ty4POg-RuWrGgqmvS9w2bc,22298
7
+ futurehouse_client/models/client.py,sha256=n4HD0KStKLm6Ek9nL9ylP-bkK10yzAaD1uIDF83Qp_A,1828
8
+ futurehouse_client/models/rest.py,sha256=W-wNFTN7HALYFFphw-RQYRMm6_TSa1cl4T-mZ1msk90,393
9
+ futurehouse_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ futurehouse_client/utils/module_utils.py,sha256=aFyd-X-pDARXz9GWpn8SSViUVYdSbuy9vSkrzcVIaGI,4955
11
+ futurehouse_client-0.0.2.dist-info/METADATA,sha256=lOwcSqbXH6Y1MDN22bW4j7VlsLItc0aG3lHaysdA-TU,8894
12
+ futurehouse_client-0.0.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
+ futurehouse_client-0.0.2.dist-info/top_level.txt,sha256=TRuLUCt_qBnggdFHCX4O_BoCu1j2X43lKfIZC-ElwWY,19
14
+ futurehouse_client-0.0.2.dist-info/RECORD,,
@@ -1,151 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: futurehouse-client
3
- Version: 0.0.1
4
- Summary: A client for interacting with endpoints of the FutureHouse service.
5
- Author-email: FutureHouse technical staff <hello@futurehouse.org>
6
- Classifier: Operating System :: OS Independent
7
- Classifier: Programming Language :: Python :: 3 :: Only
8
- Classifier: Programming Language :: Python :: 3.11
9
- Classifier: Programming Language :: Python :: 3.12
10
- Classifier: Programming Language :: Python
11
- Requires-Python: <3.13,>=3.11
12
- Description-Content-Type: text/markdown
13
- Requires-Dist: cloudpickle
14
- Requires-Dist: dm-tree<0.1.9
15
- Requires-Dist: fhaviary
16
- Requires-Dist: httpx
17
- Requires-Dist: ldp>=0.22.0
18
- Requires-Dist: pydantic
19
- Requires-Dist: python-dotenv
20
- Requires-Dist: tenacity
21
- Provides-Extra: dev
22
- Requires-Dist: black; extra == "dev"
23
- Requires-Dist: jupyter; extra == "dev"
24
- Requires-Dist: jupyterlab; extra == "dev"
25
- Requires-Dist: mypy; extra == "dev"
26
- Requires-Dist: notebook; extra == "dev"
27
- Requires-Dist: pre-commit; extra == "dev"
28
- Requires-Dist: pylint; extra == "dev"
29
- Requires-Dist: pylint-per-file-ignores; extra == "dev"
30
- Requires-Dist: pylint-pydantic; extra == "dev"
31
- Requires-Dist: pytest; extra == "dev"
32
- Requires-Dist: pytest-rerunfailures; extra == "dev"
33
- Requires-Dist: pytest-subtests; extra == "dev"
34
- Requires-Dist: pytest-timeout; extra == "dev"
35
- Requires-Dist: pytest-xdist; extra == "dev"
36
- Requires-Dist: ruff; extra == "dev"
37
- Requires-Dist: setuptools_scm; extra == "dev"
38
-
39
- # crow-client
40
-
41
- A client for interacting with endpoints of the FutureHouse crow service.
42
-
43
- ## Installation
44
-
45
- ```bash
46
- uv pip install crow-client
47
- ```
48
-
49
- ## Usage
50
-
51
- The CrowClient provides simple functions to deploy and monitor your crow.
52
-
53
- In the case of environments the deployment looks like this
54
-
55
- ```python
56
- from pathlib import Path
57
- from crow_client import CrowClient
58
- from crow_client.models import CrowDeploymentConfig
59
-
60
- client = CrowClient()
61
-
62
- crow = CrowDeploymentConfig(
63
- path=Path("../envs/dummy_env"),
64
- environment="dummy_env.env.DummyEnv",
65
- requires_aviary_internal=False,
66
- environment_variables={"SAMPLE_ENV_VAR": "sample_val"},
67
- agent="ldp.agent.SimpleAgent",
68
- )
69
-
70
- client.create_crow(crow)
71
-
72
- # checks the status
73
- client.get_build_status()
74
- ```
75
-
76
- For functional environments we don't need to pass the file path and can pass the environment builder instead
77
-
78
- ```python
79
- from aviary.core import fenv
80
- import numpy as np
81
-
82
-
83
- def function_to_use_here(inpste: str):
84
- a = np.array(np.asmatrix("1 2; 3 4"))
85
- return inpste
86
-
87
-
88
- @fenv.start()
89
- def my_env(topic: str):
90
- """
91
- Here is the doc string describing the task.
92
- """
93
- a = np.array(np.asmatrix("1 2; 3 4"))
94
- return f"Write a sad story about {topic}", {"chosen_topic": topic}
95
-
96
-
97
- @my_env.tool()
98
- def print_story(story: str, state) -> None:
99
- """Print the story and complete the task"""
100
- print(story)
101
- print(function_to_use_here(story))
102
- state.reward = 1
103
- state.done = True
104
-
105
-
106
- from crow_client import CrowClient
107
- from crow_client.models import CrowDeploymentConfig, Stage
108
- from crow_client.clients.rest_client import generate_requirements
109
-
110
- client = CrowClient(stage=Stage.LOCAL)
111
-
112
- crow = CrowDeploymentConfig(
113
- functional_environment=my_env,
114
- environment="my_env",
115
- requires_aviary_internal=False,
116
- environment_variables={"SAMPLE_ENV_VAR": "sample_val"},
117
- agent="ldp.agent.SimpleAgent",
118
- requirements=generate_requirements(my_env, globals()),
119
- )
120
-
121
- client.create_crow(crow)
122
- ```
123
-
124
- This client also provides functions that let you send tasks to an existing crow:
125
-
126
- ```python
127
- from crow_client import CrowJob
128
-
129
- client = CrowClient()
130
-
131
- job_data = {"name": "your-job-name", "query": "your task"}
132
- client.create_job(job_data)
133
-
134
- # checks the status
135
- client.get_job()
136
- ```
137
-
138
- The CrowJobClient provides an interface for managing environment states and agent interactions in the FutureHouse crow service.
139
-
140
- ```python
141
- from crow_client import CrowJobClient
142
- from crow_client.models.app import Stage
143
-
144
- client = CrowJobClient(
145
- environment="your_environment_name",
146
- agent="your_agent_id",
147
- auth_token="your_auth_token",
148
- base_uri=Stage.DEV,
149
- trajectory_id=None,
150
- )
151
- ```
@@ -1,14 +0,0 @@
1
- futurehouse_client/__init__.py,sha256=SaaBeLHh4K81dONiXxowhsgM-Zr12t1g-phDgwi5iWc,316
2
- futurehouse_client/clients/__init__.py,sha256=OWJtj6WNJ1GvzA5v-Z8yiKlta47k4dprih-9n7mag40,300
3
- futurehouse_client/clients/job_client.py,sha256=M0siUz-5Ffri4_fhXXeBb54qnELwMa1hYzosS8bx3ek,8833
4
- futurehouse_client/clients/rest_client.py,sha256=dEes4lP0JOsuRoFgjhU9uXSogBGFOWgSw8ZfopUJ4w8,24734
5
- futurehouse_client/models/__init__.py,sha256=VBKYb_2kmxtDwp9LvTL7BEFyioekggQsrQg5I_dhZoI,342
6
- futurehouse_client/models/app.py,sha256=_MO31xvKJaAztWz4KrV13ty4POg-RuWrGgqmvS9w2bc,22298
7
- futurehouse_client/models/client.py,sha256=n4HD0KStKLm6Ek9nL9ylP-bkK10yzAaD1uIDF83Qp_A,1828
8
- futurehouse_client/models/rest.py,sha256=W-wNFTN7HALYFFphw-RQYRMm6_TSa1cl4T-mZ1msk90,393
9
- futurehouse_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- futurehouse_client/utils/module_utils.py,sha256=aFyd-X-pDARXz9GWpn8SSViUVYdSbuy9vSkrzcVIaGI,4955
11
- futurehouse_client-0.0.1.dist-info/METADATA,sha256=L7c7KYAcl5HgkRBNmjHS0xnWmZb4QHwmAS3-vrLmtsw,4076
12
- futurehouse_client-0.0.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
- futurehouse_client-0.0.1.dist-info/top_level.txt,sha256=TRuLUCt_qBnggdFHCX4O_BoCu1j2X43lKfIZC-ElwWY,19
14
- futurehouse_client-0.0.1.dist-info/RECORD,,