skypilot-nightly 1.0.0.dev20250718__py3-none-any.whl → 1.0.0.dev20250723__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 skypilot-nightly might be problematic. Click here for more details.

Files changed (160) hide show
  1. sky/__init__.py +4 -2
  2. sky/admin_policy.py +11 -4
  3. sky/backends/backend_utils.py +50 -24
  4. sky/backends/cloud_vm_ray_backend.py +41 -38
  5. sky/catalog/__init__.py +3 -1
  6. sky/catalog/aws_catalog.py +8 -5
  7. sky/catalog/azure_catalog.py +8 -5
  8. sky/catalog/common.py +8 -2
  9. sky/catalog/cudo_catalog.py +5 -2
  10. sky/catalog/do_catalog.py +4 -1
  11. sky/catalog/fluidstack_catalog.py +5 -2
  12. sky/catalog/gcp_catalog.py +8 -5
  13. sky/catalog/hyperbolic_catalog.py +5 -2
  14. sky/catalog/ibm_catalog.py +8 -5
  15. sky/catalog/lambda_catalog.py +8 -5
  16. sky/catalog/nebius_catalog.py +8 -5
  17. sky/catalog/oci_catalog.py +8 -5
  18. sky/catalog/paperspace_catalog.py +4 -1
  19. sky/catalog/runpod_catalog.py +5 -2
  20. sky/catalog/scp_catalog.py +8 -5
  21. sky/catalog/vast_catalog.py +5 -2
  22. sky/catalog/vsphere_catalog.py +4 -1
  23. sky/client/cli/command.py +63 -25
  24. sky/client/sdk.py +61 -11
  25. sky/clouds/aws.py +12 -7
  26. sky/clouds/azure.py +12 -7
  27. sky/clouds/cloud.py +9 -8
  28. sky/clouds/cudo.py +13 -7
  29. sky/clouds/do.py +12 -7
  30. sky/clouds/fluidstack.py +11 -6
  31. sky/clouds/gcp.py +12 -7
  32. sky/clouds/hyperbolic.py +11 -6
  33. sky/clouds/ibm.py +11 -6
  34. sky/clouds/kubernetes.py +7 -3
  35. sky/clouds/lambda_cloud.py +11 -6
  36. sky/clouds/nebius.py +14 -12
  37. sky/clouds/oci.py +12 -7
  38. sky/clouds/paperspace.py +12 -7
  39. sky/clouds/runpod.py +12 -7
  40. sky/clouds/scp.py +11 -6
  41. sky/clouds/vast.py +14 -8
  42. sky/clouds/vsphere.py +11 -6
  43. sky/core.py +6 -1
  44. sky/dashboard/out/404.html +1 -1
  45. sky/dashboard/out/_next/static/chunks/{1043-734e57d2b27dfe5d.js → 1043-869d9c78bf5dd3df.js} +1 -1
  46. sky/dashboard/out/_next/static/chunks/{1141-d8c6404a7c6fffe6.js → 1141-e49a159c30a6c4a7.js} +1 -1
  47. sky/dashboard/out/_next/static/chunks/1559-18717d96ef2fcbe9.js +30 -0
  48. sky/dashboard/out/_next/static/chunks/1871-ea0e7283886407ca.js +6 -0
  49. sky/dashboard/out/_next/static/chunks/2003.b82e6db40ec4c463.js +1 -0
  50. sky/dashboard/out/_next/static/chunks/2350.23778a2b19aabd33.js +1 -0
  51. sky/dashboard/out/_next/static/chunks/2369.2d6e4757f8dfc2b7.js +15 -0
  52. sky/dashboard/out/_next/static/chunks/{2641.35edc9ccaeaad9e3.js → 2641.74c19c4d45a2c034.js} +1 -1
  53. sky/dashboard/out/_next/static/chunks/3785.59705416215ff08b.js +1 -0
  54. sky/dashboard/out/_next/static/chunks/{4725.4c849b1e05c8e9ad.js → 4725.66125dcd9832aa5d.js} +1 -1
  55. sky/dashboard/out/_next/static/chunks/4869.da729a7db3a31f43.js +16 -0
  56. sky/dashboard/out/_next/static/chunks/4937.d75809403fc264ac.js +15 -0
  57. sky/dashboard/out/_next/static/chunks/6135-2abbd0352f8ee061.js +1 -0
  58. sky/dashboard/out/_next/static/chunks/691.488b4aef97c28727.js +55 -0
  59. sky/dashboard/out/_next/static/chunks/6990-f64e03df359e04f7.js +1 -0
  60. sky/dashboard/out/_next/static/chunks/7411-2cc31dc0fdf2a9ad.js +41 -0
  61. sky/dashboard/out/_next/static/chunks/9025.4a9099bdf3ed4875.js +6 -0
  62. sky/dashboard/out/_next/static/chunks/938-7ee806653aef0609.js +1 -0
  63. sky/dashboard/out/_next/static/chunks/9847.387abf8a14d722db.js +30 -0
  64. sky/dashboard/out/_next/static/chunks/{9984.2b5e3fa69171bff9.js → 9984.0460de9d3adf5582.js} +1 -1
  65. sky/dashboard/out/_next/static/chunks/pages/_app-da491665d4289aae.js +34 -0
  66. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/{[job]-fa406155b4223d0d.js → [job]-2186770cc2de1623.js} +2 -2
  67. sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-0c37ee1ac5f3474d.js → [cluster]-95afb019ab85801c.js} +1 -1
  68. sky/dashboard/out/_next/static/chunks/pages/clusters-3d4be4961e1c94eb.js +1 -0
  69. sky/dashboard/out/_next/static/chunks/pages/index-89e7daf7b7df02e0.js +1 -0
  70. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-a90b4fe4616dc501.js +1 -0
  71. sky/dashboard/out/_next/static/chunks/pages/infra-0d3d1f890c5d188a.js +1 -0
  72. sky/dashboard/out/_next/static/chunks/pages/jobs/{[job]-c5b357bfd9502fbe.js → [job]-dc0299ffefebcdbe.js} +2 -2
  73. sky/dashboard/out/_next/static/chunks/pages/jobs-49f790d12a85027c.js +1 -0
  74. sky/dashboard/out/_next/static/chunks/pages/{users-19e98664bdd61643.js → users-6790fcefd5487b13.js} +1 -1
  75. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-6bcd4b20914d76c9.js +1 -0
  76. sky/dashboard/out/_next/static/chunks/pages/workspaces-5f7fe4b7d55b8612.js +1 -0
  77. sky/dashboard/out/_next/static/chunks/webpack-a305898dc479711e.js +1 -0
  78. sky/dashboard/out/_next/static/css/b3227360726f12eb.css +3 -0
  79. sky/dashboard/out/_next/static/mym3Ciwp-zqU7ZpOLGnrW/_buildManifest.js +1 -0
  80. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  81. sky/dashboard/out/clusters/[cluster].html +1 -1
  82. sky/dashboard/out/clusters.html +1 -1
  83. sky/dashboard/out/config.html +1 -1
  84. sky/dashboard/out/index.html +1 -1
  85. sky/dashboard/out/infra/[context].html +1 -1
  86. sky/dashboard/out/infra.html +1 -1
  87. sky/dashboard/out/jobs/[job].html +1 -1
  88. sky/dashboard/out/jobs.html +1 -1
  89. sky/dashboard/out/users.html +1 -1
  90. sky/dashboard/out/volumes.html +1 -1
  91. sky/dashboard/out/workspace/new.html +1 -1
  92. sky/dashboard/out/workspaces/[name].html +1 -1
  93. sky/dashboard/out/workspaces.html +1 -1
  94. sky/data/mounting_utils.py +93 -32
  95. sky/global_user_state.py +12 -143
  96. sky/jobs/state.py +9 -88
  97. sky/jobs/utils.py +28 -13
  98. sky/provision/nebius/utils.py +3 -6
  99. sky/schemas/db/README +4 -0
  100. sky/schemas/db/env.py +90 -0
  101. sky/schemas/db/global_user_state/001_initial_schema.py +124 -0
  102. sky/schemas/db/script.py.mako +28 -0
  103. sky/schemas/db/spot_jobs/001_initial_schema.py +97 -0
  104. sky/serve/client/sdk.py +6 -2
  105. sky/serve/controller.py +7 -3
  106. sky/serve/serve_state.py +1 -1
  107. sky/serve/serve_utils.py +171 -75
  108. sky/serve/server/core.py +17 -6
  109. sky/server/common.py +4 -3
  110. sky/server/requests/payloads.py +2 -0
  111. sky/server/requests/requests.py +1 -1
  112. sky/setup_files/MANIFEST.in +2 -0
  113. sky/setup_files/alembic.ini +148 -0
  114. sky/setup_files/dependencies.py +1 -0
  115. sky/skylet/configs.py +1 -1
  116. sky/skylet/constants.py +4 -0
  117. sky/skylet/job_lib.py +1 -1
  118. sky/skypilot_config.py +1 -1
  119. sky/users/permission.py +1 -1
  120. sky/utils/common_utils.py +85 -3
  121. sky/utils/config_utils.py +15 -0
  122. sky/utils/db/__init__.py +0 -0
  123. sky/utils/{db_utils.py → db/db_utils.py} +59 -0
  124. sky/utils/db/migration_utils.py +93 -0
  125. sky/utils/locks.py +319 -0
  126. sky/utils/schemas.py +38 -34
  127. sky/utils/timeline.py +41 -0
  128. {skypilot_nightly-1.0.0.dev20250718.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/METADATA +2 -1
  129. {skypilot_nightly-1.0.0.dev20250718.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/RECORD +134 -125
  130. sky/dashboard/out/_next/static/FUjweqdImyeYhMYFON-Se/_buildManifest.js +0 -1
  131. sky/dashboard/out/_next/static/chunks/1746.27d40aedc22bd2d6.js +0 -60
  132. sky/dashboard/out/_next/static/chunks/1871-76491ac174a95278.js +0 -6
  133. sky/dashboard/out/_next/static/chunks/2544.27f70672535675ed.js +0 -1
  134. sky/dashboard/out/_next/static/chunks/2875.c24c6d57dc82e436.js +0 -25
  135. sky/dashboard/out/_next/static/chunks/3785.95b94f18aaec7233.js +0 -1
  136. sky/dashboard/out/_next/static/chunks/3947-b059261d6fa88a1f.js +0 -35
  137. sky/dashboard/out/_next/static/chunks/430.ed51037d1a4a438b.js +0 -1
  138. sky/dashboard/out/_next/static/chunks/4869.bdd42f14b51d1d6f.js +0 -16
  139. sky/dashboard/out/_next/static/chunks/5491.918ffed0ba7a5294.js +0 -20
  140. sky/dashboard/out/_next/static/chunks/6990-dcb411b566e64cde.js +0 -1
  141. sky/dashboard/out/_next/static/chunks/804-9f5e98ce84d46bdd.js +0 -21
  142. sky/dashboard/out/_next/static/chunks/9025.133e9ba5c780afeb.js +0 -6
  143. sky/dashboard/out/_next/static/chunks/938-6a9ffdaa21eee969.js +0 -1
  144. sky/dashboard/out/_next/static/chunks/9470-b6f6a35283863a6f.js +0 -1
  145. sky/dashboard/out/_next/static/chunks/9847.46e613d000c55859.js +0 -30
  146. sky/dashboard/out/_next/static/chunks/pages/_app-771a40cde532309b.js +0 -20
  147. sky/dashboard/out/_next/static/chunks/pages/clusters-102d169e87913ba1.js +0 -1
  148. sky/dashboard/out/_next/static/chunks/pages/index-927ddeebe57a8ac3.js +0 -1
  149. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-8b0809f59034d509.js +0 -1
  150. sky/dashboard/out/_next/static/chunks/pages/infra-ae9d2f705ce582c9.js +0 -1
  151. sky/dashboard/out/_next/static/chunks/pages/jobs-5bbdc71878f0a068.js +0 -1
  152. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-7c0187f43757a548.js +0 -1
  153. sky/dashboard/out/_next/static/chunks/pages/workspaces-a1e43d9ef51a9cea.js +0 -1
  154. sky/dashboard/out/_next/static/chunks/webpack-6b0575ea521af4f3.js +0 -1
  155. sky/dashboard/out/_next/static/css/219887b94512388c.css +0 -3
  156. /sky/dashboard/out/_next/static/{FUjweqdImyeYhMYFON-Se → mym3Ciwp-zqU7ZpOLGnrW}/_ssgManifest.js +0 -0
  157. {skypilot_nightly-1.0.0.dev20250718.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/WHEEL +0 -0
  158. {skypilot_nightly-1.0.0.dev20250718.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/entry_points.txt +0 -0
  159. {skypilot_nightly-1.0.0.dev20250718.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/licenses/LICENSE +0 -0
  160. {skypilot_nightly-1.0.0.dev20250718.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/top_level.txt +0 -0
sky/clouds/fluidstack.py CHANGED
@@ -154,14 +154,17 @@ class Fluidstack(clouds.Cloud):
154
154
  return 'Fluidstack'
155
155
 
156
156
  @classmethod
157
- def get_default_instance_type(
158
- cls,
159
- cpus: Optional[str] = None,
160
- memory: Optional[str] = None,
161
- disk_tier: Optional[DiskTier] = None) -> Optional[str]:
157
+ def get_default_instance_type(cls,
158
+ cpus: Optional[str] = None,
159
+ memory: Optional[str] = None,
160
+ disk_tier: Optional[DiskTier] = None,
161
+ region: Optional[str] = None,
162
+ zone: Optional[str] = None) -> Optional[str]:
162
163
  return catalog.get_default_instance_type(cpus=cpus,
163
164
  memory=memory,
164
165
  disk_tier=disk_tier,
166
+ region=region,
167
+ zone=zone,
165
168
  clouds='fluidstack')
166
169
 
167
170
  @classmethod
@@ -243,7 +246,9 @@ class Fluidstack(clouds.Cloud):
243
246
  default_instance_type = Fluidstack.get_default_instance_type(
244
247
  cpus=resources.cpus,
245
248
  memory=resources.memory,
246
- disk_tier=resources.disk_tier)
249
+ disk_tier=resources.disk_tier,
250
+ region=resources.region,
251
+ zone=resources.zone)
247
252
  if default_instance_type is None:
248
253
  return resources_utils.FeasibleResources([], [], None)
249
254
  else:
sky/clouds/gcp.py CHANGED
@@ -436,15 +436,18 @@ class GCP(clouds.Cloud):
436
436
  return cls._get_image_size(image_id)
437
437
 
438
438
  @classmethod
439
- def get_default_instance_type(
440
- cls,
441
- cpus: Optional[str] = None,
442
- memory: Optional[str] = None,
443
- disk_tier: Optional[resources_utils.DiskTier] = None
444
- ) -> Optional[str]:
439
+ def get_default_instance_type(cls,
440
+ cpus: Optional[str] = None,
441
+ memory: Optional[str] = None,
442
+ disk_tier: Optional[
443
+ resources_utils.DiskTier] = None,
444
+ region: Optional[str] = None,
445
+ zone: Optional[str] = None) -> Optional[str]:
445
446
  return catalog.get_default_instance_type(cpus=cpus,
446
447
  memory=memory,
447
448
  disk_tier=disk_tier,
449
+ region=region,
450
+ zone=zone,
448
451
  clouds='gcp')
449
452
 
450
453
  @classmethod
@@ -681,7 +684,9 @@ class GCP(clouds.Cloud):
681
684
  host_vm_type = GCP.get_default_instance_type(
682
685
  cpus=resources.cpus,
683
686
  memory=resources.memory,
684
- disk_tier=resources.disk_tier)
687
+ disk_tier=resources.disk_tier,
688
+ region=resources.region,
689
+ zone=resources.zone)
685
690
  if host_vm_type is None:
686
691
  # TODO: Add hints to all return values in this method to help
687
692
  # users understand why the resources are not launchable.
sky/clouds/hyperbolic.py CHANGED
@@ -109,14 +109,17 @@ class Hyperbolic(clouds.Cloud):
109
109
  clouds='hyperbolic')
110
110
 
111
111
  @classmethod
112
- def get_default_instance_type(
113
- cls,
114
- cpus: Optional[str] = None,
115
- memory: Optional[str] = None,
116
- disk_tier: Optional[DiskTier] = None) -> Optional[str]:
112
+ def get_default_instance_type(cls,
113
+ cpus: Optional[str] = None,
114
+ memory: Optional[str] = None,
115
+ disk_tier: Optional[DiskTier] = None,
116
+ region: Optional[str] = None,
117
+ zone: Optional[str] = None) -> Optional[str]:
117
118
  return catalog.get_default_instance_type(cpus=cpus,
118
119
  memory=memory,
119
120
  disk_tier=disk_tier,
121
+ region=region,
122
+ zone=zone,
120
123
  clouds='hyperbolic')
121
124
 
122
125
  @classmethod
@@ -199,7 +202,9 @@ class Hyperbolic(clouds.Cloud):
199
202
  default_instance_type = self.get_default_instance_type(
200
203
  cpus=resources.cpus,
201
204
  memory=resources.memory,
202
- disk_tier=resources.disk_tier)
205
+ disk_tier=resources.disk_tier,
206
+ region=resources.region,
207
+ zone=resources.zone)
203
208
  if default_instance_type is None:
204
209
  return resources_utils.FeasibleResources([], [], None)
205
210
  else:
sky/clouds/ibm.py CHANGED
@@ -262,14 +262,17 @@ class IBM(clouds.Cloud):
262
262
 
263
263
  @classmethod
264
264
  def get_default_instance_type(
265
- cls,
266
- cpus: Optional[str] = None,
267
- memory: Optional[str] = None,
268
- disk_tier: Optional['resources_utils.DiskTier'] = None
269
- ) -> Optional[str]:
265
+ cls,
266
+ cpus: Optional[str] = None,
267
+ memory: Optional[str] = None,
268
+ disk_tier: Optional['resources_utils.DiskTier'] = None,
269
+ region: Optional[str] = None,
270
+ zone: Optional[str] = None) -> Optional[str]:
270
271
  return catalog.get_default_instance_type(cpus=cpus,
271
272
  memory=memory,
272
273
  disk_tier=disk_tier,
274
+ region=region,
275
+ zone=zone,
273
276
  clouds='ibm')
274
277
 
275
278
  def _get_feasible_launchable_resources(
@@ -305,7 +308,9 @@ class IBM(clouds.Cloud):
305
308
  default_instance_type = IBM.get_default_instance_type(
306
309
  cpus=resources.cpus,
307
310
  memory=resources.memory,
308
- disk_tier=resources.disk_tier)
311
+ disk_tier=resources.disk_tier,
312
+ region=resources.region,
313
+ zone=resources.zone)
309
314
  if default_instance_type is None:
310
315
  return resources_utils.FeasibleResources([], [], None)
311
316
  else:
sky/clouds/kubernetes.py CHANGED
@@ -349,10 +349,12 @@ class Kubernetes(clouds.Cloud):
349
349
  cls,
350
350
  cpus: Optional[str] = None,
351
351
  memory: Optional[str] = None,
352
- disk_tier: Optional['resources_utils.DiskTier'] = None) -> str:
352
+ disk_tier: Optional['resources_utils.DiskTier'] = None,
353
+ region: Optional[str] = None,
354
+ zone: Optional[str] = None) -> str:
353
355
  # TODO(romilb): In the future, we may want to move the instance type
