skypilot-nightly 1.0.0.dev20250807__py3-none-any.whl → 1.0.0.dev20250808__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 (61) hide show
  1. sky/__init__.py +2 -2
  2. sky/backends/backend_utils.py +20 -1
  3. sky/backends/cloud_vm_ray_backend.py +9 -2
  4. sky/client/cli/command.py +40 -26
  5. sky/client/sdk.py +132 -65
  6. sky/client/sdk_async.py +1 -1
  7. sky/core.py +5 -2
  8. sky/dashboard/out/404.html +1 -1
  9. sky/dashboard/out/_next/static/{YAirOGsV1z6B2RJ0VIUmD → -DXZksWqf2waNHeU9YTQe}/_buildManifest.js +1 -1
  10. sky/dashboard/out/_next/static/chunks/{6601-3e21152fe16da09c.js → 6601-06114c982db410b6.js} +1 -1
  11. sky/dashboard/out/_next/static/chunks/8056-34d27f51e6d1c631.js +1 -0
  12. sky/dashboard/out/_next/static/chunks/{8969-318c3dca725e8e5d.js → 8969-c9686994ddafcf01.js} +1 -1
  13. sky/dashboard/out/_next/static/chunks/pages/{_app-1e6de35d15a8d432.js → _app-491a4d699d95e808.js} +1 -1
  14. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-ae17cec0fc6483d9.js +11 -0
  15. sky/dashboard/out/_next/static/chunks/webpack-339efec49c0cc7d0.js +1 -0
  16. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  17. sky/dashboard/out/clusters/[cluster].html +1 -1
  18. sky/dashboard/out/clusters.html +1 -1
  19. sky/dashboard/out/config.html +1 -1
  20. sky/dashboard/out/index.html +1 -1
  21. sky/dashboard/out/infra/[context].html +1 -1
  22. sky/dashboard/out/infra.html +1 -1
  23. sky/dashboard/out/jobs/[job].html +1 -1
  24. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  25. sky/dashboard/out/jobs.html +1 -1
  26. sky/dashboard/out/users.html +1 -1
  27. sky/dashboard/out/volumes.html +1 -1
  28. sky/dashboard/out/workspace/new.html +1 -1
  29. sky/dashboard/out/workspaces/[name].html +1 -1
  30. sky/dashboard/out/workspaces.html +1 -1
  31. sky/execution.py +6 -4
  32. sky/global_user_state.py +8 -1
  33. sky/jobs/client/sdk.py +27 -20
  34. sky/jobs/controller.py +2 -1
  35. sky/schemas/db/global_user_state/003_fix_initial_revision.py +61 -0
  36. sky/schemas/db/global_user_state/004_is_managed.py +34 -0
  37. sky/schemas/db/serve_state/001_initial_schema.py +67 -0
  38. sky/serve/client/impl.py +11 -8
  39. sky/serve/client/sdk.py +7 -7
  40. sky/serve/serve_state.py +437 -340
  41. sky/serve/server/impl.py +2 -2
  42. sky/server/common.py +12 -8
  43. sky/server/constants.py +1 -1
  44. sky/setup_files/alembic.ini +4 -0
  45. sky/utils/cli_utils/status_utils.py +1 -1
  46. sky/utils/db/db_utils.py +31 -0
  47. sky/utils/db/migration_utils.py +5 -1
  48. sky/utils/kubernetes/deploy_remote_cluster.py +3 -1
  49. sky/utils/resource_checker.py +162 -21
  50. sky/volumes/client/sdk.py +4 -4
  51. sky/workspaces/core.py +210 -6
  52. {skypilot_nightly-1.0.0.dev20250807.dist-info → skypilot_nightly-1.0.0.dev20250808.dist-info}/METADATA +2 -2
  53. {skypilot_nightly-1.0.0.dev20250807.dist-info → skypilot_nightly-1.0.0.dev20250808.dist-info}/RECORD +58 -55
  54. sky/dashboard/out/_next/static/chunks/8056-019615038d6ce427.js +0 -1
  55. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-6fd1d2d8441aa54b.js +0 -11
  56. sky/dashboard/out/_next/static/chunks/webpack-76efbdad99742559.js +0 -1
  57. /sky/dashboard/out/_next/static/{YAirOGsV1z6B2RJ0VIUmD → -DXZksWqf2waNHeU9YTQe}/_ssgManifest.js +0 -0
  58. {skypilot_nightly-1.0.0.dev20250807.dist-info → skypilot_nightly-1.0.0.dev20250808.dist-info}/WHEEL +0 -0
  59. {skypilot_nightly-1.0.0.dev20250807.dist-info → skypilot_nightly-1.0.0.dev20250808.dist-info}/entry_points.txt +0 -0
  60. {skypilot_nightly-1.0.0.dev20250807.dist-info → skypilot_nightly-1.0.0.dev20250808.dist-info}/licenses/LICENSE +0 -0
  61. {skypilot_nightly-1.0.0.dev20250807.dist-info → skypilot_nightly-1.0.0.dev20250808.dist-info}/top_level.txt +0 -0
sky/client/sdk.py CHANGED
@@ -16,7 +16,7 @@ import logging
16
16
  import os
17
17
  import subprocess
18
18
  import typing
19
- from typing import Any, Dict, List, Optional, Tuple, Union
19
+ from typing import Any, Dict, List, Optional, Tuple, TypeVar, Union
20
20
  from urllib import parse as urlparse
21
21
 
22
22
  import click
@@ -66,6 +66,10 @@ if typing.TYPE_CHECKING:
66
66
 
67
67
  import sky
68
68
  from sky import backends
69
+ from sky import models
70
+ import sky.catalog
71
+ from sky.provision.kubernetes import utils as kubernetes_utils
72
+ from sky.skylet import job_lib
69
73
  else:
70
74
  # only used in api_login()
71
75
  base64 = adaptors_common.LazyImport('base64')
@@ -82,16 +86,34 @@ logging.getLogger('httpx').setLevel(logging.CRITICAL)
82
86
 
83
87
  _LINE_PROCESSED_KEY = 'line_processed'
84
88
 
89
+ T = TypeVar('T')
90
+
85
91
 
86
92
  def reload_config() -> None:
87
93
  """Reloads the client-side config."""
88
94
  skypilot_config.safe_reload_config()
89
95
 
90
96
 
91
- def stream_response(request_id: Optional[server_common.RequestId],
97
+ @typing.overload
98
+ def stream_response(request_id: None,
99
+ response: 'requests.Response',
100
+ output_stream: Optional['io.TextIOBase'] = None,
101
+ resumable: bool = False) -> None:
102
+ ...
103
+
104
+
105
+ @typing.overload
106
+ def stream_response(request_id: server_common.RequestId[T],
107
+ response: 'requests.Response',
108
+ output_stream: Optional['io.TextIOBase'] = None,
109
+ resumable: bool = False) -> T:
110
+ ...
111
+
112
+
113
+ def stream_response(request_id: Optional[server_common.RequestId[T]],
92
114
  response: 'requests.Response',
93
115
  output_stream: Optional['io.TextIOBase'] = None,
94
- resumable: bool = False) -> Any:
116
+ resumable: bool = False) -> Optional[T]:
95
117
  """Streams the response to the console.
96
118
 
97
119
  Args:
@@ -121,6 +143,8 @@ def stream_response(request_id: Optional[server_common.RequestId],
121
143
  retry_context.line_processed = line_count
122
144
  if request_id is not None:
123
145
  return get(request_id)
146
+ else:
147
+ return None
124
148
  except Exception: # pylint: disable=broad-except
125
149
  logger.debug(f'To stream request logs: sky api logs {request_id}')
126
150
  raise
@@ -129,9 +153,11 @@ def stream_response(request_id: Optional[server_common.RequestId],
129
153
  @usage_lib.entrypoint
130
154
  @server_common.check_server_healthy_or_start
131
155
  @annotations.client_api
132
- def check(infra_list: Optional[Tuple[str, ...]],
133
- verbose: bool,
134
- workspace: Optional[str] = None) -> server_common.RequestId:
156
+ def check(
157
+ infra_list: Optional[Tuple[str, ...]],
158
+ verbose: bool,
159
+ workspace: Optional[str] = None
160
+ ) -> server_common.RequestId[Dict[str, List[str]]]:
135
161
  """Checks the credentials to enable clouds.
