together 2.0.0a17__py3-none-any.whl → 2.0.0a18__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 (57) hide show
  1. together/_base_client.py +5 -2
  2. together/_client.py +1 -39
  3. together/_compat.py +3 -3
  4. together/_utils/_json.py +35 -0
  5. together/_version.py +1 -1
  6. together/lib/cli/api/endpoints/create.py +7 -3
  7. together/lib/cli/api/endpoints/hardware.py +37 -6
  8. together/lib/cli/api/models/upload.py +5 -1
  9. together/resources/__init__.py +0 -14
  10. together/resources/beta/__init__.py +14 -0
  11. together/resources/beta/beta.py +32 -0
  12. together/resources/beta/clusters/clusters.py +12 -12
  13. together/resources/beta/clusters/storage.py +10 -10
  14. together/resources/beta/jig/__init__.py +61 -0
  15. together/resources/beta/jig/jig.py +1024 -0
  16. together/resources/beta/jig/queue.py +482 -0
  17. together/resources/beta/jig/secrets.py +548 -0
  18. together/resources/beta/jig/volumes.py +514 -0
  19. together/resources/chat/completions.py +10 -0
  20. together/resources/models/__init__.py +33 -0
  21. together/resources/{models.py → models/models.py} +41 -9
  22. together/resources/models/uploads.py +163 -0
  23. together/types/__init__.py +0 -2
  24. together/types/beta/__init__.py +6 -0
  25. together/types/beta/deployment.py +261 -0
  26. together/types/beta/deployment_logs.py +11 -0
  27. together/types/beta/jig/__init__.py +20 -0
  28. together/types/beta/jig/queue_cancel_params.py +13 -0
  29. together/types/beta/jig/queue_cancel_response.py +11 -0
  30. together/types/beta/jig/queue_metrics_params.py +12 -0
  31. together/types/beta/jig/queue_metrics_response.py +8 -0
  32. together/types/beta/jig/queue_retrieve_params.py +15 -0
  33. together/types/beta/jig/queue_retrieve_response.py +35 -0
  34. together/types/beta/jig/queue_submit_params.py +19 -0
  35. together/types/beta/jig/queue_submit_response.py +25 -0
  36. together/types/beta/jig/secret.py +33 -0
  37. together/types/beta/jig/secret_create_params.py +34 -0
  38. together/types/beta/jig/secret_list_response.py +16 -0
  39. together/types/beta/jig/secret_update_params.py +34 -0
  40. together/types/beta/jig/volume.py +47 -0
  41. together/types/beta/jig/volume_create_params.py +34 -0
  42. together/types/beta/jig/volume_list_response.py +16 -0
  43. together/types/beta/jig/volume_update_params.py +34 -0
  44. together/types/beta/jig_deploy_params.py +150 -0
  45. together/types/beta/jig_list_response.py +16 -0
  46. together/types/beta/jig_retrieve_logs_params.py +15 -0
  47. together/types/beta/jig_update_params.py +141 -0
  48. together/types/chat/completion_create_params.py +11 -0
  49. together/types/models/__init__.py +5 -0
  50. together/types/{job_retrieve_response.py → models/upload_status_response.py} +3 -3
  51. {together-2.0.0a17.dist-info → together-2.0.0a18.dist-info}/METADATA +11 -14
  52. {together-2.0.0a17.dist-info → together-2.0.0a18.dist-info}/RECORD +55 -25
  53. together/resources/jobs.py +0 -214
  54. together/types/job_list_response.py +0 -47
  55. {together-2.0.0a17.dist-info → together-2.0.0a18.dist-info}/WHEEL +0 -0
  56. {together-2.0.0a17.dist-info → together-2.0.0a18.dist-info}/entry_points.txt +0 -0
  57. {together-2.0.0a17.dist-info → together-2.0.0a18.dist-info}/licenses/LICENSE +0 -0
together/_base_client.py CHANGED
@@ -86,6 +86,7 @@ from ._exceptions import (
86
86
  APIConnectionError,
87
87
  APIResponseValidationError,
88
88
  )