354
356
  # selection + availability checking to a kubernetes_catalog module.
355
- del disk_tier # Unused.
357
+ del disk_tier, region, zone # Unused.
356
358
  # We strip '+' from resource requests since Kubernetes can provision
357
359
  # exactly the requested resources.
358
360
  instance_cpus = float(
@@ -806,7 +808,9 @@ class Kubernetes(clouds.Cloud):
806
808
  default_instance_type = Kubernetes.get_default_instance_type(
807
809
  cpus=resources.cpus,
808
810
  memory=resources.memory,
809
- disk_tier=resources.disk_tier)
811
+ disk_tier=resources.disk_tier,
812
+ region=resources.region,
813
+ zone=resources.zone)
810
814
 
811
815
  if accelerators is None:
812
816
  # For CPU only clusters, need no special handling
@@ -132,14 +132,17 @@ class Lambda(clouds.Cloud):
132
132
 
133
133
  @classmethod
134
134
  def get_default_instance_type(
135
- cls,
136
- cpus: Optional[str] = None,
137
- memory: Optional[str] = None,
138
- disk_tier: Optional['resources_utils.DiskTier'] = None
139
- ) -> Optional[str]:
135
+ cls,
136
+ cpus: Optional[str] = None,
137
+ memory: Optional[str] = None,
138
+ disk_tier: Optional['resources_utils.DiskTier'] = None,
139
+ region: Optional[str] = None,
140
+ zone: Optional[str] = None) -> Optional[str]:
140
141
  return catalog.get_default_instance_type(cpus=cpus,
141
142
  memory=memory,
142
143
  disk_tier=disk_tier,
144
+ region=region,
145
+ zone=zone,
143
146
  clouds='lambda')
