futurehouse-client 0.0.2__py3-none-any.whl → 0.0.3__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,12 +1,12 @@
1
1
  from .clients.job_client import JobClient, JobNames
2
- from .clients.rest_client import JobResponse, JobResponseVerbose, PQAJobResponse
2
+ from .clients.rest_client import PQATaskResponse, TaskResponse, TaskResponseVerbose
3
3
  from .clients.rest_client import RestClient as FutureHouseClient
4
4
 
5
5
  __all__ = [
6
6
  "FutureHouseClient",
7
7
  "JobClient",
8
8
  "JobNames",
9
- "JobResponse",
10
- "JobResponseVerbose",
11
- "PQAJobResponse",
9
+ "PQATaskResponse",
10
+ "TaskResponse",
11
+ "TaskResponseVerbose",
12
12
  ]
@@ -1,12 +1,12 @@
1
1
  from .job_client import JobClient, JobNames
2
- from .rest_client import JobResponse, JobResponseVerbose, PQAJobResponse
2
+ from .rest_client import PQATaskResponse, TaskResponse, TaskResponseVerbose
3
3
  from .rest_client import RestClient as FutureHouseClient
4
4
 
5
5
  __all__ = [
6
6
  "FutureHouseClient",
7
7
  "JobClient",
8
8
  "JobNames",
9
- "JobResponse",
10
- "JobResponseVerbose",
11
- "PQAJobResponse",
9
+ "PQATaskResponse",
10
+ "TaskResponse",
11
+ "TaskResponseVerbose",
12
12
  ]
@@ -29,10 +29,9 @@ 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
33
- CrowDeploymentConfig,
34
- JobRequest,
32
+ JobDeploymentConfig,
35
33
  Stage,
34
+ TaskRequest,
36
35
  )