89
+ from ._utils._json import openapi_dumps
89
90
 
90
91
  log: logging.Logger = logging.getLogger(__name__)
91
92
 
@@ -554,8 +555,10 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
554
555
  kwargs["content"] = options.content
555
556
  elif isinstance(json_data, bytes):
556
557
  kwargs["content"] = json_data
557
- else:
558
- kwargs["json"] = json_data if is_given(json_data) else None
558
+ elif not files:
559
+ # Don't set content when JSON is sent as multipart/form-data,
560
+ # since httpx's content param overrides other body arguments
561
+ kwargs["content"] = openapi_dumps(json_data) if is_given(json_data) and json_data is not None else None
559
562
  kwargs["files"] = files
560
563
  else:
561
564
  headers.pop("Content-Type", None)
together/_client.py CHANGED
@@ -37,7 +37,6 @@ if TYPE_CHECKING:
37
37
  from .resources import (
38
38
  beta,
39
39
  chat,
40
- jobs,
41
40
  audio,
42
41
  evals,
43
42
  files,
@@ -53,11 +52,9 @@ if TYPE_CHECKING:
53
52
  fine_tuning,
54
53
  code_interpreter,
55
54
  )
56
- from .resources.jobs import JobsResource, AsyncJobsResource
57
55
  from .resources.evals import EvalsResource, AsyncEvalsResource
58
56
  from .resources.files import FilesResource, AsyncFilesResource
59
57
  from .resources.images import ImagesResource, AsyncImagesResource
60
- from .resources.models import ModelsResource, AsyncModelsResource
61
58
  from .resources.rerank import RerankResource, AsyncRerankResource
62
59
  from .resources.videos import VideosResource, AsyncVideosResource
63
60
  from .resources.batches import BatchesResource, AsyncBatchesResource
@@ -69,6 +66,7 @@ if TYPE_CHECKING:
69
66
  from .resources.audio.audio import AudioResource, AsyncAudioResource
70
67
  from .resources.completions import CompletionsResource, AsyncCompletionsResource
71
68
  from .resources.fine_tuning import FineTuningResource, AsyncFineTuningResource
69
+ from .resources.models.models import ModelsResource, AsyncModelsResource
72
70
  from .resources.code_interpreter.code_interpreter import CodeInterpreterResource, AsyncCodeInterpreterResource
73
71
 