136
162
 
137
163
  Args:
@@ -174,7 +200,7 @@ def check(infra_list: Optional[Tuple[str, ...]],
174
200
  @server_common.check_server_healthy_or_start
175
201
  @annotations.client_api
176
202
  def enabled_clouds(workspace: Optional[str] = None,
177
- expand: bool = False) -> server_common.RequestId:
203
+ expand: bool = False) -> server_common.RequestId[List[str]]:
178
204
  """Gets the enabled clouds.
179
205
 
180
206
  Args:
@@ -198,14 +224,17 @@ def enabled_clouds(workspace: Optional[str] = None,
198
224
  @usage_lib.entrypoint
199
225
  @server_common.check_server_healthy_or_start
200
226
  @annotations.client_api
201
- def list_accelerators(gpus_only: bool = True,
202
- name_filter: Optional[str] = None,
203
- region_filter: Optional[str] = None,
204
- quantity_filter: Optional[int] = None,
205
- clouds: Optional[Union[List[str], str]] = None,
206
- all_regions: bool = False,
207
- require_price: bool = True,
208
- case_sensitive: bool = True) -> server_common.RequestId:
227
+ def list_accelerators(
228
+ gpus_only: bool = True,
229
+ name_filter: Optional[str] = None,
230
+ region_filter: Optional[str] = None,
231
+ quantity_filter: Optional[int] = None,
232
+ clouds: Optional[Union[List[str], str]] = None,
233
+ all_regions: bool = False,
234
+ require_price: bool = True,
235
+ case_sensitive: bool = True
236
+ ) -> server_common.RequestId[Dict[str,
237
+ List['sky.catalog.common.InstanceTypeInfo']]]:
209
238
  """Lists the names of all accelerators offered by Sky.
210
239
 
211
240
  This will include all accelerators offered by Sky, including those
@@ -248,12 +277,12 @@ def list_accelerators(gpus_only: bool = True,
248
277
  @server_common.check_server_healthy_or_start
249
278
  @annotations.client_api
250
279
  def list_accelerator_counts(
251
- gpus_only: bool = True,
252
- name_filter: Optional[str] = None,
253
- region_filter: Optional[str] = None,
254
- quantity_filter: Optional[int] = None,
255
- clouds: Optional[Union[List[str],
256
- str]] = None) -> server_common.RequestId:
280
+ gpus_only: bool = True,
281
+ name_filter: Optional[str] = None,
282
+ region_filter: Optional[str] = None,
283
+ quantity_filter: Optional[int] = None,
284
+ clouds: Optional[Union[List[str], str]] = None
285
+ ) -> server_common.RequestId[Dict[str, List[float]]]:
257
286
  """Lists all accelerators offered by Sky and available counts.
258
287
 
259
288
  Args:
@@ -292,7 +321,7 @@ def optimize(
292
321
  dag: 'sky.Dag',
293
322
  minimize: common.OptimizeTarget = common.OptimizeTarget.COST,
294
323
  admin_policy_request_options: Optional[admin_policy.RequestOptions] = None
295
- ) -> server_common.RequestId:
324
+ ) -> server_common.RequestId['sky.Dag']:
296
325
  """Finds the best execution plan for the given DAG.
297
326
 
298
327
  Args:
@@ -323,7 +352,7 @@ def optimize(
323
352
  return server_common.get_request_id(response)
324
353
 
325
354
 
326
- def workspaces() -> server_common.RequestId:
355
+ def workspaces() -> server_common.RequestId[Dict[str, Any]]:
327
356
  """Gets the workspaces."""
328
357
  response = server_common.make_authenticated_request('GET', '/workspaces')
329
358
  return server_common.get_request_id(response)
@@ -409,7 +438,8 @@ def launch(
409
438
  _is_launched_by_jobs_controller: bool = False,
410
439
  _is_launched_by_sky_serve_controller: bool = False,
411
440
  _disable_controller_check: bool = False,
412
- ) -> server_common.RequestId:
441
+ ) -> server_common.RequestId[Tuple[Optional[int],
442
+ Optional['backends.ResourceHandle']]]:
413
443
  """Launches a cluster or task.
414
444
 
415
445
  The task's setup and run commands are executed under the task's workdir
@@ -591,7 +621,8 @@ def _launch(
591
621
  _is_launched_by_jobs_controller: bool = False,
592
622
  _is_launched_by_sky_serve_controller: bool = False,
593
623
  _disable_controller_check: bool = False,
594
- ) -> server_common.RequestId:
624
+ ) -> server_common.RequestId[Tuple[Optional[int],
625
+ Optional['backends.ResourceHandle']]]:
595
626
  """Auxiliary function for launch(), refer to launch() for details."""
596
627
 
597
628
  validate(dag, admin_policy_request_options=request_options)
@@ -604,8 +635,8 @@ def _launch(
604
635
  if _need_confirmation:
605
636
  cluster_status = None
606
637
  # TODO(SKY-998): we should reduce RTTs before launching the cluster.
607
- request_id = status([cluster_name], all_users=True)
608
- clusters = get(request_id)
638
+ status_request_id = status([cluster_name], all_users=True)
639
+ clusters = get(status_request_id)
609
640
  cluster_user_hash = common_utils.get_user_hash()
610
641
  cluster_user_hash_str = ''
611
642
  current_user = common_utils.get_current_user_name()
@@ -613,9 +644,9 @@ def _launch(
613
644
  if not clusters:
614
645
  # Show the optimize log before the prompt if the cluster does not
615
646
  # exist.
616
- request_id = optimize(dag,
617
- admin_policy_request_options=request_options)
618
- stream_and_get(request_id)
647
+ optimize_request_id = optimize(
648
+ dag, admin_policy_request_options=request_options)
649
+ stream_and_get(optimize_request_id)
619
650
  else:
620
651
  cluster_record = clusters[0]
621
652
  cluster_status = cluster_record['status']
@@ -690,7 +721,8 @@ def exec( # pylint: disable=redefined-builtin
690
721
  dryrun: bool = False,
691
722
  down: bool = False, # pylint: disable=redefined-outer-name
692
723
  backend: Optional['backends.Backend'] = None,
693
- ) -> server_common.RequestId:
724
+ ) -> server_common.RequestId[Tuple[Optional[int],
725
+ Optional['backends.ResourceHandle']]]:
694
726
  """Executes a task on an existing cluster.
695
727
 
696
728
  This function performs two actions:
@@ -812,7 +844,8 @@ def tail_logs(cluster_name: str,
812
844
  stream=True,
813
845
  timeout=(client_common.API_SERVER_REQUEST_CONNECTION_TIMEOUT_SECONDS,
814
846
  None))