144
147
 
145
148
  @classmethod
@@ -227,7 +230,9 @@ class Lambda(clouds.Cloud):
227
230
  default_instance_type = Lambda.get_default_instance_type(
228
231
  cpus=resources.cpus,
229
232
  memory=resources.memory,
230
- disk_tier=resources.disk_tier)
233
+ disk_tier=resources.disk_tier,
234
+ region=resources.region,
235
+ zone=resources.zone)
231
236
  if default_instance_type is None:
232
237
  return resources_utils.FeasibleResources([], [], None)
233
238
  else:
sky/clouds/nebius.py CHANGED
@@ -175,16 +175,19 @@ class Nebius(clouds.Cloud):
175
175
  return isinstance(other, Nebius)
176
176
 
177
177
  @classmethod
178
- def get_default_instance_type(
179
- cls,
180
- cpus: Optional[str] = None,
181
- memory: Optional[str] = None,
182
- disk_tier: Optional[resources_utils.DiskTier] = None
183
- ) -> Optional[str]:
178
+ def get_default_instance_type(cls,
179
+ cpus: Optional[str] = None,
180
+ memory: Optional[str] = None,
181
+ disk_tier: Optional[
182
+ resources_utils.DiskTier] = None,
183
+ region: Optional[str] = None,
184
+ zone: Optional[str] = None) -> Optional[str]:
184
185
  """Returns the default instance type for Nebius."""
185
186
  return catalog.get_default_instance_type(cpus=cpus,
186
187
  memory=memory,
187
188
  disk_tier=disk_tier,
189
+ region=region,
190
+ zone=zone,
188
191
  clouds='nebius')
189
192
 
190
193
  @classmethod
@@ -231,11 +234,8 @@ class Nebius(clouds.Cloud):
231
234
 
232
235
  config_fs = skypilot_config.get_effective_region_config(
233
236
  cloud='nebius',
234
- region=None,
235
- keys=(
236
- region.name,
237
- 'filesystems',
238
- ),
237
+ region=region.name,
238
+ keys=('filesystems',),
239
239
  default_value=[])
240
240
  resources_vars_fs = []
241
241
  for i, fs in enumerate(config_fs):
@@ -320,7 +320,9 @@ class Nebius(clouds.Cloud):
320
320
  default_instance_type = Nebius.get_default_instance_type(
321
321
  cpus=resources.cpus,
322
322
  memory=resources.memory,
323
- disk_tier=resources.disk_tier)
323
+ disk_tier=resources.disk_tier,
324
+ region=resources.region,
325
+ zone=resources.zone)
324
326
  if default_instance_type is None:
325
327
  # TODO: Add hints to all return values in this method to help
326
328
  # users understand why the resources are not launchable.
sky/clouds/oci.py CHANGED
@@ -187,15 +187,18 @@ class OCI(clouds.Cloud):
187
187
  return (num_gigabytes - 10 * 1024) * 0.0085
188
188
 
189
189
  @classmethod
190
- def get_default_instance_type(
191
- cls,
192
- cpus: Optional[str] = None,
193
- memory: Optional[str] = None,
194
- disk_tier: Optional[resources_utils.DiskTier] = None
195
- ) -> Optional[str]:
190
+ def get_default_instance_type(cls,
191
+ cpus: Optional[str] = None,
192
+ memory: Optional[str] = None,
193
+ disk_tier: Optional[
194
+ resources_utils.DiskTier] = None,
195
+ region: Optional[str] = None,
196
+ zone: Optional[str] = None) -> Optional[str]:
196
197
  return catalog.get_default_instance_type(cpus=cpus,
197
198
  memory=memory,
198
199
  disk_tier=disk_tier,
200
+ region=region,
201
+ zone=zone,
199
202
  clouds='oci')
200
203
 
201
204
  @classmethod
@@ -378,7 +381,9 @@ class OCI(clouds.Cloud):
378
381
  default_instance_type = OCI.get_default_instance_type(
379
382
  cpus=resources.cpus,
380
383
  memory=resources.memory,
381
- disk_tier=resources.disk_tier)
384
+ disk_tier=resources.disk_tier,
385
+ region=resources.region,
386
+ zone=resources.zone)
382
387
 
383
388
  if default_instance_type is None:
384
389
  return resources_utils.FeasibleResources([], [], None)
sky/clouds/paperspace.py CHANGED
@@ -160,16 +160,19 @@ class Paperspace(clouds.Cloud):
160
160
  return self._REPR
161
161
 
162
162
  @classmethod
163
- def get_default_instance_type(
164
- cls,
165
- cpus: Optional[str] = None,
166
- memory: Optional[str] = None,
167
- disk_tier: Optional[resources_utils.DiskTier] = None,
168
- ) -> Optional[str]:
163
+ def get_default_instance_type(cls,
164
+ cpus: Optional[str] = None,
165
+ memory: Optional[str] = None,
166
+ disk_tier: Optional[
167
+ resources_utils.DiskTier] = None,
168
+ region: Optional[str] = None,
169
+ zone: Optional[str] = None) -> Optional[str]:
169
170
  """Returns the default instance type for Paperspace."""
170
171
  return catalog.get_default_instance_type(cpus=cpus,
171
172
  memory=memory,
172
173
  disk_tier=disk_tier,
174
+ region=region,
175
+ zone=zone,
173
176
  clouds='paperspace')
174
177
 
175
178
  @classmethod
@@ -237,7 +240,9 @@ class Paperspace(clouds.Cloud):
237
240
  default_instance_type = Paperspace.get_default_instance_type(
238
241
  cpus=resources.cpus,
239
242
  memory=resources.memory,
240
- disk_tier=resources.disk_tier)
243
+ disk_tier=resources.disk_tier,
244
+ region=resources.region,
245
+ zone=resources.zone)
241
246
  if default_instance_type is None:
242
247
  return resources_utils.FeasibleResources([], [], None)
243
248
  else:
sky/clouds/runpod.py CHANGED
@@ -141,16 +141,19 @@ class RunPod(clouds.Cloud):
141
141
  return 0.0
142
142
 
143
143
  @classmethod
144
- def get_default_instance_type(
145
- cls,
146
- cpus: Optional[str] = None,
147
- memory: Optional[str] = None,
148
- disk_tier: Optional[resources_utils.DiskTier] = None
149
- ) -> Optional[str]:
144
+ def get_default_instance_type(cls,
145
+ cpus: Optional[str] = None,
146
+ memory: Optional[str] = None,
147
+ disk_tier: Optional[
148
+ resources_utils.DiskTier] = None,
149
+ region: Optional[str] = None,
150
+ zone: Optional[str] = None) -> Optional[str]:
150
151
  """Returns the default instance type for RunPod."""
151
152
  return catalog.get_default_instance_type(cpus=cpus,
152
153
  memory=memory,
153
154
  disk_tier=disk_tier,
155
+ region=region,
156
+ zone=zone,
154
157
  clouds='runpod')
155
158
 
156
159
  @classmethod
@@ -240,7 +243,9 @@ class RunPod(clouds.Cloud):
240
243
  default_instance_type = RunPod.get_default_instance_type(
241
244
  cpus=resources.cpus,
242
245
  memory=resources.memory,
243
- disk_tier=resources.disk_tier)
246
+ disk_tier=resources.disk_tier,
247
+ region=resources.region,
248
+ zone=resources.zone)
244
249
  if default_instance_type is None:
245
250
  # TODO: Add hints to all return values in this method to help