74
72
  __all__ = [
@@ -209,12 +207,6 @@ class Together(SyncAPIClient):
209
207
 
210
208
  return ModelsResource(self)
211
209
 
212
- @cached_property
213
- def jobs(self) -> JobsResource:
214
- from .resources.jobs import JobsResource
215
-
216
- return JobsResource(self)
217
-
218
210
  @cached_property
219
211
  def endpoints(self) -> EndpointsResource:
220
212
  from .resources.endpoints import EndpointsResource
@@ -486,12 +478,6 @@ class AsyncTogether(AsyncAPIClient):
486
478
 
487
479
  return AsyncModelsResource(self)
488
480
 
489
- @cached_property
490
- def jobs(self) -> AsyncJobsResource:
491
- from .resources.jobs import AsyncJobsResource
492
-
493
- return AsyncJobsResource(self)
494
-
495
481
  @cached_property
496
482
  def endpoints(self) -> AsyncEndpointsResource:
497
483
  from .resources.endpoints import AsyncEndpointsResource
@@ -709,12 +695,6 @@ class TogetherWithRawResponse:
709
695
 
710
696
  return ModelsResourceWithRawResponse(self._client.models)
711
697
 
712
- @cached_property
713
- def jobs(self) -> jobs.JobsResourceWithRawResponse:
714
- from .resources.jobs import JobsResourceWithRawResponse
715
-
716
- return JobsResourceWithRawResponse(self._client.jobs)
717
-
718
698
  @cached_property
719
699
  def endpoints(self) -> endpoints.EndpointsResourceWithRawResponse:
720
700
  from .resources.endpoints import EndpointsResourceWithRawResponse
@@ -818,12 +798,6 @@ class AsyncTogetherWithRawResponse:
818
798
 
819
799
  return AsyncModelsResourceWithRawResponse(self._client.models)
820
800
 
821
- @cached_property
822
- def jobs(self) -> jobs.AsyncJobsResourceWithRawResponse:
823
- from .resources.jobs import AsyncJobsResourceWithRawResponse
824
-
825
- return AsyncJobsResourceWithRawResponse(self._client.jobs)
826
-
827
801
  @cached_property
828
802
  def endpoints(self) -> endpoints.AsyncEndpointsResourceWithRawResponse:
829
803
  from .resources.endpoints import AsyncEndpointsResourceWithRawResponse
@@ -927,12 +901,6 @@ class TogetherWithStreamedResponse:
927
901
 
928
902
  return ModelsResourceWithStreamingResponse(self._client.models)
929
903
 
930
- @cached_property
931
- def jobs(self) -> jobs.JobsResourceWithStreamingResponse:
932
- from .resources.jobs import JobsResourceWithStreamingResponse
933
-
934
- return JobsResourceWithStreamingResponse(self._client.jobs)
935
-
936
904
  @cached_property
937
905
  def endpoints(self) -> endpoints.EndpointsResourceWithStreamingResponse:
938
906
  from .resources.endpoints import EndpointsResourceWithStreamingResponse
@@ -1036,12 +1004,6 @@ class AsyncTogetherWithStreamedResponse:
1036
1004
 
1037
1005
  return AsyncModelsResourceWithStreamingResponse(self._client.models)
1038
1006
 
1039
- @cached_property
1040
- def jobs(self) -> jobs.AsyncJobsResourceWithStreamingResponse:
1041
- from .resources.jobs import AsyncJobsResourceWithStreamingResponse
1042
-
1043
- return AsyncJobsResourceWithStreamingResponse(self._client.jobs)
1044
-
1045
1007
  @cached_property
1046
1008
  def endpoints(self) -> endpoints.AsyncEndpointsResourceWithStreamingResponse:
1047
1009
  from .resources.endpoints import AsyncEndpointsResourceWithStreamingResponse
together/_compat.py CHANGED
@@ -139,6 +139,7 @@ def model_dump(
139
139
  exclude_defaults: bool = False,
140
140
  warnings: bool = True,
141
141
  mode: Literal["json", "python"] = "python",
142
+ by_alias: bool | None = None,
142
143
  ) -> dict[str, Any]:
143
144
  if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
144
145
  return model.model_dump(
@@ -148,13 +149,12 @@ def model_dump(
148
149
  exclude_defaults=exclude_defaults,
149
150
  # warnings are not supported in Pydantic v1
150
151
  warnings=True if PYDANTIC_V1 else warnings,
152
+ by_alias=by_alias,
151
153
  )
152
154
  return cast(
153
155
  "dict[str, Any]",
154
156
  model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
155
- exclude=exclude,
156
- exclude_unset=exclude_unset,
157
- exclude_defaults=exclude_defaults,
157
+ exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias)
158
158
  ),
159
159
  )
160
160
 
@@ -0,0 +1,35 @@
1
+ import json
2
+ from typing import Any
3
+ from datetime import datetime
4
+ from typing_extensions import override
5
+
6
+ import pydantic
7
+
8
+ from .._compat import model_dump
9
+
10
+
11
+ def openapi_dumps(obj: Any) -> bytes:
12
+ """
13
+ Serialize an object to UTF-8 encoded JSON bytes.
14
+
15
+ Extends the standard json.dumps with support for additional types
16
+ commonly used in the SDK, such as `datetime`, `pydantic.BaseModel`, etc.
17
+ """
18
+ return json.dumps(
19
+ obj,
20
+ cls=_CustomEncoder,
21
+ # Uses the same defaults as httpx's JSON serialization
22
+ ensure_ascii=False,
23
+ separators=(",", ":"),
24
+ allow_nan=False,
25
+ ).encode()
26
+
27
+
28
+ class _CustomEncoder(json.JSONEncoder):
29
+ @override
30
+ def default(self, o: Any) -> Any:
31
+ if isinstance(o, datetime):
32
+ return o.isoformat()
33
+ if isinstance(o, pydantic.BaseModel):
34
+ return model_dump(o, exclude_unset=True, mode="json", by_alias=True)
35
+ return super().default(o)
together/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "together"
4
- __version__ = "2.0.0-alpha.17" # x-release-please-version
4
+ __version__ = "2.0.0-alpha.18" # x-release-please-version
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import sys
4
4
 