37
36
  from futurehouse_client.utils.module_utils import (
38
37
  OrganizationSelector,
@@ -41,7 +40,7 @@ from futurehouse_client.utils.module_utils import (
41
40
 
42
41
  logger = logging.getLogger(__name__)
43
42
 
44
- JobRequest.model_rebuild()
43
+ TaskRequest.model_rebuild()
45
44
 
46
45
  FILE_UPLOAD_IGNORE_PARTS = {
47
46
  ".ruff_cache",
@@ -57,6 +56,10 @@ class RestClientError(Exception):
57
56
  """Base exception for REST client errors."""
58
57
 
59
58
 
59
+ class TaskFetchError(RestClientError):
60
+ """Raised when there's an error fetching a task."""
61
+
62
+
60
63
  class JobFetchError(RestClientError):
61
64
  """Raised when there's an error fetching a job."""
62
65
 
@@ -73,13 +76,13 @@ class InvalidTaskDescriptionError(Exception):
73
76
  JWT_TOKEN_CACHE_EXPIRY: int = 300 # seconds
74
77
 
75
78
 
76
- class JobResponse(BaseModel):
77
- """Base class for job responses. This holds attributes shared over all futurehouse jobs."""
79
+ class TaskResponse(BaseModel):
80
+ """Base class for task responses. This holds attributes shared over all futurehouse jobs."""
78
81
 
79
82
  model_config = ConfigDict(extra="ignore")
80
83
 
81
84
  status: str
82
- task: str
85
+ query: str
83
86
  user: str
84
87
  created_at: datetime
85
88
  job_name: str
@@ -88,7 +91,7 @@ class JobResponse(BaseModel):
88
91
  build_owner: str | None = None
89
92
  environment_name: str | None = None
90
93
  agent_name: str | None = None
91
- job_id: UUID | None = None
94
+ task_id: UUID | None = None
92
95
 
93
96
  @model_validator(mode="before")
94
97
  @classmethod
@@ -96,13 +99,13 @@ class JobResponse(BaseModel):
96
99
  # Extract fields from environment frame state
97
100
  if not isinstance(data, dict):
98
101
  return data
99
- data["job_name"] = data.get(
100
- "crow"
101
- ) # TODO: remove this once we have the new job_name field.
102
+ # TODO: We probably want to remove these two once we define the final names.
103
+ data["job_name"] = data.get("crow")
104
+ data["query"] = data.get("task")
102
105
  if not (env_frame := data.get("environment_frame", {})):
103
106
  return data
104
107
  state = env_frame.get("state", {}).get("state", {})
105
- data["job_id"] = cast(UUID, state.get("id")) if state.get("id") else None
108
+ data["task_id"] = cast(UUID, state.get("id")) if state.get("id") else None
106
109
  if not (metadata := data.get("metadata", {})):
107
110
  return data
108
111
  data["environment_name"] = metadata.get("environment_name")
@@ -110,7 +113,7 @@ class JobResponse(BaseModel):
110
113
  return data
111
114
 
112
115
 
113
- class PQAJobResponse(JobResponse):
116
+ class PQATaskResponse(TaskResponse):
114
117
  model_config = ConfigDict(extra="ignore")
115
118
 
116
119
  answer: str | None = None
@@ -143,15 +146,15 @@ class PQAJobResponse(JobResponse):
143
146
 
144
147
  return data
145
148
 
146
- def clean_verbose(self) -> "JobResponse":
149
+ def clean_verbose(self) -> "TaskResponse":
147
150
  """Clean the verbose response from the server."""
148
151
  self.request = None
149
152
  self.response = None
150
153
  return self
151
154
 
152
155
 
153
- class JobResponseVerbose(JobResponse):
154
- """Class for responses to include all the fields of a job response."""
156
+ class TaskResponseVerbose(TaskResponse):
157
+ """Class for responses to include all the fields of a task response."""
155
158
 
156
159
  model_config = ConfigDict(extra="allow")
157
160
 
@@ -330,66 +333,66 @@ class RestClient:
330
333
  path: Path that was searched for files
331
334
 
332
335
  Raises:
333
- JobFetchError: If no files were found
336
+ TaskFetchError: If no files were found
334
337
 
335
338
  """
336
339
  if not files:
337
- raise JobFetchError(f"No files found in {path}")
340
+ raise TaskFetchError(f"No files found in {path}")
338
341
 
339
342
  @retry(
340
343
  stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
341
344
  wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
342
345
  retry=retry_if_exception_type(Timeout),
343
346
  )
344
- def get_job(
345
- self, job_id: str | None = None, history: bool = False, verbose: bool = False
346
- ) -> "JobResponse":
347
- """Get details for a specific job."""
347
+ def get_task(
348
+ self, task_id: str | None = None, history: bool = False, verbose: bool = False
349
+ ) -> "TaskResponse":
350
+ """Get details for a specific task."""
348
351
  try:
349
- job_id = job_id or self.trajectory_id
352
+ task_id = task_id or self.trajectory_id
350
353
  response = self.client.get(
351
- f"/v0.1/trajectories/{job_id}",
354
+ f"/v0.1/trajectories/{task_id}",
352
355
  params={"history": history},
353
356
  )
354
357
  response.raise_for_status()
355
- verbose_response = JobResponseVerbose(**response.json())
358
+ verbose_response = TaskResponseVerbose(**response.json())
356
359
  if verbose:
357
360
  return verbose_response
358
361
  if any(
359
362
  JobNames.from_string(job_name) in verbose_response.job_name
360
363
  for job_name in ["crow", "falcon", "owl", "dummy"]
361
364
  ):
362
- return PQAJobResponse(**response.json())
363
- return JobResponse(**response.json())
365
+ return PQATaskResponse(**response.json())
366
+ return TaskResponse(**response.json())
364
367
  except ValueError as e:
365
- raise ValueError("Invalid job ID format. Must be a valid UUID.") from e
368
+ raise ValueError("Invalid task ID format. Must be a valid UUID.") from e
366
369
  except Exception as e:
367
- raise JobFetchError(f"Error getting job: {e!s}") from e
370
+ raise TaskFetchError(f"Error getting task: {e!s}") from e
368
371
 
369
372
  @retry(
370
373
  stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
371
374
  wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
372
375
  retry=retry_if_exception_type(Timeout),
373
376
  )
374
- def create_job(self, job_data: JobRequest | dict[str, Any]):
375
- """Create a new futurehouse job."""
376
- if isinstance(job_data, dict):
377
- job_data = JobRequest.model_validate(job_data)
378
-
379
- if isinstance(job_data.name, JobNames):
380
- job_data.name = job_data.name.from_stage(
381
- job_data.name.name,
377
+ def create_task(self, task_data: TaskRequest | dict[str, Any]):
378
+ """Create a new futurehouse task."""
379
+ if isinstance(task_data, dict):
380
+ task_data = TaskRequest.model_validate(task_data)
381
+
382
+ if isinstance(task_data.name, JobNames):
383
+ task_data.name = task_data.name.from_stage(
384
+ task_data.name.name,
382
385
  self.stage,
383
386
  )
384
387
 
385
388
  try:
386
389
  response = self.client.post(
387
- "/v0.1/crows", json=job_data.model_dump(mode="json")
390
+ "/v0.1/crows", json=task_data.model_dump(mode="json")
388
391
  )
389
392
  response.raise_for_status()
390
393
  self.trajectory_id = response.json()["trajectory_id"]
391
394
  except Exception as e:
392
- raise JobFetchError(f"Error creating job: {e!s}") from e
395
+ raise TaskFetchError(f"Error creating task: {e!s}") from e
393
396
  return self.trajectory_id
394
397
 
395
398
  @retry(
@@ -405,17 +408,16 @@ class RestClient:
405
408
  return response.json()
406
409
 
407
410
  # 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.
409
411
  @retry(
410
412
  stop=stop_after_attempt(MAX_RETRY_ATTEMPTS),
411
413
  wait=wait_exponential(multiplier=RETRY_MULTIPLIER, max=MAX_RETRY_WAIT),
412
414
  retry=retry_if_exception_type(Timeout),
413
415
  )
414
- def create_crow(self, config: CrowDeploymentConfig) -> dict[str, Any]: # noqa: PLR0915
415
- """Creates a crow deployment from the environment and environment files.
416
+ def create_job(self, config: JobDeploymentConfig) -> dict[str, Any]: # noqa: PLR0915
417
+ """Creates a futurehouse job deployment from the environment and environment files.
416
418
 
417
419
  Args:
418
- config: Configuration object containing all necessary parameters for crow deployment.
420
+ config: Configuration object containing all necessary parameters for job deployment.
419
421
 
420
422
  Returns:
421
423
  A response object containing metadata of the build.
@@ -434,7 +436,7 @@ class RestClient:
434
436
  raise InvalidTaskDescriptionError(
435
437
  "Task description cannot be None or empty. Ensure your from_task environment function has a valid docstring."
436
438
  " If you are deploying with your Environment as a dependency, "
437
- "you must add a `task_description` to your `CrowDeploymentConfig`.",
439
+ "you must add a `task_description` to your `JobDeploymentConfig`.",
438
440
  )
439
441
  selected_org = OrganizationSelector.select_organization(self.organizations)
440
442
  if selected_org is None:
@@ -583,9 +585,11 @@ class RestClient:
583
585
  except HTTPStatusError as e:
584
586
  error_detail = response.json()
585
587
  error_message = error_detail.get("detail", str(e))
586
- raise JobFetchError(f"Server validation error: {error_message}") from e
588
+ raise JobCreationError(
589
+ f"Server validation error: {error_message}"
590
+ ) from e
587
591
  except Exception as e:
588
- raise JobFetchError(f"Error generating docker image: {e!s}") from e
592
+ raise JobCreationError(f"Error generating docker image: {e!s}") from e
589
593
  return build_context
590
594
 
591
595
 
@@ -1,21 +1,21 @@
1
1
  from .app import (
2
2
  AuthType,
3
- CrowDeploymentConfig,
4
3
  DockerContainerConfiguration,
5
4
  FramePath,
6
- JobRequest,
5
+ JobDeploymentConfig,
7
6
  RuntimeConfig,
8
7
  Stage,
9
8
  Step,
9
+ TaskRequest,
10
10
  )
11
11
 
12
12
  __all__ = [
13
13
  "AuthType",
14
- "CrowDeploymentConfig",
15
14
  "DockerContainerConfiguration",
16
15
  "FramePath",
17
- "JobRequest",
16
+ "JobDeploymentConfig",
18
17
  "RuntimeConfig",
19
18
  "Stage",
20
19
  "Step",
20
+ "TaskRequest",
21
21
  ]
@@ -342,7 +342,7 @@ class DockerContainerConfiguration(BaseModel):
342
342
  return self
343
343
 
344
344
 
345
- class CrowDeploymentConfig(BaseModel):
345
+ class JobDeploymentConfig(BaseModel):
346
346
  model_config = ConfigDict(
347
347
  extra="forbid",
348
348
  arbitrary_types_allowed=True, # Allows for agent: Agent | str
@@ -581,7 +581,7 @@ class RuntimeConfig(BaseModel):
581
581
  default=None,
582
582
  description=(
583
583
  "Agent configuration to use for this job. If None, it will default to the "
584
- "agent selected during Crow deployment in the CrowDeploymentConfig object."
584
+ "agent selected during Crow deployment in the JobDeploymentConfig object."
585
585
  ),
586
586
  )
587
587
  continued_job_id: UUID | None = Field(
@@ -607,10 +607,10 @@ class RuntimeConfig(BaseModel):
607
607
  return value
608
608
 
609
609
 
610
- class JobRequest(BaseModel):
611
- job_id: UUID | None = Field(
610
+ class TaskRequest(BaseModel):
611
+ task_id: UUID | None = Field(
612
612
  default=None,
613
- description="Optional job identifier",
613
+ description="Optional task identifier",
614
614
  alias="id",
615
615
  )
616
616
  name: "str | JobNames" = Field(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: futurehouse-client
3
- Version: 0.0.2
3
+ Version: 0.0.3
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
  Classifier: Operating System :: OS Independent
@@ -70,7 +70,7 @@ from aviary.core import DummyEnv
70
70
  import ldp
71
71
 
72
72
  client = CrowClient(
73
- stage=Stage.DEV,
73
+ stage=Stage.PROD,
74
74
  auth_type=AuthType.API_KEY,
75
75
  api_key="your_api_key",
76
76
  )
@@ -110,7 +110,7 @@ from crow_client import CrowClient
110
110
  from crow_client.models import Stage, AuthType
111
111
 
112
112
  client = CrowClient(
113
- stage=Stage.DEV,
113
+ stage=Stage.PROD,
114
114
  organization="your_organization",
115
115
  auth_type=AuthType.API_KEY,
116
116
  api_key="your_api_key",
@@ -150,7 +150,7 @@ from crow_client import CrowClient, JobNames
150
150
  from crow_client.models import AuthType, Stage
151
151
 
152
152
  client = CrowClient(
153
- stage=Stage.DEV,
153
+ stage=Stage.PROD,
154
154
  auth_type=AuthType.API_KEY,
155
155
  api_key="your_api_key",
156
156
  )
@@ -186,7 +186,7 @@ from crow_client import CrowClient, JobNames
186
186
  from crow_client.models import AuthType, Stage
187
187
 
188
188
  client = CrowClient(
189
- stage=Stage.DEV,
189
+ stage=Stage.PROD,
190
190
  auth_type=AuthType.API_KEY,
191
191
  api_key="your_api_key",
192
192
  )
@@ -0,0 +1,14 @@
1
+ futurehouse_client/__init__.py,sha256=ddxO7JE97c6bt7LjNglZZ2Ql8bYCGI9laSFeh9MP6VU,344
2
+ futurehouse_client/clients/__init__.py,sha256=tFWqwIAY5PvwfOVsCje4imjTpf6xXNRMh_UHIKVI1_0,320
3
+ futurehouse_client/clients/job_client.py,sha256=RNgdSJVI1vjQSypdfswHX0Gvv_XnKG4bZjklf3WdSuk,8828
4
+ futurehouse_client/clients/rest_client.py,sha256=xZs4cHVzuKu4X9xOlhqRN0EdEDP99sGp8cgx5gS8McM,25115
5
+ futurehouse_client/models/__init__.py,sha256=ta3jFLM_LsDz1rKDmx8rja8sT7WtSKoFvMgLF0yFpvA,342
6
+ futurehouse_client/models/app.py,sha256=G8_-I3aQnRIyxFJT3snTSWsPcZZ2nEvYkRaE5sVdeys,22299
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.3.dist-info/METADATA,sha256=SWITZXjP7BUoM4Ze6KAIvrcYLx8TCBKyUaJVEFyJgYw,8898
12
+ futurehouse_client-0.0.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
+ futurehouse_client-0.0.3.dist-info/top_level.txt,sha256=TRuLUCt_qBnggdFHCX4O_BoCu1j2X43lKfIZC-ElwWY,19
14
+ futurehouse_client-0.0.3.dist-info/RECORD,,
@@ -1,14 +0,0 @@
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,,