246
251
  # users understand why the resources are not launchable.
sky/clouds/scp.py CHANGED
@@ -156,14 +156,17 @@ class SCP(clouds.Cloud):
156
156
 
157
157
  @classmethod
158
158
  def get_default_instance_type(
159
- cls,
160
- cpus: Optional[str] = None,
161
- memory: Optional[str] = None,
162
- disk_tier: Optional['resources_utils.DiskTier'] = None
163
- ) -> Optional[str]:
159
+ cls,
160
+ cpus: Optional[str] = None,
161
+ memory: Optional[str] = None,
162
+ disk_tier: Optional['resources_utils.DiskTier'] = None,
163
+ region: Optional[str] = None,
164
+ zone: Optional[str] = None) -> Optional[str]:
164
165
  return catalog.get_default_instance_type(cpus=cpus,
165
166
  memory=memory,
166
167
  disk_tier=disk_tier,
168
+ region=region,
169
+ zone=zone,
167
170
  clouds='scp')
168
171
 
169
172
  @classmethod
@@ -301,7 +304,9 @@ class SCP(clouds.Cloud):
301
304
  default_instance_type = SCP.get_default_instance_type(
302
305
  cpus=resources.cpus,
303
306
  memory=resources.memory,
304
- disk_tier=resources.disk_tier)
307
+ disk_tier=resources.disk_tier,
308
+ region=resources.region,
309
+ zone=resources.zone)
305
310
  if default_instance_type is None:
306
311
  return resources_utils.FeasibleResources([], [], None)
307
312
  else:
sky/clouds/vast.py CHANGED
@@ -136,16 +136,19 @@ class Vast(clouds.Cloud):
136
136
  return 0.0
137
137
 
138
138
  @classmethod
139
- def get_default_instance_type(
140
- cls,
141
- cpus: Optional[str] = None,
142
- memory: Optional[str] = None,
143
- disk_tier: Optional[resources_utils.DiskTier] = None
144
- ) -> Optional[str]:
139
+ def get_default_instance_type(cls,
140
+ cpus: Optional[str] = None,
141
+ memory: Optional[str] = None,
142
+ disk_tier: Optional[
143
+ resources_utils.DiskTier] = None,
144
+ region: Optional[str] = None,
145
+ zone: Optional[str] = None) -> Optional[str]:
145
146
  """Returns the default instance type for Vast."""
146
147
  return catalog.get_default_instance_type(cpus=cpus,
147
148
  memory=memory,
148
149
  disk_tier=disk_tier,
150
+ region=region,
151
+ zone=zone,
149
152
  clouds='vast')
150
153
 
151
154
  @classmethod
@@ -218,7 +221,9 @@ class Vast(clouds.Cloud):
218
221
  default_instance_type = Vast.get_default_instance_type(
219
222
  cpus=resources.cpus,
220
223
  memory=resources.memory,
221
- disk_tier=resources.disk_tier)
224
+ disk_tier=resources.disk_tier,
225
+ region=resources.region,
226
+ zone=resources.zone)
222
227
  if default_instance_type is None:
223
228
  # TODO: Add hints to all return values in this method to help
224
229
  # users understand why the resources are not launchable.
@@ -260,7 +265,8 @@ class Vast(clouds.Cloud):
260
265
  'error \n' # First line is indented by 4 spaces
261
266
  ' Credentials can be set up by running: \n'
262
267
  ' $ pip install vastai\n'
263
- ' $ echo [key] > ~/.vast_api_key\n'
268
+ ' $ mkdir -p ~/.config/vastai\n'
269
+ ' $ echo [key] > ~/.config/vastai/vast_api_key\n'
264
270
  ' For more information, see https://skypilot.readthedocs.io/en/latest/getting-started/installation.html#vast' # pylint: disable=line-too-long
265
271
  )
266
272
 
sky/clouds/vsphere.py CHANGED
@@ -149,15 +149,18 @@ class Vsphere(clouds.Cloud):
149
149
  return 'vSphere'
150
150
 
151
151
  @classmethod
152
- def get_default_instance_type(
153
- cls,
154
- cpus: Optional[str] = None,
155
- memory: Optional[str] = None,
156
- disk_tier: Optional[resources_utils.DiskTier] = None,
157
- ) -> Optional[str]:
152
+ def get_default_instance_type(cls,
153
+ cpus: Optional[str] = None,
154
+ memory: Optional[str] = None,
155
+ disk_tier: Optional[
156
+ resources_utils.DiskTier] = None,
157
+ region: Optional[str] = None,
158
+ zone: Optional[str] = None) -> Optional[str]:
158
159
  return catalog.get_default_instance_type(cpus=cpus,
159
160
  memory=memory,
160
161
  disk_tier=disk_tier,
162
+ region=region,
163
+ zone=zone,
161
164
  clouds=_CLOUD_VSPHERE)
162
165
 
163
166
  @classmethod
@@ -240,6 +243,8 @@ class Vsphere(clouds.Cloud):
240
243
  cpus=resources.cpus,
241
244
  memory=resources.memory,
242
245
  disk_tier=resources.disk_tier,
246
+ region=resources.region,
247
+ zone=resources.zone,
243
248
  )
244
249
  if default_instance_type is None:
245
250
  return resources_utils.FeasibleResources([], [], None)