5
5
  import click
6
- from rich import print
7
6
 
8
7
  from together import APIError, Together, omit
9
8
  from together.lib.cli.api._utils import handle_api_errors
@@ -124,8 +123,13 @@ def create(
124
123
  extra_query={"availability_zone": availability_zone or omit},
125
124
  )
126
125
  except APIError as e:
127
- if "check the hardware api" in str(e.args[0]).lower() or "invalid hardware provided" in str(e.args[0]).lower():
128
- print("Invalid hardware provided")
126
+ if (
127
+ "check the hardware api" in str(e.args[0]).lower()
128
+ or "invalid hardware provided" in str(e.args[0]).lower()
129
+ or "the selected configuration" in str(e.args[0]).lower()
130
+ ):
131
+ click.secho("Invalid hardware selected.", fg="red", err=True)
132
+ click.echo("\nAvailable hardware options:")
129
133
  ctx.invoke(hardware, available=True, model=model, json=False)
130
134
  sys.exit(1)
131
135
  raise e
@@ -1,10 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import re
3
4
  import json as json_lib
5
+ from typing import Any, Dict, List
4
6
 
5
7
  import click
8
+ from tabulate import tabulate
6
9
 
7
10
  from together import Together, omit
11
+ from together.types import HardwareListResponse
8
12
  from together.lib.cli.api._utils import handle_api_errors
9
13
  from together.lib.utils.serializer import datetime_serializer
10
14
 
@@ -21,20 +25,47 @@ from together.lib.utils.serializer import datetime_serializer
21
25
  @handle_api_errors("Endpoints")
22
26
  def hardware(client: Together, model: str | None, json: bool, available: bool) -> None:
23
27
  """List all available hardware options, optionally filtered by model."""
24
- message = "Available hardware options:" if available else "All hardware options:"
25
- click.echo(message, err=True)
26
28
  hardware_options = client.hardware.list(model=model or omit)
27
- # hardware_options = client.endpoints.list_hardware(model)
29
+
28
30
  if available:
29
31
  hardware_options.data = [
30
32
  hardware
31
33
  for hardware in hardware_options.data
32
34
  if hardware.availability is not None and hardware.availability.status == "available"
33
35
  ]
34
-
35
36
  if json:
36
37
  json_output = [hardware.model_dump() for hardware in hardware_options.data]
37
38
  click.echo(json_lib.dumps(json_output, default=datetime_serializer, indent=2))
38
39
  else:
39
- for hardware in hardware_options.data:
40
- click.echo(f" {hardware.id}", err=True)
40
+ _format_hardware_options(hardware_options, show_availability=model is not None)
41
+
42
+
43
+ def _format_hardware_options(hardware_options: HardwareListResponse, show_availability: bool = True) -> None:
44
+ display_list: List[Dict[str, Any]] = []
45
+
46
+ for hw in hardware_options.data:
47
+ data = {
48
+ "Hardware ID": hw.id,
49
+ "GPU": re.sub(r"\-\d+[a-zA-Z][a-zA-Z]$", "", hw.specs.gpu_type)
50
+ if hw.specs and hw.specs.gpu_type
51
+ else "N/A",
52
+ "Memory": f"{int(hw.specs.gpu_memory)}GB" if hw.specs else "N/A",
53
+ "Count": hw.specs.gpu_count if hw.specs else "N/A",
54
+ "Price (per minute)": (f"${hw.pricing.cents_per_minute / 100:.2f}" if hw.pricing else "N/A"),
55
+ }
56
+
57
+ if show_availability:
58
+ status_display = "—"
59
+ if hw.availability:
60
+ status = hw.availability.status
61
+ # Add visual indicators for status
62
+ if status == "available":
63
+ status_display = click.style("✓ available", fg="green")
64
+ elif status == "unavailable":
65
+ status_display = click.style("✗ unavailable", fg="red")
66
+ else: # insufficient
67
+ status_display = click.style("⚠ insufficient", fg="yellow")
68
+ data["availability"] = status_display
69
+ display_list.append(data)
70
+
71
+ click.echo(tabulate(display_list, headers="keys", numalign="left"))
@@ -3,7 +3,7 @@ from typing import Literal, Optional
3
3
 