815
- request_id = server_common.get_request_id(response)
847
+ request_id: server_common.RequestId[int] = server_common.get_request_id(
848
+ response)
816
849
  # Log request is idempotent when tail is 0, thus can resume previous
817
850
  # streaming point on retry.
818
851
  return stream_response(request_id=request_id,
@@ -854,8 +887,9 @@ def download_logs(cluster_name: str,
854
887
  )
855
888
  response = server_common.make_authenticated_request(
856
889
  'POST', '/download_logs', json=json.loads(body.model_dump_json()))
857
- job_id_remote_path_dict = stream_and_get(
858
- server_common.get_request_id(response))
890
+ request_id: server_common.RequestId[Dict[
891
+ str, str]] = server_common.get_request_id(response)
892
+ job_id_remote_path_dict = stream_and_get(request_id)
859
893
  remote2local_path_dict = client_common.download_logs_from_api_server(
860
894
  job_id_remote_path_dict.values())
861
895
  return {
@@ -874,7 +908,7 @@ def start(
874
908
  retry_until_up: bool = False,
875
909
  down: bool = False, # pylint: disable=redefined-outer-name
876
910
  force: bool = False,
877
- ) -> server_common.RequestId:
911
+ ) -> server_common.RequestId['backends.CloudVmRayResourceHandle']:
878
912
  """Restart a cluster.
879
913
 
880
914
  If a cluster is previously stopped (status is STOPPED) or failed in
@@ -956,7 +990,8 @@ def start(
956
990
  @usage_lib.entrypoint
957
991
  @server_common.check_server_healthy_or_start
958
992
  @annotations.client_api
959
- def down(cluster_name: str, purge: bool = False) -> server_common.RequestId:
993
+ def down(cluster_name: str,
994
+ purge: bool = False) -> server_common.RequestId[None]:
960
995
  """Tears down a cluster.
961
996
 
962
997
  Tearing down a cluster will delete all associated resources (all billing
@@ -998,7 +1033,8 @@ def down(cluster_name: str, purge: bool = False) -> server_common.RequestId:
998
1033
  @usage_lib.entrypoint
999
1034
  @server_common.check_server_healthy_or_start
1000
1035
  @annotations.client_api
1001
- def stop(cluster_name: str, purge: bool = False) -> server_common.RequestId:
1036
+ def stop(cluster_name: str,
1037
+ purge: bool = False) -> server_common.RequestId[None]:
1002
1038
  """Stops a cluster.
1003
1039
 
1004
1040
  Data on attached disks is not lost when a cluster is stopped. Billing for
@@ -1048,7 +1084,7 @@ def autostop(
1048
1084
  idle_minutes: int,
1049
1085
  wait_for: Optional[autostop_lib.AutostopWaitFor] = None,
1050
1086
  down: bool = False, # pylint: disable=redefined-outer-name
1051
- ) -> server_common.RequestId:
1087
+ ) -> server_common.RequestId[None]:
1052
1088
  """Schedules an autostop/autodown for a cluster.
1053
1089
 
1054
1090
  Autostop/autodown will automatically stop or teardown a cluster when it
@@ -1128,7 +1164,7 @@ def autostop(
1128
1164
  @annotations.client_api
1129
1165
  def queue(cluster_name: str,
1130
1166
  skip_finished: bool = False,
1131
- all_users: bool = False) -> server_common.RequestId:
1167
+ all_users: bool = False) -> server_common.RequestId[List[dict]]:
1132
1168
  """Gets the job queue of a cluster.
1133
1169
 
1134
1170
  Args:
@@ -1185,8 +1221,11 @@ def queue(cluster_name: str,
1185
1221
  @usage_lib.entrypoint
1186
1222
  @server_common.check_server_healthy_or_start
1187
1223
  @annotations.client_api
1188
- def job_status(cluster_name: str,
1189
- job_ids: Optional[List[int]] = None) -> server_common.RequestId:
1224
+ def job_status(
1225
+ cluster_name: str,
1226
+ job_ids: Optional[List[int]] = None
1227
+ ) -> server_common.RequestId[Dict[Optional[int],
1228
+ Optional['job_lib.JobStatus']]]:
1190
1229
  """Gets the status of jobs on a cluster.
1191
1230
 
1192
1231
  Args:
@@ -1233,7 +1272,7 @@ def cancel(
1233
1272
  job_ids: Optional[List[int]] = None,
1234
1273
  # pylint: disable=invalid-name
1235
1274
  _try_cancel_if_cluster_is_init: bool = False
1236
- ) -> server_common.RequestId:
1275
+ ) -> server_common.RequestId[None]:
1237
1276
  """Cancels jobs on a cluster.
1238
1277
 
1239
1278
  Args:
@@ -1283,7 +1322,7 @@ def status(
1283
1322
  cluster_names: Optional[List[str]] = None,
1284
1323
  refresh: common.StatusRefreshMode = common.StatusRefreshMode.NONE,
1285
1324
  all_users: bool = False,
1286
- ) -> server_common.RequestId:
1325
+ ) -> server_common.RequestId[List[Dict[str, Any]]]:
1287
1326
  """Gets cluster statuses.
1288
1327
 
1289
1328
  If cluster_names is given, return those clusters. Otherwise, return all
@@ -1375,8 +1414,9 @@ def status(
1375
1414
  @server_common.check_server_healthy_or_start
1376
1415
  @annotations.client_api
1377
1416
  def endpoints(
1378
- cluster: str,
1379
- port: Optional[Union[int, str]] = None) -> server_common.RequestId:
1417
+ cluster: str,
1418
+ port: Optional[Union[int, str]] = None
1419
+ ) -> server_common.RequestId[Dict[str, str]]:
1380
1420
  """Gets the endpoint for a given cluster and port number (endpoint).
1381
1421
 
1382
1422
  Args:
@@ -1408,7 +1448,9 @@ def endpoints(
1408
1448
  @usage_lib.entrypoint
1409
1449
  @server_common.check_server_healthy_or_start
1410
1450
  @annotations.client_api
1411
- def cost_report(days: Optional[int] = None) -> server_common.RequestId: # pylint: disable=redefined-builtin
1451
+ def cost_report(
1452
+ days: Optional[int] = None
1453
+ ) -> server_common.RequestId[List[Dict[str, Any]]]: # pylint: disable=redefined-builtin
1412
1454
  """Gets all cluster cost reports, including those that have been downed.
1413
1455
 
1414
1456
  The estimated cost column indicates price for the cluster based on the type
@@ -1453,7 +1495,7 @@ def cost_report(days: Optional[int] = None) -> server_common.RequestId: # pylin
1453
1495
  @usage_lib.entrypoint
1454
1496
  @server_common.check_server_healthy_or_start
1455
1497
  @annotations.client_api
1456
- def storage_ls() -> server_common.RequestId:
1498
+ def storage_ls() -> server_common.RequestId[List[Dict[str, Any]]]:
1457
1499
  """Gets the storages.
1458
1500
 
1459
1501
  Returns:
@@ -1481,7 +1523,7 @@ def storage_ls() -> server_common.RequestId:
1481
1523
  @usage_lib.entrypoint
1482
1524
  @server_common.check_server_healthy_or_start
1483
1525
  @annotations.client_api
1484
- def storage_delete(name: str) -> server_common.RequestId:
1526
+ def storage_delete(name: str) -> server_common.RequestId[None]:
1485
1527
  """Deletes a storage.
1486
1528
 
1487
1529
  Args:
@@ -1514,7 +1556,7 @@ def local_up(gpus: bool,
1514
1556
  ssh_key: Optional[str],
1515
1557
  cleanup: bool,
1516
1558
  context_name: Optional[str] = None,
1517
- password: Optional[str] = None) -> server_common.RequestId:
1559
+ password: Optional[str] = None) -> server_common.RequestId[None]:
1518
1560
  """Launches a Kubernetes cluster on local machines.
1519
1561
 
1520
1562
  Returns:
@@ -1543,7 +1585,7 @@ def local_up(gpus: bool,
1543
1585
  @usage_lib.entrypoint
1544
1586
  @server_common.check_server_healthy_or_start
1545
1587
  @annotations.client_api
1546
- def local_down() -> server_common.RequestId:
1588
+ def local_down() -> server_common.RequestId[None]:
1547
1589
  """Tears down the Kubernetes cluster started by local_up."""
1548
1590
  # We do not allow local up when the API server is running remotely since it
1549
1591
  # will modify the kubeconfig.
@@ -1618,7 +1660,7 @@ def _upload_ssh_key_and_wait(key_name: str, key_file_path: str) -> str:
1618
1660
  @server_common.check_server_healthy_or_start
1619
1661
  @annotations.client_api
1620
1662
  def ssh_up(infra: Optional[str] = None,
1621
- file: Optional[str] = None) -> server_common.RequestId:
1663
+ file: Optional[str] = None) -> server_common.RequestId[None]:
1622
1664
  """Deploys the SSH Node Pools defined in ~/.sky/ssh_targets.yaml.