sky/core.py CHANGED
@@ -944,7 +944,12 @@ def tail_logs(cluster_name: str,
944
944
  backend = backend_utils.get_backend_from_handle(handle)
945
945
 
946
946
  usage_lib.record_cluster_name_for_current_operation(cluster_name)
947
- return backend.tail_logs(handle, job_id, follow=follow, tail=tail)
947
+ # Although tail_logs returns an int when require_outputs=False (default),
948
+ # we need to check returnval as an int to avoid type checking errors.
949
+ returnval = backend.tail_logs(handle, job_id, follow=follow, tail=tail)
950
+ assert isinstance(returnval,
951
+ int), (f'returnval must be an int, but got {returnval}')
952
+ return returnval
948
953
 
949
954
 
950
955
  @usage_lib.entrypoint
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6b0575ea521af4f3.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c72a1f77a3c0be1b.js" defer=""></script><script src="/dashboard/_next/static/FUjweqdImyeYhMYFON-Se/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/FUjweqdImyeYhMYFON-Se/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"FUjweqdImyeYhMYFON-Se","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/b3227360726f12eb.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/b3227360726f12eb.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-a305898dc479711e.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-da491665d4289aae.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c72a1f77a3c0be1b.js" defer=""></script><script src="/dashboard/_next/static/mym3Ciwp-zqU7ZpOLGnrW/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/mym3Ciwp-zqU7ZpOLGnrW/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"mym3Ciwp-zqU7ZpOLGnrW","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1043],{326:function(e,t,a){a.d(t,{$N:function(){return p},Be:function(){return _},Vq:function(){return c},cN:function(){return f},cZ:function(){return d},fK:function(){return g}});var r=a(5893),s=a(7294),o=a(6327),n=a(2350),l=a(3767);let c=o.fC;o.xz;let u=o.h_;o.x8;let i=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.aV,{ref:t,className:(0,n.cn)("fixed inset-0 z-50 bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",a),...s})});i.displayName=o.aV.displayName;let d=s.forwardRef((e,t)=>{let{className:a,children:s,...c}=e;return(0,r.jsxs)(u,{children:[(0,r.jsx)(i,{}),(0,r.jsxs)(o.VY,{ref:t,className:(0,n.cn)("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-gray-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",a),...c,children:[s,(0,r.jsxs)(o.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-gray-100 data-[state=open]:text-gray-500",children:[(0,r.jsx)(l.Z,{className:"h-4 w-4"}),(0,r.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});d.displayName=o.VY.displayName;let g=e=>{let{className:t,...a}=e;return(0,r.jsx)("div",{className:(0,n.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...a})};g.displayName="DialogHeader";let f=e=>{let{className:t,...a}=e;return(0,r.jsx)("div",{className:(0,n.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...a})};f.displayName="DialogFooter";let p=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.Dx,{ref:t,className:(0,n.cn)("text-lg font-semibold leading-none tracking-tight",a),...s})});p.displayName=o.Dx.displayName;let _=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.dk,{ref:t,className:(0,n.cn)("text-sm text-gray-500",a),...s})});_.displayName=o.dk.displayName},3266:function(e,t,a){a.d(t,{QL:function(){return g},Sl:function(){return i},getClusters:function(){return c},uR:function(){return u}});var r=a(7294),s=a(5821),o=a(7145),n=a(6378);let l={UP:"RUNNING",STOPPED:"STOPPED",INIT:"LAUNCHING",null:"TERMINATED"};async function c(){let{clusterNames:e=null}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{return(await o.x.fetch("/status",{cluster_names:e,all_users:!0})).map(e=>{let t="",a=t=e.zone?e.zone:e.region;return t&&t.length>25&&(t=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:15;if(!e||e.length<=t)return e;if(t<=3)return"...";let a=Math.floor((t-3)/2),r=a+(t-3)%2;return 0===a?e.substring(0,r)+"...":e.substring(0,r)+"..."+e.substring(e.length-a)}(t,25)),{status:l[e.status],cluster:e.name,user:e.user_name,user_hash:e.user_hash,cloud:e.cloud,region:e.region,infra:t?e.cloud+" ("+t+")":e.cloud,full_infra:a?"".concat(e.cloud," (").concat(a,")"):e.cloud,cpus:e.cpus,mem:e.memory,gpus:e.accelerators,resources_str:e.resources_str,resources_str_full:e.resources_str_full,time:new Date(1e3*e.launched_at),num_nodes:e.nodes,workspace:e.workspace,autostop:e.autostop,to_down:e.to_down,jobs:[],command:e.last_creation_command||e.last_use,task_yaml:e.last_creation_yaml||"{}",events:[{time:new Date(1e3*e.launched_at),event:"Cluster created."}]}})}catch(e){return console.error("Error fetching clusters:",e),[]}}async function u(){try{let e=await o.x.fetch("/cost_report",{days:30});console.log("Raw cluster history data:",e);let t=e.map(e=>{let t="Unknown";e.cloud?t=e.cloud:e.resources&&e.resources.cloud&&(t=e.resources.cloud);let a=e.user_name||"-";return{status:e.status?l[e.status]:"TERMINATED",cluster:e.name,user:a,user_hash:e.user_hash,cloud:t,region:"",infra:t,full_infra:t,resources_str:e.resources_str,resources_str_full:e.resources_str_full,time:e.launched_at?new Date(1e3*e.launched_at):null,num_nodes:e.num_nodes||1,duration:e.duration,total_cost:e.total_cost,workspace:e.workspace||"default",autostop:-1,to_down:!1,cluster_hash:e.cluster_hash,usage_intervals:e.usage_intervals,command:e.last_creation_command||"",task_yaml:e.last_creation_yaml||"{}",events:[{time:e.launched_at?new Date(1e3*e.launched_at):new Date,event:"Cluster created."}]}});return console.log("Processed cluster history data:",t),t}catch(e){return console.error("Error fetching cluster history:",e),[]}}async function i(e){let{clusterName:t,jobId:a,onNewLog:r,workspace:n}=e;try{await o.x.stream("/logs",{follow:!1,cluster_name:t,job_id:a,override_skypilot_config:{active_workspace:n||"default"}},r)}catch(e){console.error("Error in streamClusterJobLogs:",e),(0,s.C)("Error in streamClusterJobLogs: ".concat(e.message),"error")}}async function d(e){let{clusterName:t,workspace:a}=e;try{return(await o.x.fetch("/queue",{cluster_name:t,all_users:!0,override_skypilot_config:{active_workspace:a}})).map(e=>{var r;let s=e.end_at?e.end_at:Date.now()/1e3,o=0,n=0;return e.submitted_at&&(o=s-e.submitted_at),e.start_at&&(n=s-e.start_at),{id:e.job_id,status:e.status,job:e.job_name,user:e.username,user_hash:e.user_hash,gpus:e.accelerators||{},submitted_at:e.submitted_at?new Date(1e3*e.submitted_at):null,resources:e.resources,cluster:t,total_duration:o,job_duration:n,infra:"",logs:"",workspace:a||"default",git_commit:(null===(r=e.metadata)||void 0===r?void 0:r.git_commit)||"-"}})}catch(e){return console.error("Error fetching cluster jobs:",e),[]}}function g(e){let{cluster:t,job:a=null}=e,[s,o]=(0,r.useState)(null),[l,u]=(0,r.useState)(null),[i,g]=(0,r.useState)(!0),[f,p]=(0,r.useState)(!0),_=(0,r.useCallback)(async()=>{if(t)try{g(!0);let e=await n.default.get(c,[{clusterNames:[t]}]);return o(e[0]),e[0]}catch(e){console.error("Error fetching cluster data:",e)}finally{g(!1)}return null},[t]),m=(0,r.useCallback)(async e=>{if(t)try{p(!0);let a=await n.default.get(d,[{clusterName:t,workspace:e||"default"}]);u(a)}catch(e){console.error("Error fetching cluster job data:",e)}finally{p(!1)}},[t]),h=(0,r.useCallback)(async()=>{n.default.invalidate(c,[{clusterNames:[t]}]);let e=await _();e&&(n.default.invalidate(d,[{clusterName:t,workspace:e.workspace||"default"}]),await m(e.workspace))},[_,m,t]),b=(0,r.useCallback)(async()=>{s&&(n.default.invalidate(d,[{clusterName:t,workspace:s.workspace||"default"}]),await m(s.workspace))},[m,s,t]);return(0,r.useEffect)(()=>{(async()=>{let e=await _();e&&m(e.workspace)})()},[t,a,_,m]),{clusterData:s,clusterJobData:l,loading:i,clusterDetailsLoading:i,clusterJobsLoading:f,refreshData:h,refreshClusterJobsOnly:b}}},2045:function(e,t,a){a.d(t,{l4:function(){return n}});var r=a(3225),s=a(7145);async function o(e,t){try{let a=[];try{let e=await s.x.get("/enabled_clouds"),t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("X-Request-ID"),r=await s.x.get("/api/get?request_id=".concat(t)),o=await r.json();a=o.return_value?JSON.parse(o.return_value):[],console.log("Enabled clouds:",a)}catch(e){console.error("Error fetching enabled clouds:",e),a=[]}let o={};r.$m.forEach(e=>{let t=a.includes(e.toLowerCase());o[e]={name:e,clusters:0,jobs:0,enabled:t}}),e.forEach(e=>{if(e.cloud){let t=e.cloud;o[t]&&(o[t].clusters+=1,o[t].enabled=!0)}}),t.forEach(e=>{if(e.cloud){let t=e.cloud;o[t]&&(o[t].jobs+=1,o[t].enabled=!0)}});let n=r.$m.length,l=Object.values(o).filter(e=>e.enabled).length;return{clouds:Object.values(o).filter(e=>e.enabled).sort((e,t)=>e.name.localeCompare(t.name)),totalClouds:n,enabledClouds:l}}catch(e){return console.error("Error fetching cloud infrastructure:",e),{clouds:[],totalClouds:r.$m.length,enabledClouds:0}}}async function n(){let{getClusters:e}=await Promise.resolve().then(a.bind(a,3266)),{getManagedJobs:t}=await Promise.resolve().then(a.bind(a,8969)),r=(await Promise.resolve().then(a.bind(a,6378))).default,[s,n]=await Promise.all([r.get(e),r.get(t,[{allUsers:!0}])]),c=s||[],u=(null==n?void 0:n.jobs)||[],[i,d]=await Promise.all([l(c,u),o(c,u)]);return{gpuData:i,cloudData:d}}async function l(e,t){return await g({clusters:e||[],jobs:t||[]})}async function c(){try{let e=await s.x.post("/realtime_kubernetes_gpu_availability",{context:null,name_filter:null,quantity_filter:null});if(!e.ok)return console.error("Error fetching Kubernetes context GPUs (in getKubernetesContextGPUs): ".concat(e.status," ").concat(e.statusText)),[];let t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("x-request-id");if(!t)return console.error("No request ID returned for Kubernetes GPU availability (in getKubernetesContextGPUs)"),[];let a=await s.x.get("/api/get?request_id=".concat(t)),r=await a.text();if(500===a.status){try{let e=JSON.parse(r);if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);console.error("[infra.jsx] getKubernetesContextGPUs: Server error detail:",t.message)}catch(t){console.error("[infra.jsx] getKubernetesContextGPUs: Error parsing server error JSON:",t,"Original error text:",e.detail.error)}}catch(e){console.error("[infra.jsx] getKubernetesContextGPUs: Error parsing 500 error response JSON:",e,"Raw text was:",r)}return[]}let o=JSON.parse(r);return o.return_value?JSON.parse(o.return_value):[]}catch(e){return console.error("[infra.jsx] Outer error in getKubernetesContextGPUs:",e),[]}}async function u(){try{let e=await s.x.get("/all_contexts");if(!e.ok)return console.error("Error fetching all contexts: ".concat(e.status," ").concat(e.statusText)),[];let t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("x-request-id");if(!t)return console.error("No request ID returned for /all_contexts"),[];let a=await s.x.get("/api/get?request_id=".concat(t)),r=await a.json();return r.return_value?JSON.parse(r.return_value):[]}catch(e){return console.error("[infra.jsx] Error in getAllContexts:",e),[]}}async function i(e){try{let t=await s.x.post("/kubernetes_node_info",{context:e}),a=t.headers.get("X-Skypilot-Request-ID")||t.headers.get("x-request-id"),r=await s.x.get("/api/get?request_id=".concat(a));if(500===r.status){try{let e=await r.json();if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);console.error("Error fetching Kubernetes per node GPUs:",t.message)}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{}}let o=await r.json();return(o.return_value?JSON.parse(o.return_value):{}).node_info_dict||{}}catch(t){return console.error("[infra.jsx] Error in getKubernetesPerNodeGPUs for context",e,":",t),{}}}async function d(e){try{let t=e.clusters,a=e.jobs,r={};return t.forEach(e=>{let t=null;if("Kubernetes"===e.cloud)(t=e.region)&&(t="kubernetes/".concat(t));else if("SSH"===e.cloud&&(t=e.region)){let e=t.startsWith("ssh-")?t.substring(4):t;t="ssh/".concat(e)}t&&(r[t]||(r[t]={clusters:0,jobs:0}),r[t].clusters+=1)}),a.forEach(e=>{let t=null;if("Kubernetes"===e.cloud)(t=e.region)&&(t="kubernetes/".concat(t));else if("SSH"===e.cloud&&(t=e.region)){let e=t.startsWith("ssh-")?t.substring(4):t;t="ssh/".concat(e)}t&&(r[t]||(r[t]={clusters:0,jobs:0}),r[t].jobs+=1)}),r}catch(e){return console.error("=== Error in getContextClustersAndJobs ===",e),{}}}async function g(e){try{let o=await u();if(!o||0===o.length)return console.log("No contexts found from /all_contexts endpoint."),{allContextNames:[],allGPUs:[],perContextGPUs:[],perNodeGPUs:[],contextStats:{}};let n=await d(e),l=await c(),g=new Map;l&&l.forEach(e=>{g.set(e[0],e[1])});let f={},p={},_={};for(let e of o){p[e]||(p[e]=[]);let o=g.get(e);if(o&&o.length>0)for(let t of o){let a=t[0],r=t[1].join(", "),s=t[2],o=t[3];a in f?(f[a].gpu_total+=s,f[a].gpu_free+=o):f[a]={gpu_total:s,gpu_free:o,gpu_name:a},p[e].push({gpu_name:a,gpu_requestable_qty_per_node:r,gpu_total:s,gpu_free:o,context:e})}let n=await i(e);if(n&&Object.keys(n).length>0)for(let o in n){var t,a,r,s;let l=n[o],c=l.accelerator_type||"-",u=null!==(r=null===(t=l.total)||void 0===t?void 0:t.accelerator_count)&&void 0!==r?r:0,i=null!==(s=null===(a=l.free)||void 0===a?void 0:a.accelerators_available)&&void 0!==s?s:0;_["".concat(e,"/").concat(o)]={node_name:l.name,gpu_name:c,gpu_total:u,gpu_free:i,ip_address:l.ip_address||null,context:e},"-"===c||p[e].some(e=>e.gpu_name===c)||(c in f||(f[c]={gpu_total:0,gpu_free:0,gpu_name:c}),p[e].find(e=>e.gpu_name===c)||p[e].push({gpu_name:c,gpu_requestable_qty_per_node:"-",gpu_total:0,gpu_free:0,context:e}))}0===p[e].length&&n&&Object.keys(n).length}return{allContextNames:o.sort(),allGPUs:Object.values(f).sort((e,t)=>e.gpu_name.localeCompare(t.gpu_name)),perContextGPUs:Object.values(p).flat().sort((e,t)=>e.context.localeCompare(t.context)||e.gpu_name.localeCompare(t.gpu_name)),perNodeGPUs:Object.values(_).sort((e,t)=>e.context.localeCompare(t.context)||e.node_name.localeCompare(t.node_name)||e.gpu_name.localeCompare(t.gpu_name)),contextStats:n}}catch(e){return console.error("[infra.jsx] Outer error in getKubernetesGPUs:",e),{allContextNames:[],allGPUs:[],perContextGPUs:[],perNodeGPUs:[],contextStats:{}}}}},3081:function(e,t,a){a.d(t,{R:function(){return s}}),a(3266),a(8969);var r=a(7145);async function s(){try{let e=await r.x.get("/users");if(!e.ok)throw Error("HTTP error! status: ".concat(e.status));return(await e.json()).map(e=>({userId:e.id,username:e.name,role:e.role,created_at:e.created_at}))||[]}catch(e){return console.error("Failed to fetch users:",e),[]}}},9238:function(e,t,a){a.d(t,{C:function(){return s},w:function(){return o}});var r=a(7145);async function s(){try{return(await r.x.fetch("/volumes",{},"GET")).map(e=>{var t,a,r;let s=e.cloud||"";return e.region&&(s+="/".concat(e.region)),e.zone&&(s+="/".concat(e.zone)),{name:e.name,launched_at:e.launched_at,user_hash:e.user_hash,user_name:e.user_name||"-",workspace:e.workspace||"-",last_attached_at:e.last_attached_at,status:e.status,type:e.type,cloud:e.cloud,region:e.region,zone:e.zone,infra:s,size:"".concat(e.size,"Gi"),config:e.config,storage_class:(null===(t=e.config)||void 0===t?void 0:t.storage_class_name)||"-",access_mode:(null===(a=e.config)||void 0===a?void 0:a.access_mode)||"-",namespace:(null===(r=e.config)||void 0===r?void 0:r.namespace)||"-",name_on_cloud:e.name_on_cloud,usedby_pods:e.usedby_pods,usedby_clusters:e.usedby_clusters}})||[]}catch(e){return console.error("Failed to fetch volumes:",e),[]}}async function o(e){let t="";try{let a=(await r.x.post("/volumes/delete",{names:[e]})).headers.get("X-Request-ID"),s=await r.x.get("/api/get?request_id=".concat(a));if(500===s.status){try{let e=await s.json();if(e.detail&&e.detail.error)try{t=JSON.parse(e.detail.error).message}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{success:!1,msg:t}}return{success:!0}}catch(e){return console.error("Failed to delete volume:",e),{success:!1,msg:e.message}}}},6856:function(e,t,a){var r=a(6378),s=a(3266),o=a(8969),n=a(7324),l=a(3081),c=a(2045),u=a(9238);let i={base:{getClusters:{fn:s.getClusters,args:[]},getClusterHistory:{fn:s.uR,args:[]},getManagedJobs:{fn:o.getManagedJobs,args:[{allUsers:!0}]},getWorkspaces:{fn:n.fX,args:[]},getUsers:{fn:l.R,args:[]},getInfraData:{fn:c.l4,args:[]},getVolumes:{fn:u.C,args:[]}},dynamic:{getEnabledClouds:{fn:n.yz,requiresWorkspaces:!0}},pages:{clusters:["getClusters","getClusterHistory","getWorkspaces","getUsers"],jobs:["getManagedJobs","getClusters","getWorkspaces","getUsers"],infra:["getInfraData","getClusters","getManagedJobs"],workspaces:["getWorkspaces","getClusters","getManagedJobs","getEnabledClouds"],users:["getUsers","getClusters","getManagedJobs"],volumes:["getVolumes"]}};class d{async preloadForPage(e,t){let{backgroundPreload:a=!0,force:r=!1}=t||{};if(!i.pages[e]){console.warn("Unknown page: ".concat(e));return}console.log("[CachePreloader] Preloading cache for page: ".concat(e));try{await this._loadPageData(e,r),a&&this._backgroundPreloadOtherPages(e)}catch(t){console.error("[CachePreloader] Error preloading for page ".concat(e,":"),t)}}async _loadPageData(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=i.pages[e],s=[];for(let e of a)if(i.base[e]){let{fn:a,args:o}=i.base[e];t&&r.default.invalidate(a,o),s.push(r.default.get(a,o))}else"getEnabledClouds"===e&&s.push(this._loadEnabledCloudsForAllWorkspaces(t));await Promise.allSettled(s),console.log("[CachePreloader] Loaded data for page: ".concat(e))}async _loadEnabledCloudsForAllWorkspaces(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];try{e&&r.default.invalidate(n.fX);let t=await r.default.get(n.fX),a=Object.keys(t||{}).map(t=>(e&&r.default.invalidate(n.yz,[t]),r.default.get(n.yz,[t])));await Promise.allSettled(a)}catch(e){console.error("[CachePreloader] Error loading enabled clouds:",e)}}_backgroundPreloadOtherPages(e){if(this.isPreloading)return;this.isPreloading=!0;let t=Object.keys(i.pages).filter(t=>t!==e);console.log("[CachePreloader] Background preloading pages: ".concat(t.join(", "))),Promise.allSettled(t.map(async e=>{try{await this._loadPageData(e,!1),console.log("[CachePreloader] Background loaded: ".concat(e))}catch(t){console.error("[CachePreloader] Background load failed for ".concat(e,":"),t)}})).then(()=>{this.isPreloading=!1,console.log("[CachePreloader] Background preloading complete")})}async preloadBaseFunctions(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];console.log("[CachePreloader] Preloading all base functions");let t=Object.entries(i.base).map(t=>{let[a,{fn:s,args:o}]=t;return e&&r.default.invalidate(s,o),r.default.get(s,o).catch(e=>{console.error("[CachePreloader] Failed to preload ".concat(a,":"),e)})});await Promise.allSettled(t),console.log("[CachePreloader] Base functions preloaded")}getCacheStats(){return{...r.default.getStats(),isPreloading:this.isPreloading}}clearCache(){r.default.clear(),this.isPreloading=!1,this.preloadPromises.clear(),console.log("[CachePreloader] Cache cleared")}constructor(){this.isPreloading=!1,this.preloadPromises=new Map}}let g=new d;t.ZP=g}}]);
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1043],{326:function(e,t,a){a.d(t,{$N:function(){return p},Be:function(){return _},Vq:function(){return c},cN:function(){return f},cZ:function(){return d},fK:function(){return g}});var r=a(5893),s=a(7294),o=a(6327),n=a(2350),l=a(3767);let c=o.fC;o.xz;let u=o.h_;o.x8;let i=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.aV,{ref:t,className:(0,n.cn)("fixed inset-0 z-50 bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",a),...s})});i.displayName=o.aV.displayName;let d=s.forwardRef((e,t)=>{let{className:a,children:s,...c}=e;return(0,r.jsxs)(u,{children:[(0,r.jsx)(i,{}),(0,r.jsxs)(o.VY,{ref:t,className:(0,n.cn)("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-gray-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",a),...c,children:[s,(0,r.jsxs)(o.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-gray-100 data-[state=open]:text-gray-500",children:[(0,r.jsx)(l.Z,{className:"h-4 w-4"}),(0,r.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});d.displayName=o.VY.displayName;let g=e=>{let{className:t,...a}=e;return(0,r.jsx)("div",{className:(0,n.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...a})};g.displayName="DialogHeader";let f=e=>{let{className:t,...a}=e;return(0,r.jsx)("div",{className:(0,n.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...a})};f.displayName="DialogFooter";let p=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.Dx,{ref:t,className:(0,n.cn)("text-lg font-semibold leading-none tracking-tight",a),...s})});p.displayName=o.Dx.displayName;let _=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.dk,{ref:t,className:(0,n.cn)("text-sm text-gray-500",a),...s})});_.displayName=o.dk.displayName},3266:function(e,t,a){a.d(t,{QL:function(){return g},Sl:function(){return i},getClusters:function(){return c},uR:function(){return u}});var r=a(7294),s=a(5821),o=a(7145),n=a(6378);let l={UP:"RUNNING",STOPPED:"STOPPED",INIT:"LAUNCHING",null:"TERMINATED"};async function c(){let{clusterNames:e=null}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{return(await o.x.fetch("/status",{cluster_names:e,all_users:!0})).map(e=>{let t="",a=t=e.zone?e.zone:e.region;return t&&t.length>25&&(t=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:15;if(!e||e.length<=t)return e;if(t<=3)return"...";let a=Math.floor((t-3)/2),r=a+(t-3)%2;return 0===a?e.substring(0,r)+"...":e.substring(0,r)+"..."+e.substring(e.length-a)}(t,25)),{status:l[e.status],cluster:e.name,user:e.user_name,user_hash:e.user_hash,cloud:e.cloud,region:e.region,infra:t?e.cloud+" ("+t+")":e.cloud,full_infra:a?"".concat(e.cloud," (").concat(a,")"):e.cloud,cpus:e.cpus,mem:e.memory,gpus:e.accelerators,resources_str:e.resources_str,resources_str_full:e.resources_str_full,time:new Date(1e3*e.launched_at),num_nodes:e.nodes,workspace:e.workspace,autostop:e.autostop,to_down:e.to_down,jobs:[],command:e.last_creation_command||e.last_use,task_yaml:e.last_creation_yaml||"{}",events:[{time:new Date(1e3*e.launched_at),event:"Cluster created."}]}})}catch(e){return console.error("Error fetching clusters:",e),[]}}async function u(){try{let e=await o.x.fetch("/cost_report",{days:30});console.log("Raw cluster history data:",e);let t=e.map(e=>{let t="Unknown";e.cloud?t=e.cloud:e.resources&&e.resources.cloud&&(t=e.resources.cloud);let a=e.user_name||"-";return{status:e.status?l[e.status]:"TERMINATED",cluster:e.name,user:a,user_hash:e.user_hash,cloud:t,region:"",infra:t,full_infra:t,resources_str:e.resources_str,resources_str_full:e.resources_str_full,time:e.launched_at?new Date(1e3*e.launched_at):null,num_nodes:e.num_nodes||1,duration:e.duration,total_cost:e.total_cost,workspace:e.workspace||"default",autostop:-1,to_down:!1,cluster_hash:e.cluster_hash,usage_intervals:e.usage_intervals,command:e.last_creation_command||"",task_yaml:e.last_creation_yaml||"{}",events:[{time:e.launched_at?new Date(1e3*e.launched_at):new Date,event:"Cluster created."}]}});return console.log("Processed cluster history data:",t),t}catch(e){return console.error("Error fetching cluster history:",e),[]}}async function i(e){let{clusterName:t,jobId:a,onNewLog:r,workspace:n}=e;try{await o.x.stream("/logs",{follow:!1,cluster_name:t,job_id:a,override_skypilot_config:{active_workspace:n||"default"}},r)}catch(e){console.error("Error in streamClusterJobLogs:",e),(0,s.C)("Error in streamClusterJobLogs: ".concat(e.message),"error")}}async function d(e){let{clusterName:t,workspace:a}=e;try{return(await o.x.fetch("/queue",{cluster_name:t,all_users:!0,override_skypilot_config:{active_workspace:a}})).map(e=>{var r;let s=e.end_at?e.end_at:Date.now()/1e3,o=0,n=0;return e.submitted_at&&(o=s-e.submitted_at),e.start_at&&(n=s-e.start_at),{id:e.job_id,status:e.status,job:e.job_name,user:e.username,user_hash:e.user_hash,gpus:e.accelerators||{},submitted_at:e.submitted_at?new Date(1e3*e.submitted_at):null,resources:e.resources,cluster:t,total_duration:o,job_duration:n,infra:"",logs:"",workspace:a||"default",git_commit:(null===(r=e.metadata)||void 0===r?void 0:r.git_commit)||"-"}})}catch(e){return console.error("Error fetching cluster jobs:",e),[]}}function g(e){let{cluster:t,job:a=null}=e,[s,o]=(0,r.useState)(null),[l,u]=(0,r.useState)(null),[i,g]=(0,r.useState)(!0),[f,p]=(0,r.useState)(!0),_=(0,r.useCallback)(async()=>{if(t)try{g(!0);let e=await n.default.get(c,[{clusterNames:[t]}]);return o(e[0]),e[0]}catch(e){console.error("Error fetching cluster data:",e)}finally{g(!1)}return null},[t]),m=(0,r.useCallback)(async e=>{if(t)try{p(!0);let a=await n.default.get(d,[{clusterName:t,workspace:e||"default"}]);u(a)}catch(e){console.error("Error fetching cluster job data:",e)}finally{p(!1)}},[t]),h=(0,r.useCallback)(async()=>{n.default.invalidate(c,[{clusterNames:[t]}]);let e=await _();e&&(n.default.invalidate(d,[{clusterName:t,workspace:e.workspace||"default"}]),await m(e.workspace))},[_,m,t]),b=(0,r.useCallback)(async()=>{s&&(n.default.invalidate(d,[{clusterName:t,workspace:s.workspace||"default"}]),await m(s.workspace))},[m,s,t]);return(0,r.useEffect)(()=>{(async()=>{let e=await _();e&&m(e.workspace)})()},[t,a,_,m]),{clusterData:s,clusterJobData:l,loading:i,clusterDetailsLoading:i,clusterJobsLoading:f,refreshData:h,refreshClusterJobsOnly:b}}},2045:function(e,t,a){a.d(t,{l4:function(){return n}});var r=a(3225),s=a(7145);async function o(e,t){try{let a=[];try{let e=await s.x.get("/enabled_clouds"),t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("X-Request-ID"),r=await s.x.get("/api/get?request_id=".concat(t)),o=await r.json();a=o.return_value?JSON.parse(o.return_value):[],console.log("Enabled clouds:",a)}catch(e){console.error("Error fetching enabled clouds:",e),a=[]}let o={};r.$m.forEach(e=>{let t=a.includes(e.toLowerCase());o[e]={name:e,clusters:0,jobs:0,enabled:t}}),e.forEach(e=>{if(e.cloud){let t=e.cloud;o[t]&&(o[t].clusters+=1,o[t].enabled=!0)}}),t.forEach(e=>{if(e.cloud){let t=e.cloud;o[t]&&(o[t].jobs+=1,o[t].enabled=!0)}});let n=r.$m.length,l=Object.values(o).filter(e=>e.enabled).length;return{clouds:Object.values(o).filter(e=>e.enabled).sort((e,t)=>e.name.localeCompare(t.name)),totalClouds:n,enabledClouds:l}}catch(e){return console.error("Error fetching cloud infrastructure:",e),{clouds:[],totalClouds:r.$m.length,enabledClouds:0}}}async function n(){let{getClusters:e}=await Promise.resolve().then(a.bind(a,3266)),{getManagedJobs:t}=await Promise.resolve().then(a.bind(a,8969)),r=(await Promise.resolve().then(a.bind(a,6378))).default,[s,n]=await Promise.all([r.get(e),r.get(t,[{allUsers:!0}])]),c=s||[],u=(null==n?void 0:n.jobs)||[],[i,d]=await Promise.all([l(c,u),o(c,u)]);return{gpuData:i,cloudData:d}}async function l(e,t){return await g({clusters:e||[],jobs:t||[]})}async function c(){try{let e=await s.x.post("/realtime_kubernetes_gpu_availability",{context:null,name_filter:null,quantity_filter:null});if(!e.ok)return console.error("Error fetching Kubernetes context GPUs (in getKubernetesContextGPUs): ".concat(e.status," ").concat(e.statusText)),[];let t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("x-request-id");if(!t)return console.error("No request ID returned for Kubernetes GPU availability (in getKubernetesContextGPUs)"),[];let a=await s.x.get("/api/get?request_id=".concat(t)),r=await a.text();if(500===a.status){try{let e=JSON.parse(r);if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);console.error("[infra.jsx] getKubernetesContextGPUs: Server error detail:",t.message)}catch(t){console.error("[infra.jsx] getKubernetesContextGPUs: Error parsing server error JSON:",t,"Original error text:",e.detail.error)}}catch(e){console.error("[infra.jsx] getKubernetesContextGPUs: Error parsing 500 error response JSON:",e,"Raw text was:",r)}return[]}let o=JSON.parse(r);return o.return_value?JSON.parse(o.return_value):[]}catch(e){return console.error("[infra.jsx] Outer error in getKubernetesContextGPUs:",e),[]}}async function u(){try{let e=await s.x.get("/all_contexts");if(!e.ok)return console.error("Error fetching all contexts: ".concat(e.status," ").concat(e.statusText)),[];let t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("x-request-id");if(!t)return console.error("No request ID returned for /all_contexts"),[];let a=await s.x.get("/api/get?request_id=".concat(t)),r=await a.json();return r.return_value?JSON.parse(r.return_value):[]}catch(e){return console.error("[infra.jsx] Error in getAllContexts:",e),[]}}async function i(e){try{let t=await s.x.post("/kubernetes_node_info",{context:e}),a=t.headers.get("X-Skypilot-Request-ID")||t.headers.get("x-request-id"),r=await s.x.get("/api/get?request_id=".concat(a));if(500===r.status){try{let e=await r.json();if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);console.error("Error fetching Kubernetes per node GPUs:",t.message)}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{}}let o=await r.json();return(o.return_value?JSON.parse(o.return_value):{}).node_info_dict||{}}catch(t){return console.error("[infra.jsx] Error in getKubernetesPerNodeGPUs for context",e,":",t),{}}}async function d(e){try{let t=e.clusters,a=e.jobs,r={};return t.forEach(e=>{let t=null;if("Kubernetes"===e.cloud)(t=e.region)&&(t="kubernetes/".concat(t));else if("SSH"===e.cloud&&(t=e.region)){let e=t.startsWith("ssh-")?t.substring(4):t;t="ssh/".concat(e)}t&&(r[t]||(r[t]={clusters:0,jobs:0}),r[t].clusters+=1)}),a.forEach(e=>{let t=null;if("Kubernetes"===e.cloud)(t=e.region)&&(t="kubernetes/".concat(t));else if("SSH"===e.cloud&&(t=e.region)){let e=t.startsWith("ssh-")?t.substring(4):t;t="ssh/".concat(e)}t&&(r[t]||(r[t]={clusters:0,jobs:0}),r[t].jobs+=1)}),r}catch(e){return console.error("=== Error in getContextClustersAndJobs ===",e),{}}}async function g(e){try{let o=await u();if(!o||0===o.length)return console.log("No contexts found from /all_contexts endpoint."),{allContextNames:[],allGPUs:[],perContextGPUs:[],perNodeGPUs:[],contextStats:{}};let n=await d(e),l=await c(),g=new Map;l&&l.forEach(e=>{g.set(e[0],e[1])});let f={},p={},_={};for(let e of o){p[e]||(p[e]=[]);let o=g.get(e);if(o&&o.length>0)for(let t of o){let a=t[0],r=t[1].join(", "),s=t[2],o=t[3];a in f?(f[a].gpu_total+=s,f[a].gpu_free+=o):f[a]={gpu_total:s,gpu_free:o,gpu_name:a},p[e].push({gpu_name:a,gpu_requestable_qty_per_node:r,gpu_total:s,gpu_free:o,context:e})}let n=await i(e);if(n&&Object.keys(n).length>0)for(let o in n){var t,a,r,s;let l=n[o],c=l.accelerator_type||"-",u=null!==(r=null===(t=l.total)||void 0===t?void 0:t.accelerator_count)&&void 0!==r?r:0,i=null!==(s=null===(a=l.free)||void 0===a?void 0:a.accelerators_available)&&void 0!==s?s:0;_["".concat(e,"/").concat(o)]={node_name:l.name,gpu_name:c,gpu_total:u,gpu_free:i,ip_address:l.ip_address||null,context:e},"-"===c||p[e].some(e=>e.gpu_name===c)||(c in f||(f[c]={gpu_total:0,gpu_free:0,gpu_name:c}),p[e].find(e=>e.gpu_name===c)||p[e].push({gpu_name:c,gpu_requestable_qty_per_node:"-",gpu_total:0,gpu_free:0,context:e}))}0===p[e].length&&n&&Object.keys(n).length}return{allContextNames:o.sort(),allGPUs:Object.values(f).sort((e,t)=>e.gpu_name.localeCompare(t.gpu_name)),perContextGPUs:Object.values(p).flat().sort((e,t)=>e.context.localeCompare(t.context)||e.gpu_name.localeCompare(t.gpu_name)),perNodeGPUs:Object.values(_).sort((e,t)=>e.context.localeCompare(t.context)||e.node_name.localeCompare(t.node_name)||e.gpu_name.localeCompare(t.gpu_name)),contextStats:n}}catch(e){return console.error("[infra.jsx] Outer error in getKubernetesGPUs:",e),{allContextNames:[],allGPUs:[],perContextGPUs:[],perNodeGPUs:[],contextStats:{}}}}},3081:function(e,t,a){a.d(t,{R:function(){return s}}),a(3266),a(8969);var r=a(7145);async function s(){try{let e=await r.x.get("/users");if(!e.ok)throw Error("HTTP error! status: ".concat(e.status));return(await e.json()).map(e=>({userId:e.id,username:e.name,role:e.role,created_at:e.created_at}))||[]}catch(e){return console.error("Failed to fetch users:",e),[]}}},9238:function(e,t,a){a.d(t,{C:function(){return s},w:function(){return o}});var r=a(7145);async function s(){try{return(await r.x.fetch("/volumes",{},"GET")).map(e=>{var t,a,r;let s=e.cloud||"";return e.region&&(s+="/".concat(e.region)),e.zone&&(s+="/".concat(e.zone)),{name:e.name,launched_at:e.launched_at,user_hash:e.user_hash,user_name:e.user_name||"-",workspace:e.workspace||"-",last_attached_at:e.last_attached_at,status:e.status,type:e.type,cloud:e.cloud,region:e.region,zone:e.zone,infra:s,size:"".concat(e.size,"Gi"),config:e.config,storage_class:(null===(t=e.config)||void 0===t?void 0:t.storage_class_name)||"-",access_mode:(null===(a=e.config)||void 0===a?void 0:a.access_mode)||"-",namespace:(null===(r=e.config)||void 0===r?void 0:r.namespace)||"-",name_on_cloud:e.name_on_cloud,usedby_pods:e.usedby_pods,usedby_clusters:e.usedby_clusters}})||[]}catch(e){return console.error("Failed to fetch volumes:",e),[]}}async function o(e){let t="";try{let a=await r.x.post("/volumes/delete",{names:[e]}),s=a.headers.get("X-SkyPilot-Request-ID")||a.headers.get("X-Request-ID"),o=await r.x.get("/api/get?request_id=".concat(s));if(500===o.status){try{let e=await o.json();if(e.detail&&e.detail.error)try{t=JSON.parse(e.detail.error).message}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{success:!1,msg:t}}return{success:!0}}catch(e){return console.error("Failed to delete volume:",e),{success:!1,msg:e.message}}}},6856:function(e,t,a){var r=a(6378),s=a(3266),o=a(8969),n=a(7324),l=a(3081),c=a(2045),u=a(9238);let i={base:{getClusters:{fn:s.getClusters,args:[]},getClusterHistory:{fn:s.uR,args:[]},getManagedJobs:{fn:o.getManagedJobs,args:[{allUsers:!0}]},getWorkspaces:{fn:n.fX,args:[]},getUsers:{fn:l.R,args:[]},getInfraData:{fn:c.l4,args:[]},getVolumes:{fn:u.C,args:[]}},dynamic:{getEnabledClouds:{fn:n.yz,requiresWorkspaces:!0}},pages:{clusters:["getClusters","getClusterHistory","getWorkspaces","getUsers"],jobs:["getManagedJobs","getClusters","getWorkspaces","getUsers"],infra:["getInfraData","getClusters","getManagedJobs"],workspaces:["getWorkspaces","getClusters","getManagedJobs","getEnabledClouds"],users:["getUsers","getClusters","getManagedJobs"],volumes:["getVolumes"]}};class d{async preloadForPage(e,t){let{backgroundPreload:a=!0,force:r=!1}=t||{};if(!i.pages[e]){console.warn("Unknown page: ".concat(e));return}console.log("[CachePreloader] Preloading cache for page: ".concat(e));try{await this._loadPageData(e,r),a&&this._backgroundPreloadOtherPages(e)}catch(t){console.error("[CachePreloader] Error preloading for page ".concat(e,":"),t)}}async _loadPageData(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=i.pages[e],s=[];for(let e of a)if(i.base[e]){let{fn:a,args:o}=i.base[e];t&&r.default.invalidate(a,o),s.push(r.default.get(a,o))}else"getEnabledClouds"===e&&s.push(this._loadEnabledCloudsForAllWorkspaces(t));await Promise.allSettled(s),console.log("[CachePreloader] Loaded data for page: ".concat(e))}async _loadEnabledCloudsForAllWorkspaces(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];try{e&&r.default.invalidate(n.fX);let t=await r.default.get(n.fX),a=Object.keys(t||{}).map(t=>(e&&r.default.invalidate(n.yz,[t]),r.default.get(n.yz,[t])));await Promise.allSettled(a)}catch(e){console.error("[CachePreloader] Error loading enabled clouds:",e)}}_backgroundPreloadOtherPages(e){if(this.isPreloading)return;this.isPreloading=!0;let t=Object.keys(i.pages).filter(t=>t!==e);console.log("[CachePreloader] Background preloading pages: ".concat(t.join(", "))),Promise.allSettled(t.map(async e=>{try{await this._loadPageData(e,!1),console.log("[CachePreloader] Background loaded: ".concat(e))}catch(t){console.error("[CachePreloader] Background load failed for ".concat(e,":"),t)}})).then(()=>{this.isPreloading=!1,console.log("[CachePreloader] Background preloading complete")})}async preloadBaseFunctions(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];console.log("[CachePreloader] Preloading all base functions");let t=Object.entries(i.base).map(t=>{let[a,{fn:s,args:o}]=t;return e&&r.default.invalidate(s,o),r.default.get(s,o).catch(e=>{console.error("[CachePreloader] Failed to preload ".concat(a,":"),e)})});await Promise.allSettled(t),console.log("[CachePreloader] Base functions preloaded")}getCacheStats(){return{...r.default.getStats(),isPreloading:this.isPreloading}}clearCache(){r.default.clear(),this.isPreloading=!1,this.preloadPromises.clear(),console.log("[CachePreloader] Cache cleared")}constructor(){this.isPreloading=!1,this.preloadPromises=new Map}}let g=new d;t.ZP=g}}]);