4
4
  import click
5
5
 
6
- from together import Together, omit
6
+ from together import Together, TogetherError, omit
7
7
  from together._response import APIResponse as APIResponse
8
8
  from together.lib.cli.api._utils import handle_api_errors
9
9
  from together.types.model_upload_response import ModelUploadResponse
@@ -76,6 +76,10 @@ def upload(
76
76
  if json:
77
77
  click.echo(json_lib.dumps(response.model_dump(), indent=2))
78
78
  else:
79
+ # If the model weights already exist, the api is returning 200 but with no data
80
+ if response.data is None: # type: ignore
81
+ raise TogetherError(response.message)
82
+
79
83
  click.echo(f"Model upload job created successfully!")
80
84
  if response.data.job_id:
81
85
  click.echo(f"Job ID: {response.data.job_id}")
@@ -16,14 +16,6 @@ from .chat import (
16
16
  ChatResourceWithStreamingResponse,
17
17
  AsyncChatResourceWithStreamingResponse,
18
18
  )
19
- from .jobs import (
20
- JobsResource,
21
- AsyncJobsResource,
22
- JobsResourceWithRawResponse,
23
- AsyncJobsResourceWithRawResponse,
24
- JobsResourceWithStreamingResponse,
25
- AsyncJobsResourceWithStreamingResponse,
26
- )
27
19
  from .audio import (
28
20
  AudioResource,
29
21
  AsyncAudioResource,
@@ -204,12 +196,6 @@ __all__ = [
204
196
  "AsyncModelsResourceWithRawResponse",
205
197
  "ModelsResourceWithStreamingResponse",
206
198
  "AsyncModelsResourceWithStreamingResponse",
207
- "JobsResource",
208
- "AsyncJobsResource",
209
- "JobsResourceWithRawResponse",
210
- "AsyncJobsResourceWithRawResponse",
211
- "JobsResourceWithStreamingResponse",
212
- "AsyncJobsResourceWithStreamingResponse",
213
199
  "EndpointsResource",
214
200
  "AsyncEndpointsResource",
215
201
  "EndpointsResourceWithRawResponse",
@@ -1,5 +1,13 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
+ from .jig import (
4
+ JigResource,
5
+ AsyncJigResource,
6
+ JigResourceWithRawResponse,
7
+ AsyncJigResourceWithRawResponse,
8
+ JigResourceWithStreamingResponse,
9
+ AsyncJigResourceWithStreamingResponse,
10
+ )
3
11
  from .beta import (
4
12
  BetaResource,
5
13
  AsyncBetaResource,
@@ -18,6 +26,12 @@ from .clusters import (
18
26
  )
19
27
 
20
28
  __all__ = [
29
+ "JigResource",
30
+ "AsyncJigResource",
31
+ "JigResourceWithRawResponse",
32
+ "AsyncJigResourceWithRawResponse",
33
+ "JigResourceWithStreamingResponse",
34
+ "AsyncJigResourceWithStreamingResponse",
21
35
  "ClustersResource",
22
36
  "AsyncClustersResource",
23
37
  "ClustersResourceWithRawResponse",
@@ -2,6 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from .jig.jig import (
6
+ JigResource,
7
+ AsyncJigResource,
8
+ JigResourceWithRawResponse,
9
+ AsyncJigResourceWithRawResponse,
10
+ JigResourceWithStreamingResponse,
11
+ AsyncJigResourceWithStreamingResponse,
12
+ )
5
13
  from ..._compat import cached_property
6
14
  from ..._resource import SyncAPIResource, AsyncAPIResource
7
15
  from .clusters.clusters import (
@@ -17,6 +25,10 @@ __all__ = ["BetaResource", "AsyncBetaResource"]
17
25
 
18
26
 
19
27
  class BetaResource(SyncAPIResource):
28
+ @cached_property
29
+ def jig(self) -> JigResource:
30
+ return JigResource(self._client)
31
+
20
32
  @cached_property
21
33
  def clusters(self) -> ClustersResource:
22
34
  return ClustersResource(self._client)
@@ -42,6 +54,10 @@ class BetaResource(SyncAPIResource):
42
54
 
43
55
 
44
56
  class AsyncBetaResource(AsyncAPIResource):
57
+ @cached_property
58
+ def jig(self) -> AsyncJigResource:
59
+ return AsyncJigResource(self._client)
60
+
45
61
  @cached_property
46
62
  def clusters(self) -> AsyncClustersResource:
47
63
  return AsyncClustersResource(self._client)
@@ -70,6 +86,10 @@ class BetaResourceWithRawResponse:
70
86
  def __init__(self, beta: BetaResource) -> None:
71
87
  self._beta = beta
72
88
 
89
+ @cached_property
90
+ def jig(self) -> JigResourceWithRawResponse:
91
+ return JigResourceWithRawResponse(self._beta.jig)
92
+
73
93
  @cached_property
74
94
  def clusters(self) -> ClustersResourceWithRawResponse:
75
95
  return ClustersResourceWithRawResponse(self._beta.clusters)
@@ -79,6 +99,10 @@ class AsyncBetaResourceWithRawResponse:
79
99
  def __init__(self, beta: AsyncBetaResource) -> None:
80
100
  self._beta = beta
81
101
 
102
+ @cached_property
103
+ def jig(self) -> AsyncJigResourceWithRawResponse:
104
+ return AsyncJigResourceWithRawResponse(self._beta.jig)
105
+
82
106
  @cached_property
83
107
  def clusters(self) -> AsyncClustersResourceWithRawResponse:
84
108
  return AsyncClustersResourceWithRawResponse(self._beta.clusters)
@@ -88,6 +112,10 @@ class BetaResourceWithStreamingResponse:
88
112
  def __init__(self, beta: BetaResource) -> None:
89
113
  self._beta = beta
90
114
 
115
+ @cached_property
116
+ def jig(self) -> JigResourceWithStreamingResponse:
117
+ return JigResourceWithStreamingResponse(self._beta.jig)
118
+
91
119
  @cached_property
92
120
  def clusters(self) -> ClustersResourceWithStreamingResponse:
93
121
  return ClustersResourceWithStreamingResponse(self._beta.clusters)
@@ -97,6 +125,10 @@ class AsyncBetaResourceWithStreamingResponse:
97
125
  def __init__(self, beta: AsyncBetaResource) -> None:
98
126
  self._beta = beta
99
127
 
128
+ @cached_property
129
+ def jig(self) -> AsyncJigResourceWithStreamingResponse:
130
+ return AsyncJigResourceWithStreamingResponse(self._beta.jig)
131
+
100
132
  @cached_property
101
133
  def clusters(self) -> AsyncClustersResourceWithStreamingResponse:
102
134
  return AsyncClustersResourceWithStreamingResponse(self._beta.clusters)
@@ -110,7 +110,7 @@ class ClustersResource(SyncAPIResource):
110
110
  timeout: Override the client-level default timeout for this request, in seconds
111
111
  """
112
112
  return self._post(
113
- "/clusters",
113
+ "/compute/clusters",
114
114
  body=maybe_transform(
115
115
  {
116
116
  "billing_type": billing_type,
@@ -158,7 +158,7 @@ class ClustersResource(SyncAPIResource):
158
158
  if not cluster_id:
159
159
  raise ValueError(f"Expected a non-empty value for `cluster_id` but received {cluster_id!r}")
160
160
  return self._get(
161
- f"/clusters/{cluster_id}",
161
+ f"/compute/clusters/{cluster_id}",
162
162
  options=make_request_options(
163
163
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
164
164
  ),
@@ -193,7 +193,7 @@ class ClustersResource(SyncAPIResource):
193
193
  if not cluster_id:
194
194
  raise ValueError(f"Expected a non-empty value for `cluster_id` but received {cluster_id!r}")
195
195
  return self._put(
196
- f"/clusters/{cluster_id}",
196
+ f"/compute/clusters/{cluster_id}",
197
197
  body=maybe_transform(
198
198
  {
199
199
  "cluster_type": cluster_type,
@@ -219,7 +219,7 @@ class ClustersResource(SyncAPIResource):
219
219
  ) -> ClusterListResponse:
220
220
  """List all GPU clusters."""
221
221
  return self._get(
222
- "/clusters",
222
+ "/compute/clusters",
223
223
  options=make_request_options(
224
224
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
225
225
  ),
@@ -252,7 +252,7 @@ class ClustersResource(SyncAPIResource):
252
252
  if not cluster_id:
253
253
  raise ValueError(f"Expected a non-empty value for `cluster_id` but received {cluster_id!r}")
254
254
  return self._delete(
255
- f"/clusters/{cluster_id}",
255
+ f"/compute/clusters/{cluster_id}",
256
256
  options=make_request_options(
257
257
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
258
258
  ),
@@ -271,7 +271,7 @@ class ClustersResource(SyncAPIResource):
271
271
  ) -> ClusterListRegionsResponse:
272
272
  """List regions and corresponding supported driver versions"""
273
273
  return self._get(
274
- "/clusters/regions",
274
+ "/compute/regions",
275
275
  options=make_request_options(
276
276
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
277
277
  ),
@@ -355,7 +355,7 @@ class AsyncClustersResource(AsyncAPIResource):
355
355
  timeout: Override the client-level default timeout for this request, in seconds
356
356
  """
357
357
  return await self._post(
358
- "/clusters",
358
+ "/compute/clusters",
359
359
  body=await async_maybe_transform(
360
360
  {
361
361
  "billing_type": billing_type,
@@ -403,7 +403,7 @@ class AsyncClustersResource(AsyncAPIResource):
403
403
  if not cluster_id:
404
404
  raise ValueError(f"Expected a non-empty value for `cluster_id` but received {cluster_id!r}")
405
405
  return await self._get(
406
- f"/clusters/{cluster_id}",
406
+ f"/compute/clusters/{cluster_id}",
407
407
  options=make_request_options(
408
408
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
409
409
  ),
@@ -438,7 +438,7 @@ class AsyncClustersResource(AsyncAPIResource):
438
438
  if not cluster_id:
439
439
  raise ValueError(f"Expected a non-empty value for `cluster_id` but received {cluster_id!r}")
440
440
  return await self._put(
441
- f"/clusters/{cluster_id}",
441
+ f"/compute/clusters/{cluster_id}",
442
442
  body=await async_maybe_transform(
443
443
  {
444
444
  "cluster_type": cluster_type,
@@ -464,7 +464,7 @@ class AsyncClustersResource(AsyncAPIResource):
464
464
  ) -> ClusterListResponse:
465
465
  """List all GPU clusters."""
466
466
  return await self._get(
467
- "/clusters",
467
+ "/compute/clusters",
468
468
  options=make_request_options(
469
469
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
470
470
  ),
@@ -497,7 +497,7 @@ class AsyncClustersResource(AsyncAPIResource):
497
497
  if not cluster_id:
498
498
  raise ValueError(f"Expected a non-empty value for `cluster_id` but received {cluster_id!r}")
499
499
  return await self._delete(
500
- f"/clusters/{cluster_id}",
500
+ f"/compute/clusters/{cluster_id}",
501
501
  options=make_request_options(
502
502
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
503
503
  ),
@@ -516,7 +516,7 @@ class AsyncClustersResource(AsyncAPIResource):
516
516
  ) -> ClusterListRegionsResponse:
517
517
  """List regions and corresponding supported driver versions"""
518
518
  return await self._get(
519
- "/clusters/regions",
519
+ "/compute/regions",
520
520
  options=make_request_options(
521
521
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
522
522
  ),
@@ -77,7 +77,7 @@ class StorageResource(SyncAPIResource):
77
77
  timeout: Override the client-level default timeout for this request, in seconds
78
78
  """
79
79
  return self._post(
80
- "/clusters/storages",
80
+ "/compute/clusters/storage/volumes",
81
81
  body=maybe_transform(
82
82
  {
83
83
  "region": region,
@@ -118,7 +118,7 @@ class StorageResource(SyncAPIResource):
118
118
  if not volume_id:
119
119
  raise ValueError(f"Expected a non-empty value for `volume_id` but received {volume_id!r}")
120
120
  return self._get(
121
- f"/clusters/storages/{volume_id}",
121
+ f"/compute/clusters/storage/volumes/{volume_id}",
122
122
  options=make_request_options(
123
123
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
124
124
  ),
@@ -150,7 +150,7 @@ class StorageResource(SyncAPIResource):
150
150
  timeout: Override the client-level default timeout for this request, in seconds
151
151
  """
152
152
  return self._put(
153
- "/clusters/storages",
153
+ "/compute/clusters/storage/volumes",
154
154
  body=maybe_transform(
155
155
  {
156
156
  "size_tib": size_tib,
@@ -176,7 +176,7 @@ class StorageResource(SyncAPIResource):
176
176
  ) -> StorageListResponse:
177
177
  """List all shared volumes."""
178
178
  return self._get(
179
- "/clusters/storages",
179
+ "/compute/clusters/storage/volumes",
180
180
  options=make_request_options(
181
181
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
182
182
  ),
@@ -211,7 +211,7 @@ class StorageResource(SyncAPIResource):
211
211
  if not volume_id:
212
212
  raise ValueError(f"Expected a non-empty value for `volume_id` but received {volume_id!r}")
213
213
  return self._delete(
214
- f"/clusters/storages/{volume_id}",
214
+ f"/compute/clusters/storage/volumes/{volume_id}",
215
215
  options=make_request_options(
216
216
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
217
217
  ),
@@ -273,7 +273,7 @@ class AsyncStorageResource(AsyncAPIResource):
273
273
  timeout: Override the client-level default timeout for this request, in seconds
274
274
  """
275
275
  return await self._post(
276
- "/clusters/storages",
276
+ "/compute/clusters/storage/volumes",
277
277
  body=await async_maybe_transform(
278
278
  {
279
279
  "region": region,
@@ -314,7 +314,7 @@ class AsyncStorageResource(AsyncAPIResource):
314
314
  if not volume_id:
315
315
  raise ValueError(f"Expected a non-empty value for `volume_id` but received {volume_id!r}")
316
316
  return await self._get(
317
- f"/clusters/storages/{volume_id}",
317
+ f"/compute/clusters/storage/volumes/{volume_id}",
318
318
  options=make_request_options(
319
319
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
320
320
  ),
@@ -346,7 +346,7 @@ class AsyncStorageResource(AsyncAPIResource):
346
346
  timeout: Override the client-level default timeout for this request, in seconds
347
347
  """
348
348
  return await self._put(
349
- "/clusters/storages",
349
+ "/compute/clusters/storage/volumes",
350
350
  body=await async_maybe_transform(
351
351
  {
352
352
  "size_tib": size_tib,
@@ -372,7 +372,7 @@ class AsyncStorageResource(AsyncAPIResource):
372
372
  ) -> StorageListResponse:
373
373
  """List all shared volumes."""
374
374
  return await self._get(
375
- "/clusters/storages",
375
+ "/compute/clusters/storage/volumes",
376
376
  options=make_request_options(
377
377
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
378
378
  ),
@@ -407,7 +407,7 @@ class AsyncStorageResource(AsyncAPIResource):
407
407
  if not volume_id:
408
408
  raise ValueError(f"Expected a non-empty value for `volume_id` but received {volume_id!r}")
409
409
  return await self._delete(
410
- f"/clusters/storages/{volume_id}",
410
+ f"/compute/clusters/storage/volumes/{volume_id}",
411
411
  options=make_request_options(
412
412
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
413
413
  ),