1623
1665
 
1624
1666
  Args:
@@ -1651,7 +1693,7 @@ def ssh_up(infra: Optional[str] = None,
1651
1693
  @usage_lib.entrypoint
1652
1694
  @server_common.check_server_healthy_or_start
1653
1695
  @annotations.client_api
1654
- def ssh_down(infra: Optional[str] = None) -> server_common.RequestId:
1696
+ def ssh_down(infra: Optional[str] = None) -> server_common.RequestId[None]:
1655
1697
  """Tears down a Kubernetes cluster on SSH targets.
1656
1698
 
1657
1699
  Args:
@@ -1680,10 +1722,12 @@ def ssh_down(infra: Optional[str] = None) -> server_common.RequestId:
1680
1722
  @server_common.check_server_healthy_or_start
1681
1723
  @annotations.client_api
1682
1724
  def realtime_kubernetes_gpu_availability(
1683
- context: Optional[str] = None,
1684
- name_filter: Optional[str] = None,
1685
- quantity_filter: Optional[int] = None,
1686
- is_ssh: Optional[bool] = None) -> server_common.RequestId:
1725
+ context: Optional[str] = None,
1726
+ name_filter: Optional[str] = None,
1727
+ quantity_filter: Optional[int] = None,
1728
+ is_ssh: Optional[bool] = None
1729
+ ) -> server_common.RequestId[List[Tuple[
1730
+ str, List['models.RealtimeGpuAvailability']]]]:
1687
1731
  """Gets the real-time Kubernetes GPU availability.
1688
1732
 
1689
1733
  Returns:
@@ -1706,7 +1750,8 @@ def realtime_kubernetes_gpu_availability(
1706
1750
  @server_common.check_server_healthy_or_start
1707
1751
  @annotations.client_api
1708
1752
  def kubernetes_node_info(
1709
- context: Optional[str] = None) -> server_common.RequestId:
1753
+ context: Optional[str] = None
1754
+ ) -> server_common.RequestId['models.KubernetesNodesInfo']:
1710
1755
  """Gets the resource information for all the nodes in the cluster.
1711
1756
 
1712
1757
  Currently only GPU resources are supported. The function returns the total
@@ -1737,7 +1782,10 @@ def kubernetes_node_info(
1737
1782
  @usage_lib.entrypoint
1738
1783
  @server_common.check_server_healthy_or_start
1739
1784
  @annotations.client_api
1740
- def status_kubernetes() -> server_common.RequestId:
1785
+ def status_kubernetes() -> server_common.RequestId[Tuple[
1786
+ List['kubernetes_utils.KubernetesSkyPilotClusterInfoPayload'],
1787
+ List['kubernetes_utils.KubernetesSkyPilotClusterInfoPayload'], List[Dict[
1788
+ str, Any]], Optional[str]]]:
1741
1789
  """Gets all SkyPilot clusters and jobs in the Kubernetes cluster.
1742
1790
 
1743
1791
  Managed jobs and services are also included in the clusters returned.
@@ -1766,7 +1814,7 @@ def status_kubernetes() -> server_common.RequestId:
1766
1814
  # === API request APIs ===
1767
1815
  @usage_lib.entrypoint
1768
1816
  @annotations.client_api
1769
- def get(request_id: server_common.RequestId) -> Any:
1817
+ def get(request_id: server_common.RequestId[T]) -> T:
1770
1818
  """Waits for and gets the result of a request.
1771
1819
 
1772
1820
  This function will not check the server health since /api/get is typically
@@ -1825,16 +1873,34 @@ def get(request_id: server_common.RequestId) -> Any:
1825
1873
  return request_task.get_return_value()
1826
1874
 
1827
1875
 
1876
+ @typing.overload
1877
+ def stream_and_get(request_id: server_common.RequestId[T],
1878
+ log_path: Optional[str] = None,
1879
+ tail: Optional[int] = None,
1880
+ follow: bool = True,
1881
+ output_stream: Optional['io.TextIOBase'] = None) -> T:
1882
+ ...
1883
+
1884
+
1885
+ @typing.overload
1886
+ def stream_and_get(request_id: None = None,
1887
+ log_path: Optional[str] = None,
1888
+ tail: Optional[int] = None,
1889
+ follow: bool = True,
1890
+ output_stream: Optional['io.TextIOBase'] = None) -> None:
1891
+ ...
1892
+
1893
+
1828
1894
  @usage_lib.entrypoint
1829
1895
  @server_common.check_server_healthy_or_start
1830
1896
  @annotations.client_api
1831
1897
  def stream_and_get(
1832
- request_id: Optional[server_common.RequestId] = None,
1898
+ request_id: Optional[server_common.RequestId[T]] = None,
1833
1899
  log_path: Optional[str] = None,
1834
1900
  tail: Optional[int] = None,
1835
1901
  follow: bool = True,
1836
1902
  output_stream: Optional['io.TextIOBase'] = None,
1837
- ) -> Any:
1903
+ ) -> Optional[T]:
1838
1904
  """Streams the logs of a request or a log file and gets the final result.
1839
1905
 
1840
1906
  This will block until the request is finished. The request id can be a
@@ -1891,10 +1957,11 @@ def stream_and_get(
1891
1957
 
1892
1958
  @usage_lib.entrypoint
1893
1959
  @annotations.client_api
1894
- def api_cancel(request_ids: Optional[Union[
1895
- server_common.RequestId, List[server_common.RequestId]]] = None,
1960
+ def api_cancel(request_ids: Optional[Union[server_common.RequestId[T],
1961
+ List[server_common.RequestId[T]],
1962
+ str, List[str]]] = None,
1896
1963
  all_users: bool = False,
1897
- silent: bool = False) -> server_common.RequestId:
1964
+ silent: bool = False) -> server_common.RequestId[List[str]]:
1898
1965
  """Aborts a request or all requests.
1899
1966
 
1900
1967
  Args:
@@ -1957,7 +2024,7 @@ def _local_api_server_running(kill: bool = False) -> bool:
1957
2024
  @usage_lib.entrypoint
1958
2025
  @annotations.client_api
1959
2026
  def api_status(
1960
- request_ids: Optional[List[server_common.RequestId]] = None,
2027
+ request_ids: Optional[List[Union[server_common.RequestId[T], str]]] = None,
1961
2028
  # pylint: disable=redefined-builtin
1962
2029
  all_status: bool = False
1963
2030
  ) -> List[payloads.RequestPayload]:
sky/client/sdk_async.py CHANGED
@@ -587,7 +587,7 @@ async def endpoints(
587
587
  cluster: str,
588
588
  port: Optional[Union[int, str]] = None,
589
589
  stream_logs: Optional[StreamConfig] = DEFAULT_STREAM_CONFIG
590
- ) -> Dict[int, str]:
590
+ ) -> Dict[str, str]:
591
591
  """Async version of endpoints() that gets the endpoint for a given cluster
592
592
  and port number."""
593
593
  request_id = await context_utils.to_thread(sdk.endpoints, cluster, port)
sky/core.py CHANGED
@@ -256,7 +256,7 @@ all_clusters, unmanaged_clusters, all_jobs, context
256
256
 
257
257
 
258
258
  def endpoints(cluster: str,
259
- port: Optional[Union[int, str]] = None) -> Dict[int, str]:
259
+ port: Optional[Union[int, str]] = None) -> Dict[str, str]:
260
260
  """Gets the endpoint for a given cluster and port number (endpoint).
261
261
 
262
262
  Args:
@@ -275,7 +275,10 @@ def endpoints(cluster: str,
275
275
  with rich_utils.safe_status(
276
276
  ux_utils.spinner_message(
277
277
  f'Fetching endpoints for cluster {cluster}')):
278
- return backend_utils.get_endpoints(cluster=cluster, port=port)
278
+ result = backend_utils.get_endpoints(cluster=cluster, port=port)
279
+ # Convert int keys to str keys.
280
+ # In JSON serialization, each key must be a string.
281
+ return {str(k): v for k, v in result.items()}
279
282
 
280
283
 
281
284
  @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/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.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-76efbdad99742559.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-1e6de35d15a8d432.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/YAirOGsV1z6B2RJ0VIUmD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/YAirOGsV1z6B2RJ0VIUmD/_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":"YAirOGsV1z6B2RJ0VIUmD","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/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.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-339efec49c0cc7d0.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-491a4d699d95e808.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/-DXZksWqf2waNHeU9YTQe/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-DXZksWqf2waNHeU9YTQe/_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":"-DXZksWqf2waNHeU9YTQe","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- self.__BUILD_MANIFEST=function(s,c,e,a,t,f,u,n,o,r,j,i,b,k,h){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-b30460f683e6ba96.js"],"/clusters/[cluster]":[s,c,e,f,u,j,r,a,t,n,i,b,o,k,h,"static/chunks/1871-980a395e92633a5c.js","static/chunks/pages/clusters/[cluster]-155d477a6c3e04e2.js"],"/clusters/[cluster]/[job]":[s,c,e,f,a,t,o,"static/chunks/pages/clusters/[cluster]/[job]-6fd1d2d8441aa54b.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-fc9222e26c8e2f0d.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-13d53fffc03ccb52.js"],"/jobs":["static/chunks/pages/jobs-cdc60fb5d371e16a.js"],"/jobs/pools/[pool]":[s,c,e,u,r,a,t,n,"static/chunks/pages/jobs/pools/[pool]-f5ccf5d39d87aebe.js"],"/jobs/[job]":[s,c,e,f,u,r,a,t,n,o,"static/chunks/pages/jobs/[job]-154f55cf8af55be5.js"],"/users":["static/chunks/pages/users-7ed36e44e779d5c7.js"],"/volumes":["static/chunks/pages/volumes-c9695d657f78b5dc.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-8f67be60165724cc.js"],"/workspaces/[name]":[s,c,e,f,u,j,a,t,n,i,b,o,k,h,"static/chunks/1141-a8a8f1adba34c892.js","static/chunks/pages/workspaces/[name]-f72f73bcef9541dc.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/pools/[pool]","/jobs/[job]","/users","/volumes","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-3d59f75e2ccf9321.js","static/chunks/6130-2be46d70a38f1e82.js","static/chunks/5739-d67458fcb1386c92.js","static/chunks/6989-6129c1cfbcf51063.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-318c3dca725e8e5d.js","static/chunks/6135-85426374db04811e.js","static/chunks/6212-7bd06f60ba693125.js","static/chunks/1559-6c00e20454194859.js","static/chunks/6990-0f886f16e0d55ff8.js","static/chunks/8056-019615038d6ce427.js","static/chunks/6601-3e21152fe16da09c.js","static/chunks/9159-11421c0f2909236f.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
1
+ self.__BUILD_MANIFEST=function(s,c,e,a,t,f,u,n,o,r,j,i,b,k,h){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-b30460f683e6ba96.js"],"/clusters/[cluster]":[s,c,e,f,u,j,r,a,t,n,i,b,o,k,h,"static/chunks/1871-980a395e92633a5c.js","static/chunks/pages/clusters/[cluster]-155d477a6c3e04e2.js"],"/clusters/[cluster]/[job]":[s,c,e,f,a,t,o,"static/chunks/pages/clusters/[cluster]/[job]-ae17cec0fc6483d9.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-fc9222e26c8e2f0d.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-13d53fffc03ccb52.js"],"/jobs":["static/chunks/pages/jobs-cdc60fb5d371e16a.js"],"/jobs/pools/[pool]":[s,c,e,u,r,a,t,n,"static/chunks/pages/jobs/pools/[pool]-f5ccf5d39d87aebe.js"],"/jobs/[job]":[s,c,e,f,u,r,a,t,n,o,"static/chunks/pages/jobs/[job]-154f55cf8af55be5.js"],"/users":["static/chunks/pages/users-7ed36e44e779d5c7.js"],"/volumes":["static/chunks/pages/volumes-c9695d657f78b5dc.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-8f67be60165724cc.js"],"/workspaces/[name]":[s,c,e,f,u,j,a,t,n,i,b,o,k,h,"static/chunks/1141-a8a8f1adba34c892.js","static/chunks/pages/workspaces/[name]-f72f73bcef9541dc.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/pools/[pool]","/jobs/[job]","/users","/volumes","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-3d59f75e2ccf9321.js","static/chunks/6130-2be46d70a38f1e82.js","static/chunks/5739-d67458fcb1386c92.js","static/chunks/6989-6129c1cfbcf51063.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-c9686994ddafcf01.js","static/chunks/6135-85426374db04811e.js","static/chunks/6212-7bd06f60ba693125.js","static/chunks/1559-6c00e20454194859.js","static/chunks/6990-0f886f16e0d55ff8.js","static/chunks/8056-34d27f51e6d1c631.js","static/chunks/6601-06114c982db410b6.js","static/chunks/9159-11421c0f2909236f.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -1 +1 @@
1
- "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6601],{99307:function(e,s,t){t.d(s,{Cl:function(){return l},OE:function(){return d}});var a=t(85893);t(67294);var r=t(55739),n=t(36989),c=t(53850);let l=e=>{switch(e){case"LAUNCHING":return"bg-blue-100 text-sky-blue";case"RUNNING":case"IN_USE":case"READY":return"bg-green-50 text-green-700";case"STOPPED":return"bg-yellow-100 text-yellow-800";case"TERMINATED":case"PENDING":case"UNKNOWN":default:return"bg-gray-100 text-gray-800";case"SUCCEEDED":case"PROVISIONING":case"CONTROLLER_INIT":case"REPLICA_INIT":return"bg-blue-50 text-blue-700";case"FAILED":case"FAILED_PRECHECKS":case"FAILED_NO_RESOURCE":case"FAILED_CONTROLLER":case"FAILED_INITIAL_DELAY":case"FAILED_PROBING":case"FAILED_PROVISION":case"FAILED_CLEANUP":case"CONTROLLER_FAILED":return"bg-red-50 text-red-700";case"CANCELLED":case"CANCELLING":case"NOT_READY":return"bg-yellow-50 text-yellow-700";case"RECOVERING":case"SHUTTING_DOWN":return"bg-orange-50 text-orange-700";case"SUBMITTED":return"bg-indigo-50 text-indigo-700";case"STARTING":return"bg-cyan-50 text-cyan-700";case"FAILED_SETUP":return"bg-pink-50 text-pink-700";case"PREEMPTED":case"NO_REPLICA":return"bg-purple-50 text-purple-700"}},i=e=>{switch(e){case"LAUNCHING":case"STARTING":case"PROVISIONING":case"SHUTTING_DOWN":return(0,a.jsx)(r.Z,{size:12,className:"w-3 h-3 mr-1"});case"RUNNING":case"IN_USE":default:return(0,a.jsx)(c.W2,{className:"w-3 h-3 mr-1"});case"STOPPED":case"PREEMPTED":return(0,a.jsx)(c.fp,{className:"w-3 h-3 mr-1"});case"TERMINATED":case"FAILED":case"CANCELLED":case"FAILED_INITIAL_DELAY":case"FAILED_PROBING":case"FAILED_PROVISION":case"FAILED_CLEANUP":case"CONTROLLER_FAILED":case"UNKNOWN":return(0,a.jsx)(c.Ps,{className:"w-3 h-3 mr-1"});case"SUCCEEDED":return(0,a.jsx)(c.Ye,{className:"w-3 h-3 mr-1"});case"PENDING":case"RECOVERING":case"SUBMITTED":case"CANCELLING":case"FAILED_SETUP":case"FAILED_PRECHECKS":case"FAILED_NO_RESOURCE":case"FAILED_CONTROLLER":case"READY":case"NOT_READY":case"CONTROLLER_INIT":case"REPLICA_INIT":case"NO_REPLICA":return(0,a.jsx)(c.J$,{className:"w-3 h-3 mr-1"})}},o=e=>{let s=l(e),t=i(e);return(0,a.jsxs)("span",{className:"".concat("inline-flex items-center px-2 py-1 rounded-full text-sm"," ").concat(s),children:[t,e]})},d=e=>{let{status:s}=e;return(0,a.jsx)(n.WH,{content:s,className:"text-muted-foreground text-sm",children:(0,a.jsx)("span",{children:o(s)})})}},20546:function(e,s,t){t.d(s,{H:function(){return d}});var a=t(85893);t(67294);var r=t(41664),n=t.n(r),c=t(45697),l=t.n(c);function i(e){return!!e&&"string"==typeof e&&e.toLowerCase().startsWith("sa-")}let o=()=>(0,a.jsx)("span",{className:"px-2 py-0.5 text-xs bg-blue-100 text-blue-700 rounded font-medium ml-1",children:"SA"}),d=e=>{let{username:s,userHash:t,className:r="flex items-center gap-1",linkClassName:c="text-gray-700 hover:text-blue-600 hover:underline",showBadge:l=!0}=e,d=i(t),u=i(t)?"/users?tab=service-accounts":"/users";return(0,a.jsxs)("div",{className:r,children:[(0,a.jsx)(n(),{href:u,className:c,children:s}),l&&d&&(0,a.jsx)(o,{})]})};d.propTypes={username:l().string.isRequired,userHash:l().string,className:l().string,linkClassName:l().string,showBadge:l().bool}},92128:function(e,s,t){t.d(s,{Oh:function(){return m},_R:function(){return x},cV:function(){return N}});var a=t(85893),r=t(67294),n=t(50326),c=t(30803),l=t(37673),i=t(27325),o=t(36989),d=t(93225),u=t(23001);function m(e){let{isOpen:s,onClose:t,cluster:d}=e,[u,m]=r.useState(!1),x=e=>{navigator.clipboard.writeText(e),m(!0),setTimeout(()=>m(!1),2e3)},N=["sky status ".concat(d),"ssh ".concat(d)],h=N.join("\n");return(0,a.jsx)(n.Vq,{open:s,onOpenChange:t,children:(0,a.jsxs)(n.cZ,{className:"sm:max-w-md",children:[(0,a.jsxs)(n.fK,{children:[(0,a.jsxs)(n.$N,{children:["Connect to: ",(0,a.jsx)("span",{className:"font-light",children:d})]}),(0,a.jsx)(n.Be,{children:"Use these instructions to connect to your cluster via SSH."})]}),(0,a.jsxs)("div",{className:"flex flex-col space-y-4",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2",children:"SSH Command"}),(0,a.jsx)(l.Zb,{className:"p-3 bg-gray-50",children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("pre",{className:"text-sm w-full whitespace-pre-wrap",children:N.map((e,s)=>(0,a.jsx)("code",{className:"block",children:e},s))}),(0,a.jsx)(o.WH,{content:u?"Copied!":"Copy command",children:(0,a.jsx)(c.z,{variant:"ghost",size:"icon",onClick:()=>x(h),className:"h-8 w-8 rounded-full",children:(0,a.jsx)(i.Z,{className:"h-4 w-4"})})})]})})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2",children:"Additional Information"}),(0,a.jsxs)("p",{className:"text-sm text-secondary-foreground",children:["Make sure to run"," ",(0,a.jsxs)("code",{className:"text-sm",children:["sky status ",d]})," first to have SkyPilot set up the SSH access."]})]})]})]})})}function x(e){let{isOpen:s,onClose:t,cluster:r}=e,m=(0,u.X)();return(0,a.jsx)(n.Vq,{open:s,onOpenChange:t,children:(0,a.jsx)(n.cZ,{className:"sm:max-w-3xl",children:(0,a.jsxs)(n.fK,{children:[(0,a.jsxs)(n.$N,{children:["Connect to: ",(0,a.jsx)("span",{className:"font-light",children:r})]}),(0,a.jsx)(n.Be,{children:(0,a.jsxs)("div",{className:"flex flex-col space-y-4",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2 my-2",children:"Setup SSH access"}),(0,a.jsx)(l.Zb,{className:"p-3 bg-gray-50",children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("pre",{className:"text-sm",children:(0,a.jsxs)("code",{children:["sky status ",r]})}),(0,a.jsx)(o.WH,{content:"Copy command",children:(0,a.jsx)(c.z,{variant:"ghost",size:"icon",onClick:()=>navigator.clipboard.writeText("sky status ".concat(r)),className:"h-8 w-8 rounded-full",children:(0,a.jsx)(i.Z,{className:"h-4 w-4"})})})]})})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2 my-2",children:"Connect with VSCode/Cursor"}),(0,a.jsx)(l.Zb,{className:"p-3 bg-gray-50",children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("pre",{className:"text-sm",children:(0,a.jsxs)("code",{children:["code --remote ssh-remote+",r]})}),(0,a.jsx)(o.WH,{content:"Copy command",children:(0,a.jsx)(c.z,{variant:"ghost",size:"icon",onClick:()=>navigator.clipboard.writeText("code --remote ssh-remote+".concat(r)),className:"h-8 w-8 rounded-full",children:(0,a.jsx)(i.Z,{className:"h-4 w-4"})})})]})})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium",children:"Or use the GUI to connect"}),(0,a.jsx)("div",{className:"relative ".concat(m?"-mt-5":"-mt-10"),style:{paddingBottom:"70%"},children:(0,a.jsxs)("video",{className:"absolute top-0 left-0 w-full h-full rounded-lg",controls:!0,autoPlay:!0,muted:!0,preload:"metadata",children:[(0,a.jsx)("source",{src:"".concat(d.GW,"/videos/cursor-small.mp4"),type:"video/mp4"}),"Your browser does not support the video tag."]})})]})]})})]})})})}function N(e){let{isOpen:s,onClose:t,onConfirm:r,title:l,message:i,confirmText:o="Confirm",confirmVariant:d="destructive",confirmClassName:u=null}=e;return(0,a.jsx)(n.Vq,{open:s,onOpenChange:t,children:(0,a.jsxs)(n.cZ,{className:"sm:max-w-md",children:[(0,a.jsxs)(n.fK,{children:[(0,a.jsx)(n.$N,{children:l}),(0,a.jsx)(n.Be,{children:i})]}),(0,a.jsxs)(n.cN,{className:"flex justify-end gap-2 pt-4",children:[(0,a.jsx)(c.z,{variant:"outline",onClick:t,children:"Cancel"}),(0,a.jsx)(c.z,{variant:u?void 0:d,className:u,onClick:()=>{r(),t()},children:o})]})]})})}},68764:function(e,s,t){t.d(s,{RM:function(){return i},SC:function(){return o},iA:function(){return c},pj:function(){return u},ss:function(){return d},xD:function(){return l}});var a=t(85893),r=t(67294),n=t(32350);let c=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("div",{className:"relative w-full overflow-auto",children:(0,a.jsx)("table",{ref:s,className:(0,n.cn)("w-full caption-bottom text-base",t),...r})})});c.displayName="Table";let l=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("thead",{ref:s,className:(0,n.cn)("[&_tr]:border-b",t),...r})});l.displayName="TableHeader";let i=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("tbody",{ref:s,className:(0,n.cn)("[&_tr:last-child]:border-0",t),...r})});i.displayName="TableBody",r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("tfoot",{ref:s,className:(0,n.cn)("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",t),...r})}).displayName="TableFooter";let o=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("tr",{ref:s,className:(0,n.cn)("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",t),...r})});o.displayName="TableRow";let d=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("th",{ref:s,className:(0,n.cn)("h-12 px-4 text-left align-middle font-medium text-[hsl(var(--text-strong))] [&:has([role=checkbox])]:pr-0",t),...r})});d.displayName="TableHead";let u=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("td",{ref:s,className:(0,n.cn)("p-4 align-middle [&:has([role=checkbox])]:pr-0",t),...r})});u.displayName="TableCell",r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("caption",{ref:s,className:(0,n.cn)("mt-4 text-base text-muted-foreground",t),...r})}).displayName="TableCaption"},94545:function(e,s,t){function a(e){return e.startsWith("sky-jobs-controller-")}function r(e,s,t){return null===s?e:[...e].sort((e,a)=>e[s]<a[s]?"ascending"===t?-1:1:e[s]>a[s]?"ascending"===t?1:-1:0)}t.d(s,{R0:function(){return r},Ym:function(){return a}})}}]);
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6601],{99307:function(e,s,t){t.d(s,{Cl:function(){return l},OE:function(){return d}});var a=t(85893);t(67294);var r=t(55739),n=t(36989),c=t(53850);let l=e=>{switch(e){case"LAUNCHING":return"bg-blue-100 text-sky-blue";case"RUNNING":case"IN_USE":case"READY":return"bg-green-50 text-green-700";case"STOPPED":return"bg-yellow-100 text-yellow-800";case"TERMINATED":case"PENDING":case"UNKNOWN":default:return"bg-gray-100 text-gray-800";case"SUCCEEDED":case"PROVISIONING":case"CONTROLLER_INIT":case"REPLICA_INIT":return"bg-blue-50 text-blue-700";case"FAILED":case"FAILED_PRECHECKS":case"FAILED_NO_RESOURCE":case"FAILED_CONTROLLER":case"FAILED_INITIAL_DELAY":case"FAILED_PROBING":case"FAILED_PROVISION":case"FAILED_CLEANUP":case"CONTROLLER_FAILED":return"bg-red-50 text-red-700";case"CANCELLED":case"CANCELLING":case"NOT_READY":return"bg-yellow-50 text-yellow-700";case"RECOVERING":case"SHUTTING_DOWN":return"bg-orange-50 text-orange-700";case"SUBMITTED":return"bg-indigo-50 text-indigo-700";case"STARTING":return"bg-cyan-50 text-cyan-700";case"FAILED_SETUP":return"bg-pink-50 text-pink-700";case"PREEMPTED":case"NO_REPLICA":return"bg-purple-50 text-purple-700"}},i=e=>{switch(e){case"LAUNCHING":case"STARTING":case"PROVISIONING":case"SHUTTING_DOWN":return(0,a.jsx)(r.Z,{size:12,className:"w-3 h-3 mr-1"});case"RUNNING":case"IN_USE":default:return(0,a.jsx)(c.W2,{className:"w-3 h-3 mr-1"});case"STOPPED":case"PREEMPTED":return(0,a.jsx)(c.fp,{className:"w-3 h-3 mr-1"});case"TERMINATED":case"FAILED":case"CANCELLED":case"FAILED_INITIAL_DELAY":case"FAILED_PROBING":case"FAILED_PROVISION":case"FAILED_CLEANUP":case"CONTROLLER_FAILED":case"UNKNOWN":return(0,a.jsx)(c.Ps,{className:"w-3 h-3 mr-1"});case"SUCCEEDED":return(0,a.jsx)(c.Ye,{className:"w-3 h-3 mr-1"});case"PENDING":case"RECOVERING":case"SUBMITTED":case"CANCELLING":case"FAILED_SETUP":case"FAILED_PRECHECKS":case"FAILED_NO_RESOURCE":case"FAILED_CONTROLLER":case"READY":case"NOT_READY":case"CONTROLLER_INIT":case"REPLICA_INIT":case"NO_REPLICA":return(0,a.jsx)(c.J$,{className:"w-3 h-3 mr-1"})}},o=e=>{let s=l(e),t=i(e);return(0,a.jsxs)("span",{className:"".concat("inline-flex items-center px-2 py-1 rounded-full text-sm"," ").concat(s),children:[t,e]})},d=e=>{let{status:s}=e;return(0,a.jsx)(n.WH,{content:s,className:"text-muted-foreground text-sm",children:(0,a.jsx)("span",{children:o(s)})})}},20546:function(e,s,t){t.d(s,{H:function(){return d}});var a=t(85893);t(67294);var r=t(41664),n=t.n(r),c=t(45697),l=t.n(c);function i(e){return!!e&&"string"==typeof e&&e.toLowerCase().startsWith("sa-")}let o=()=>(0,a.jsx)("span",{className:"px-2 py-0.5 text-xs bg-blue-100 text-blue-700 rounded font-medium ml-1",children:"SA"}),d=e=>{let{username:s,userHash:t,className:r="flex items-center gap-1",linkClassName:c="text-gray-700 hover:text-blue-600 hover:underline",showBadge:l=!0}=e,d=i(t),u=i(t)?"/users?tab=service-accounts":"/users";return(0,a.jsxs)("div",{className:r,children:[(0,a.jsx)(n(),{href:u,className:c,children:s}),l&&d&&(0,a.jsx)(o,{})]})};d.propTypes={username:l().string.isRequired,userHash:l().string,className:l().string,linkClassName:l().string,showBadge:l().bool}},92128:function(e,s,t){t.d(s,{Oh:function(){return m},_R:function(){return x},cV:function(){return N}});var a=t(85893),r=t(67294),n=t(50326),c=t(30803),l=t(37673),i=t(27325),o=t(36989),d=t(93225),u=t(23001);function m(e){let{isOpen:s,onClose:t,cluster:d}=e,[u,m]=r.useState(!1),x=e=>{navigator.clipboard.writeText(e),m(!0),setTimeout(()=>m(!1),2e3)},N=["sky status ".concat(d),"ssh ".concat(d)],h=N.join("\n");return(0,a.jsx)(n.Vq,{open:s,onOpenChange:t,children:(0,a.jsxs)(n.cZ,{className:"sm:max-w-md",children:[(0,a.jsxs)(n.fK,{children:[(0,a.jsxs)(n.$N,{children:["Connect to: ",(0,a.jsx)("span",{className:"font-light",children:d})]}),(0,a.jsx)(n.Be,{children:"Use these instructions to connect to your cluster via SSH."})]}),(0,a.jsxs)("div",{className:"flex flex-col space-y-4",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2",children:"SSH Command"}),(0,a.jsx)(l.Zb,{className:"p-3 bg-gray-50",children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("pre",{className:"text-sm w-full whitespace-pre-wrap",children:N.map((e,s)=>(0,a.jsx)("code",{className:"block",children:e},s))}),(0,a.jsx)(o.WH,{content:u?"Copied!":"Copy command",children:(0,a.jsx)(c.z,{variant:"ghost",size:"icon",onClick:()=>x(h),className:"h-8 w-8 rounded-full",children:(0,a.jsx)(i.Z,{className:"h-4 w-4"})})})]})})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2",children:"Additional Information"}),(0,a.jsxs)("p",{className:"text-sm text-secondary-foreground",children:["Make sure to run"," ",(0,a.jsxs)("code",{className:"text-sm",children:["sky status ",d]})," first to have SkyPilot set up the SSH access."]})]})]})]})})}function x(e){let{isOpen:s,onClose:t,cluster:r}=e,m=(0,u.X)();return(0,a.jsx)(n.Vq,{open:s,onOpenChange:t,children:(0,a.jsx)(n.cZ,{className:"sm:max-w-3xl",children:(0,a.jsxs)(n.fK,{children:[(0,a.jsxs)(n.$N,{children:["Connect to: ",(0,a.jsx)("span",{className:"font-light",children:r})]}),(0,a.jsx)(n.Be,{children:(0,a.jsxs)("div",{className:"flex flex-col space-y-4",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2 my-2",children:"Setup SSH access"}),(0,a.jsx)(l.Zb,{className:"p-3 bg-gray-50",children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("pre",{className:"text-sm",children:(0,a.jsxs)("code",{children:["sky status ",r]})}),(0,a.jsx)(o.WH,{content:"Copy command",children:(0,a.jsx)(c.z,{variant:"ghost",size:"icon",onClick:()=>navigator.clipboard.writeText("sky status ".concat(r)),className:"h-8 w-8 rounded-full",children:(0,a.jsx)(i.Z,{className:"h-4 w-4"})})})]})})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium mb-2 my-2",children:"Connect with VSCode/Cursor"}),(0,a.jsx)(l.Zb,{className:"p-3 bg-gray-50",children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("pre",{className:"text-sm",children:(0,a.jsxs)("code",{children:["code --remote ssh-remote+",r,' "/home"']})}),(0,a.jsx)(o.WH,{content:"Copy command",children:(0,a.jsx)(c.z,{variant:"ghost",size:"icon",onClick:()=>navigator.clipboard.writeText("code --remote ssh-remote+".concat(r,' "/home"')),className:"h-8 w-8 rounded-full",children:(0,a.jsx)(i.Z,{className:"h-4 w-4"})})})]})})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-medium",children:"Or use the GUI to connect"}),(0,a.jsx)("div",{className:"relative ".concat(m?"-mt-5":"-mt-10"),style:{paddingBottom:"70%"},children:(0,a.jsxs)("video",{className:"absolute top-0 left-0 w-full h-full rounded-lg",controls:!0,autoPlay:!0,muted:!0,preload:"metadata",children:[(0,a.jsx)("source",{src:"".concat(d.GW,"/videos/cursor-small.mp4"),type:"video/mp4"}),"Your browser does not support the video tag."]})})]})]})})]})})})}function N(e){let{isOpen:s,onClose:t,onConfirm:r,title:l,message:i,confirmText:o="Confirm",confirmVariant:d="destructive",confirmClassName:u=null}=e;return(0,a.jsx)(n.Vq,{open:s,onOpenChange:t,children:(0,a.jsxs)(n.cZ,{className:"sm:max-w-md",children:[(0,a.jsxs)(n.fK,{children:[(0,a.jsx)(n.$N,{children:l}),(0,a.jsx)(n.Be,{children:i})]}),(0,a.jsxs)(n.cN,{className:"flex justify-end gap-2 pt-4",children:[(0,a.jsx)(c.z,{variant:"outline",onClick:t,children:"Cancel"}),(0,a.jsx)(c.z,{variant:u?void 0:d,className:u,onClick:()=>{r(),t()},children:o})]})]})})}},68764:function(e,s,t){t.d(s,{RM:function(){return i},SC:function(){return o},iA:function(){return c},pj:function(){return u},ss:function(){return d},xD:function(){return l}});var a=t(85893),r=t(67294),n=t(32350);let c=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("div",{className:"relative w-full overflow-auto",children:(0,a.jsx)("table",{ref:s,className:(0,n.cn)("w-full caption-bottom text-base",t),...r})})});c.displayName="Table";let l=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("thead",{ref:s,className:(0,n.cn)("[&_tr]:border-b",t),...r})});l.displayName="TableHeader";let i=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("tbody",{ref:s,className:(0,n.cn)("[&_tr:last-child]:border-0",t),...r})});i.displayName="TableBody",r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("tfoot",{ref:s,className:(0,n.cn)("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",t),...r})}).displayName="TableFooter";let o=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("tr",{ref:s,className:(0,n.cn)("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",t),...r})});o.displayName="TableRow";let d=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("th",{ref:s,className:(0,n.cn)("h-12 px-4 text-left align-middle font-medium text-[hsl(var(--text-strong))] [&:has([role=checkbox])]:pr-0",t),...r})});d.displayName="TableHead";let u=r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("td",{ref:s,className:(0,n.cn)("p-4 align-middle [&:has([role=checkbox])]:pr-0",t),...r})});u.displayName="TableCell",r.forwardRef((e,s)=>{let{className:t,...r}=e;return(0,a.jsx)("caption",{ref:s,className:(0,n.cn)("mt-4 text-base text-muted-foreground",t),...r})}).displayName="TableCaption"},94545:function(e,s,t){function a(e){return e.startsWith("sky-jobs-controller-")}function r(e,s,t){return null===s?e:[...e].sort((e,a)=>e[s]<a[s]?"ascending"===t?-1:1:e[s]>a[s]?"ascending"===t?1:-1:0)}t.d(s,{R0:function(){return r},Ym:function(){return a}})}}]);