skypilot-nightly 1.0.0.dev20250417__py3-none-any.whl → 1.0.0.dev20250421__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. sky/__init__.py +2 -2
  2. sky/backends/backend_utils.py +28 -0
  3. sky/backends/wheel_utils.py +9 -0
  4. sky/cli.py +92 -19
  5. sky/client/cli.py +92 -19
  6. sky/client/common.py +10 -3
  7. sky/client/sdk.py +6 -3
  8. sky/dashboard/out/404.html +1 -0
  9. sky/dashboard/out/_next/static/chunks/236-d437cf66e68a6f64.js +6 -0
  10. sky/dashboard/out/_next/static/chunks/312-c3c8845990db8ffc.js +15 -0
  11. sky/dashboard/out/_next/static/chunks/37-72fdc8f71d6e4784.js +6 -0
  12. sky/dashboard/out/_next/static/chunks/678-206dddca808e6d16.js +59 -0
  13. sky/dashboard/out/_next/static/chunks/845-2ea1cc63ba1f4067.js +1 -0
  14. sky/dashboard/out/_next/static/chunks/979-7cd0778078b9cfad.js +1 -0
  15. sky/dashboard/out/_next/static/chunks/fd9d1056-2821b0f0cabcd8bd.js +1 -0
  16. sky/dashboard/out/_next/static/chunks/framework-87d061ee6ed71b28.js +33 -0
  17. sky/dashboard/out/_next/static/chunks/main-app-241eb28595532291.js +1 -0
  18. sky/dashboard/out/_next/static/chunks/main-e0e2335212e72357.js +1 -0
  19. sky/dashboard/out/_next/static/chunks/pages/_app-3001e84c61acddfb.js +1 -0
  20. sky/dashboard/out/_next/static/chunks/pages/_error-1be831200e60c5c0.js +1 -0
  21. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-b09f7fbf6d5d74f6.js +1 -0
  22. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-b57ec043f09c5813.js +1 -0
  23. sky/dashboard/out/_next/static/chunks/pages/clusters-a93b93e10b8b074e.js +1 -0
  24. sky/dashboard/out/_next/static/chunks/pages/index-f9f039532ca8cbc4.js +1 -0
  25. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-ef2e0e91a9222cac.js +1 -0
  26. sky/dashboard/out/_next/static/chunks/pages/jobs-a75029b67aab6a2e.js +1 -0
  27. sky/dashboard/out/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js +1 -0
  28. sky/dashboard/out/_next/static/chunks/webpack-830f59b8404e96b8.js +1 -0
  29. sky/dashboard/out/_next/static/css/f3538cd90cfca88c.css +3 -0
  30. sky/dashboard/out/_next/static/mS9YfLA5hhsJMeBj9W8J7/_buildManifest.js +1 -0
  31. sky/dashboard/out/_next/static/mS9YfLA5hhsJMeBj9W8J7/_ssgManifest.js +1 -0
  32. sky/dashboard/out/clusters/[cluster]/[job].html +1 -0
  33. sky/dashboard/out/clusters/[cluster].html +1 -0
  34. sky/dashboard/out/clusters.html +1 -0
  35. sky/dashboard/out/favicon.ico +0 -0
  36. sky/dashboard/out/index.html +1 -0
  37. sky/dashboard/out/jobs/[job].html +1 -0
  38. sky/dashboard/out/jobs.html +1 -0
  39. sky/dashboard/out/skypilot.svg +15 -0
  40. sky/dashboard/out/videos/cursor-small.mp4 +0 -0
  41. sky/data/data_transfer.py +2 -1
  42. sky/data/storage.py +24 -14
  43. sky/optimizer.py +7 -9
  44. sky/provision/provisioner.py +2 -1
  45. sky/resources.py +11 -2
  46. sky/serve/__init__.py +2 -0
  47. sky/serve/autoscalers.py +6 -2
  48. sky/serve/client/sdk.py +61 -0
  49. sky/serve/replica_managers.py +6 -8
  50. sky/serve/serve_utils.py +33 -1
  51. sky/serve/server/core.py +187 -5
  52. sky/serve/server/server.py +28 -0
  53. sky/server/common.py +19 -1
  54. sky/server/constants.py +6 -0
  55. sky/server/requests/executor.py +4 -0
  56. sky/server/requests/payloads.py +12 -15
  57. sky/server/server.py +43 -0
  58. sky/setup_files/MANIFEST.in +1 -0
  59. sky/sky_logging.py +10 -0
  60. sky/skypilot_config.py +51 -31
  61. sky/templates/kubernetes-ray.yml.j2 +6 -2
  62. sky/utils/config_utils.py +0 -1
  63. sky/utils/controller_utils.py +0 -1
  64. {skypilot_nightly-1.0.0.dev20250417.dist-info → skypilot_nightly-1.0.0.dev20250421.dist-info}/METADATA +1 -1
  65. {skypilot_nightly-1.0.0.dev20250417.dist-info → skypilot_nightly-1.0.0.dev20250421.dist-info}/RECORD +69 -36
  66. {skypilot_nightly-1.0.0.dev20250417.dist-info → skypilot_nightly-1.0.0.dev20250421.dist-info}/WHEEL +1 -1
  67. {skypilot_nightly-1.0.0.dev20250417.dist-info → skypilot_nightly-1.0.0.dev20250421.dist-info}/entry_points.txt +0 -0
  68. {skypilot_nightly-1.0.0.dev20250417.dist-info → skypilot_nightly-1.0.0.dev20250421.dist-info}/licenses/LICENSE +0 -0
  69. {skypilot_nightly-1.0.0.dev20250417.dist-info → skypilot_nightly-1.0.0.dev20250421.dist-info}/top_level.txt +0 -0
sky/__init__.py CHANGED
@@ -5,7 +5,7 @@ from typing import Optional
5
5
  import urllib.request
6
6
 
7
7
  # Replaced with the current commit when building the wheels.
8
- _SKYPILOT_COMMIT_SHA = 'ff17963ce2804e65e3aa2cb1fb02dcd247f680e6'
8
+ _SKYPILOT_COMMIT_SHA = 'd37ba6f11593127305c73cb1b1a03dc6da8452b7'
9
9
 
10
10
 
11
11
  def _get_git_commit():
@@ -35,7 +35,7 @@ def _get_git_commit():
35
35
 
36
36
 
37
37
  __commit__ = _get_git_commit()
38
- __version__ = '1.0.0.dev20250417'
38
+ __version__ = '1.0.0.dev20250421'
39
39
  __root_dir__ = os.path.dirname(os.path.abspath(__file__))
40
40
 
41
41
 
@@ -2582,11 +2582,36 @@ def get_clusters(
2582
2582
  logger.info(f'Cluster(s) not found: {bright}{clusters_str}{reset}.')
2583
2583
  records = new_records
2584
2584
 
2585
+ def _update_record_with_resources(record: Optional[Dict[str, Any]]) -> None:
2586
+ """Add the resources to the record."""
2587
+ if record is None:
2588
+ return
2589
+ handle = record['handle']
2590
+ if handle is None:
2591
+ return
2592
+ record['nodes'] = handle.launched_nodes
2593
+ if handle.launched_resources is None:
2594
+ return
2595
+ record['cloud'] = (f'{handle.launched_resources.cloud}'
2596
+ if handle.launched_resources.cloud else None)
2597
+ record['region'] = (f'{handle.launched_resources.region}'
2598
+ if handle.launched_resources.region else None)
2599
+ record['cpus'] = (f'{handle.launched_resources.cpus}'
2600
+ if handle.launched_resources.cpus else None)
2601
+ record['memory'] = (f'{handle.launched_resources.memory}'
2602
+ if handle.launched_resources.memory else None)
2603
+ record['accelerators'] = (f'{handle.launched_resources.accelerators}'
2604
+ if handle.launched_resources.accelerators else
2605
+ None)
2606
+
2585
2607
  # Add auth_config to the records
2586
2608
  for record in records:
2587
2609
  _update_record_with_credentials_and_resources_str(record)
2588
2610
 
2589
2611
  if refresh == common.StatusRefreshMode.NONE:
2612
+ # Add resources to the records
2613
+ for record in records:
2614
+ _update_record_with_resources(record)
2590
2615
  return records
2591
2616
 
2592
2617
  plural = 's' if len(records) > 1 else ''
@@ -2662,6 +2687,9 @@ def get_clusters(
2662
2687
  for cluster_name, e in failed_clusters:
2663
2688
  logger.warning(f' {bright}{cluster_name}{reset}: {e}')
2664
2689
 
2690
+ # Add resources to the records
2691
+ for record in kept_records:
2692
+ _update_record_with_resources(record)
2665
2693
  return kept_records
2666
2694
 
2667
2695
 
@@ -85,6 +85,15 @@ def _build_sky_wheel() -> pathlib.Path:
85
85
  for f in setup_files_dir.iterdir():
86
86
  if f.is_file() and f.name != 'setup.py':
87
87
  shutil.copy(str(f), str(tmp_dir))
88
+ if f.name == 'MANIFEST.in':
89
+ # Remove the line `sky/dashboard/out`, so we do not
90
+ # include the dashboard files in the internal wheel
91
+ import fileinput # pylint: disable=import-outside-toplevel
92
+ with fileinput.input(tmp_dir / f.name,
93
+ inplace=True) as file:
94
+ for line in file:
95
+ if 'sky/dashboard/out' not in line:
96
+ print(line, end='')
88
97
 
89
98
  init_file_path = SKY_PACKAGE_PATH / '__init__.py'
90
99
  init_file_content = init_file_path.read_text()
sky/cli.py CHANGED
@@ -28,6 +28,7 @@ import datetime
28
28
  import functools
29
29
  import getpass
30
30
  import os
31
+ import pathlib
31
32
  import shlex
32
33
  import shutil
33
34
  import subprocess
@@ -4867,8 +4868,14 @@ def serve_down(
4867
4868
  default=False,
4868
4869
  required=False,
4869
4870
  help='Show the load balancer logs of this service.')
4871
+ @click.option('--sync-down',
4872
+ '-s',
4873
+ is_flag=True,
4874
+ default=False,
4875
+ help='Sync down logs to the local machine. Can be combined with '
4876
+ '--controller, --load-balancer, or a replica ID to narrow scope.')
4870
4877
  @click.argument('service_name', required=True, type=str)
4871
- @click.argument('replica_id', required=False, type=int)
4878
+ @click.argument('replica_ids', required=False, type=int, nargs=-1)
4872
4879
  @usage_lib.entrypoint
4873
4880
  # TODO(tian): Add default argument for this CLI if none of the flags are
4874
4881
  # specified.
@@ -4877,9 +4884,13 @@ def serve_logs(
4877
4884
  follow: bool,
4878
4885
  controller: bool,
4879
4886
  load_balancer: bool,
4880
- replica_id: Optional[int],
4887
+ replica_ids: Tuple[int, ...],
4888
+ sync_down: bool,
4881
4889
  ):
4882
- """Tail the log of a service.
4890
+ """Tail or sync down logs of a service.
4891
+
4892
+ Logs can be tailed from one target (controller, load balancer, or a single
4893
+ replica) or synced down from multiple targets simultaneously.
4883
4894
 
4884
4895
  Example:
4885
4896
 
@@ -4893,27 +4904,89 @@ def serve_logs(
4893
4904
  \b
4894
4905
  # Tail the logs of replica 1
4895
4906
  sky serve logs [SERVICE_NAME] 1
4907
+ \b
4908
+ # Sync down all logs of the service (controller, LB, all replicas)
4909
+ sky serve logs [SERVICE_NAME] --sync-down
4910
+ \b
4911
+ # Sync down controller logs and logs for replicas 1 and 3
4912
+ sky serve logs [SERVICE_NAME] 1 3 --controller --sync-down
4896
4913
  """
4897
- have_replica_id = replica_id is not None
4898
- num_flags = (controller + load_balancer + have_replica_id)
4899
- if num_flags > 1:
4900
- raise click.UsageError('At most one of --controller, --load-balancer, '
4901
- '[REPLICA_ID] can be specified.')
4902
- if num_flags == 0:
4903
- raise click.UsageError('One of --controller, --load-balancer, '
4904
- '[REPLICA_ID] must be specified.')
4914
+ chosen_components: Set[serve_lib.ServiceComponent] = set()
4905
4915
  if controller:
4906
- target_component = serve_lib.ServiceComponent.CONTROLLER
4907
- elif load_balancer:
4908
- target_component = serve_lib.ServiceComponent.LOAD_BALANCER
4909
- else:
4910
- # Already checked that num_flags == 1.
4911
- assert replica_id is not None
4912
- target_component = serve_lib.ServiceComponent.REPLICA
4916
+ chosen_components.add(serve_lib.ServiceComponent.CONTROLLER)
4917
+ if load_balancer:
4918
+ chosen_components.add(serve_lib.ServiceComponent.LOAD_BALANCER)
4919
+ # replica_ids contains the specific replica IDs provided by the user.
4920
+ # If it's not empty, it implies the user wants replica logs.
4921
+ if replica_ids:
4922
+ chosen_components.add(serve_lib.ServiceComponent.REPLICA)
4923
+
4924
+ if sync_down:
4925
+ # For sync-down, multiple targets are allowed.
4926
+ # If no specific components/replicas are mentioned, sync all.
4927
+ # Note: Multiple replicas or targets can only be specified when
4928
+ # using --sync-down.
4929
+ targets_to_sync = list(chosen_components)
4930
+ if not targets_to_sync and not replica_ids:
4931
+ # Default to all components if nothing specific is requested
4932
+ targets_to_sync = [
4933
+ serve_lib.ServiceComponent.CONTROLLER,
4934
+ serve_lib.ServiceComponent.LOAD_BALANCER,
4935
+ serve_lib.ServiceComponent.REPLICA,
4936
+ ]
4937
+
4938
+ timestamp = sky_logging.get_run_timestamp()
4939
+ log_dir = (pathlib.Path(constants.SKY_LOGS_DIRECTORY) / 'service' /
4940
+ f'{service_name}_{timestamp}').expanduser()
4941
+ log_dir.mkdir(parents=True, exist_ok=True)
4942
+
4943
+ with rich_utils.client_status(
4944
+ ux_utils.spinner_message('Downloading service logs...')):
4945
+ serve_lib.sync_down_logs(service_name,
4946
+ local_dir=str(log_dir),
4947
+ targets=targets_to_sync,
4948
+ replica_ids=list(replica_ids))
4949
+ style = colorama.Style
4950
+ fore = colorama.Fore
4951
+ logger.info(f'{fore.CYAN}Service {service_name} logs: '
4952
+ f'{log_dir}{style.RESET_ALL}')
4953
+ return
4954
+
4955
+ # Tailing requires exactly one target.
4956
+ num_targets = len(chosen_components)
4957
+ # If REPLICA component is chosen, len(replica_ids) must be 1 for tailing.
4958
+ if serve_lib.ServiceComponent.REPLICA in chosen_components:
4959
+ if len(replica_ids) != 1:
4960
+ raise click.UsageError(
4961
+ 'Can only tail logs from a single replica at a time. '
4962
+ 'Provide exactly one REPLICA_ID or use --sync-down '
4963
+ 'to download logs from multiple replicas.')
4964
+ # If replica is chosen and len is 1, num_targets effectively counts it.
4965
+ # We need to ensure no other component (controller/LB) is selected.
4966
+ if num_targets > 1:
4967
+ raise click.UsageError(
4968
+ 'Can only tail logs from one target at a time (controller, '
4969
+ 'load balancer, or a single replica). Use --sync-down '
4970
+ 'to download logs from multiple sources.')
4971
+ elif num_targets == 0:
4972
+ raise click.UsageError(
4973
+ 'Specify a target to tail: --controller, --load-balancer, or '
4974
+ 'a REPLICA_ID.')
4975
+ elif num_targets > 1:
4976
+ raise click.UsageError(
4977
+ 'Can only tail logs from one target at a time. Use --sync-down '
4978
+ 'to download logs from multiple sources.')
4979
+
4980
+ # At this point, we have exactly one target for tailing.
4981
+ assert len(chosen_components) == 1
4982
+ assert len(replica_ids) in [0, 1]
4983
+ target_component = chosen_components.pop()
4984
+ target_replica_id: Optional[int] = replica_ids[0] if replica_ids else None
4985
+
4913
4986
  try:
4914
4987
  serve_lib.tail_logs(service_name,
4915
4988
  target=target_component,
4916
- replica_id=replica_id,
4989
+ replica_id=target_replica_id,
4917
4990
  follow=follow)
4918
4991
  except exceptions.ClusterNotUpError:
4919
4992
  with ux_utils.print_exception_no_traceback():
sky/client/cli.py CHANGED
@@ -28,6 +28,7 @@ import datetime
28
28
  import functools
29
29
  import getpass
30
30
  import os
31
+ import pathlib
31
32
  import shlex
32
33
  import shutil
33
34
  import subprocess
@@ -4867,8 +4868,14 @@ def serve_down(
4867
4868
  default=False,
4868
4869
  required=False,
4869
4870
  help='Show the load balancer logs of this service.')
4871
+ @click.option('--sync-down',
4872
+ '-s',
4873
+ is_flag=True,
4874
+ default=False,
4875
+ help='Sync down logs to the local machine. Can be combined with '
4876
+ '--controller, --load-balancer, or a replica ID to narrow scope.')
4870
4877
  @click.argument('service_name', required=True, type=str)
4871
- @click.argument('replica_id', required=False, type=int)
4878
+ @click.argument('replica_ids', required=False, type=int, nargs=-1)
4872
4879
  @usage_lib.entrypoint
4873
4880
  # TODO(tian): Add default argument for this CLI if none of the flags are
4874
4881
  # specified.
@@ -4877,9 +4884,13 @@ def serve_logs(
4877
4884
  follow: bool,
4878
4885
  controller: bool,
4879
4886
  load_balancer: bool,
4880
- replica_id: Optional[int],
4887
+ replica_ids: Tuple[int, ...],
4888
+ sync_down: bool,
4881
4889
  ):
4882
- """Tail the log of a service.
4890
+ """Tail or sync down logs of a service.
4891
+
4892
+ Logs can be tailed from one target (controller, load balancer, or a single
4893
+ replica) or synced down from multiple targets simultaneously.
4883
4894
 
4884
4895
  Example:
4885
4896
 
@@ -4893,27 +4904,89 @@ def serve_logs(
4893
4904
  \b
4894
4905
  # Tail the logs of replica 1
4895
4906
  sky serve logs [SERVICE_NAME] 1
4907
+ \b
4908
+ # Sync down all logs of the service (controller, LB, all replicas)
4909
+ sky serve logs [SERVICE_NAME] --sync-down
4910
+ \b
4911
+ # Sync down controller logs and logs for replicas 1 and 3
4912
+ sky serve logs [SERVICE_NAME] 1 3 --controller --sync-down
4896
4913
  """
4897
- have_replica_id = replica_id is not None
4898
- num_flags = (controller + load_balancer + have_replica_id)
4899
- if num_flags > 1:
4900
- raise click.UsageError('At most one of --controller, --load-balancer, '
4901
- '[REPLICA_ID] can be specified.')
4902
- if num_flags == 0:
4903
- raise click.UsageError('One of --controller, --load-balancer, '
4904
- '[REPLICA_ID] must be specified.')
4914
+ chosen_components: Set[serve_lib.ServiceComponent] = set()
4905
4915
  if controller:
4906
- target_component = serve_lib.ServiceComponent.CONTROLLER
4907
- elif load_balancer:
4908
- target_component = serve_lib.ServiceComponent.LOAD_BALANCER
4909
- else:
4910
- # Already checked that num_flags == 1.
4911
- assert replica_id is not None
4912
- target_component = serve_lib.ServiceComponent.REPLICA
4916
+ chosen_components.add(serve_lib.ServiceComponent.CONTROLLER)
4917
+ if load_balancer:
4918
+ chosen_components.add(serve_lib.ServiceComponent.LOAD_BALANCER)
4919
+ # replica_ids contains the specific replica IDs provided by the user.
4920
+ # If it's not empty, it implies the user wants replica logs.
4921
+ if replica_ids:
4922
+ chosen_components.add(serve_lib.ServiceComponent.REPLICA)
4923
+
4924
+ if sync_down:
4925
+ # For sync-down, multiple targets are allowed.
4926
+ # If no specific components/replicas are mentioned, sync all.
4927
+ # Note: Multiple replicas or targets can only be specified when
4928
+ # using --sync-down.
4929
+ targets_to_sync = list(chosen_components)
4930
+ if not targets_to_sync and not replica_ids:
4931
+ # Default to all components if nothing specific is requested
4932
+ targets_to_sync = [
4933
+ serve_lib.ServiceComponent.CONTROLLER,
4934
+ serve_lib.ServiceComponent.LOAD_BALANCER,
4935
+ serve_lib.ServiceComponent.REPLICA,
4936
+ ]
4937
+
4938
+ timestamp = sky_logging.get_run_timestamp()
4939
+ log_dir = (pathlib.Path(constants.SKY_LOGS_DIRECTORY) / 'service' /
4940
+ f'{service_name}_{timestamp}').expanduser()
4941
+ log_dir.mkdir(parents=True, exist_ok=True)
4942
+
4943
+ with rich_utils.client_status(
4944
+ ux_utils.spinner_message('Downloading service logs...')):
4945
+ serve_lib.sync_down_logs(service_name,
4946
+ local_dir=str(log_dir),
4947
+ targets=targets_to_sync,
4948
+ replica_ids=list(replica_ids))
4949
+ style = colorama.Style
4950
+ fore = colorama.Fore
4951
+ logger.info(f'{fore.CYAN}Service {service_name} logs: '
4952
+ f'{log_dir}{style.RESET_ALL}')
4953
+ return
4954
+
4955
+ # Tailing requires exactly one target.
4956
+ num_targets = len(chosen_components)
4957
+ # If REPLICA component is chosen, len(replica_ids) must be 1 for tailing.
4958
+ if serve_lib.ServiceComponent.REPLICA in chosen_components:
4959
+ if len(replica_ids) != 1:
4960
+ raise click.UsageError(
4961
+ 'Can only tail logs from a single replica at a time. '
4962
+ 'Provide exactly one REPLICA_ID or use --sync-down '
4963
+ 'to download logs from multiple replicas.')
4964
+ # If replica is chosen and len is 1, num_targets effectively counts it.
4965
+ # We need to ensure no other component (controller/LB) is selected.
4966
+ if num_targets > 1:
4967
+ raise click.UsageError(
4968
+ 'Can only tail logs from one target at a time (controller, '
4969
+ 'load balancer, or a single replica). Use --sync-down '
4970
+ 'to download logs from multiple sources.')
4971
+ elif num_targets == 0:
4972
+ raise click.UsageError(
4973
+ 'Specify a target to tail: --controller, --load-balancer, or '
4974
+ 'a REPLICA_ID.')
4975
+ elif num_targets > 1:
4976
+ raise click.UsageError(
4977
+ 'Can only tail logs from one target at a time. Use --sync-down '
4978
+ 'to download logs from multiple sources.')
4979
+
4980
+ # At this point, we have exactly one target for tailing.
4981
+ assert len(chosen_components) == 1
4982
+ assert len(replica_ids) in [0, 1]
4983
+ target_component = chosen_components.pop()
4984
+ target_replica_id: Optional[int] = replica_ids[0] if replica_ids else None
4985
+
4913
4986
  try:
4914
4987
  serve_lib.tail_logs(service_name,
4915
4988
  target=target_component,
4916
- replica_id=replica_id,
4989
+ replica_id=target_replica_id,
4917
4990
  follow=follow)
4918
4991
  except exceptions.ClusterNotUpError:
4919
4992
  with ux_utils.print_exception_no_traceback():
sky/client/common.py CHANGED
@@ -53,11 +53,18 @@ API_SERVER_REQUEST_CONNECTION_TIMEOUT_SECONDS = 5
53
53
 
54
54
 
55
55
  def download_logs_from_api_server(
56
- paths_on_api_server: Iterable[str]) -> Dict[str, str]:
56
+ paths_on_api_server: Iterable[str],
57
+ remote_machine_prefix: str = str(
58
+ server_common.api_server_user_logs_dir_prefix()),
59
+ local_machine_prefix: str = constants.SKY_LOGS_DIRECTORY
60
+ ) -> Dict[str, str]:
57
61
  """Downloads the logs from the API server.
58
62
 
59
63
  Args:
60
64
  paths_on_api_server: The paths on the API server to download.
65
+ remote_machine_prefix: The prefix of the remote machine to save the
66
+ logs.
67
+ local_machine_prefix: The prefix of the local machine to save the logs.
61
68
 
62
69
  Returns:
63
70
  A dictionary mapping the remote path on API server to the local path.
@@ -69,8 +76,8 @@ def download_logs_from_api_server(
69
76
  # This should be moved to remote API server. A proper way might be
70
77
  # set the returned path to be started with a special prefix, instead
71
78
  # of using the `api_server_user_logs_dir_prefix()`.
72
- str(server_common.api_server_user_logs_dir_prefix()),
73
- constants.SKY_LOGS_DIRECTORY) for remote_path in paths_on_api_server
79
+ remote_machine_prefix,
80
+ local_machine_prefix) for remote_path in paths_on_api_server
74
81
  }
75
82
  body = payloads.DownloadBody(folder_paths=list(paths_on_api_server),)
76
83
  response = requests.post(f'{server_common.get_server_url()}/download',
sky/client/sdk.py CHANGED
@@ -1821,6 +1821,9 @@ def api_login(endpoint: Optional[str] = None) -> None:
1821
1821
  else:
1822
1822
  config = skypilot_config.get_user_config()
1823
1823
  config.set_nested(('api_server', 'endpoint'), endpoint)
1824
- common_utils.dump_yaml(str(config_path), config)
1825
- click.secho(f'Logged in to SkyPilot API server at {endpoint}',
1826
- fg='green')
1824
+ common_utils.dump_yaml(str(config_path), dict(config))
1825
+ dashboard_msg = f'Dashboard: {endpoint}/dashboard'
1826
+ click.secho(
1827
+ f'Logged in to SkyPilot API server at {endpoint}.'
1828
+ f' {dashboard_msg}',
1829
+ fg='green')
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link rel="preload" href="/dashboard/_next/static/css/f3538cd90cfca88c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/f3538cd90cfca88c.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-830f59b8404e96b8.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-3001e84c61acddfb.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/mS9YfLA5hhsJMeBj9W8J7/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/mS9YfLA5hhsJMeBj9W8J7/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"mS9YfLA5hhsJMeBj9W8J7","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -0,0 +1,6 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[236],{8236:function(e,s,t){t.d(s,{L4:function(){return _},Nk:function(){return k}});var n=t(5893),r=t(7294),a=t(1163),l=t(1664),i=t.n(l),c=t(8799),o=t(803),d=t(7673),h=t(8764),u=t(7469),x=t(8969),m=t(3266),j=t(9470),p=t(3626),f=t(998);/**
2
+ * @license lucide-react v0.407.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */let g=(0,f.Z)("RefreshCcw",[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]]),b=(0,f.Z)("FileSearch",[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3",key:"ms7g94"}],["path",{d:"m9 18-1.5-1.5",key:"1j6qii"}],["circle",{cx:"5",cy:"14",r:"3",key:"ufru5t"}]]),N=(0,f.Z)("MonitorPlay",[["path",{d:"M10 7.75a.75.75 0 0 1 1.142-.638l3.664 2.249a.75.75 0 0 1 0 1.278l-3.664 2.25a.75.75 0 0 1-1.142-.64z",key:"1pctta"}],["path",{d:"M12 17v4",key:"1riwvh"}],["path",{d:"M8 21h8",key:"1ev6f3"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",key:"x3v2xh"}]]);var y=t(1266),w=t(4545),v=t(9307);function k(){let[e,s]=(0,r.useState)(!1),t=r.useRef(null),[a,l]=(0,r.useState)({isOpen:!1,title:"",message:"",onConfirm:null});return(0,n.jsxs)(j.A,{highlighted:"jobs",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between mb-4 h-5",children:[(0,n.jsx)("div",{className:"text-base",children:(0,n.jsx)(i(),{href:"/jobs",className:"text-sky-blue hover:underline leading-none",children:"Managed Jobs"})}),(0,n.jsxs)("div",{className:"flex items-center space-x-2",children:[e&&(0,n.jsxs)("div",{className:"flex items-center mr-2",children:[(0,n.jsx)(c.Z,{size:15,className:"mt-0"}),(0,n.jsx)("span",{className:"ml-2 text-gray-500 text-sm",children:"Loading..."})]}),(0,n.jsxs)(o.z,{variant:"ghost",size:"sm",onClick:()=>{t.current&&t.current()},disabled:e,className:"text-sky-blue hover:text-sky-blue-bright",title:"Refresh",children:[(0,n.jsx)(p.Z,{className:"h-4 w-4 mr-1.5"}),(0,n.jsx)("span",{children:"Refresh"})]})]})]}),(0,n.jsx)(C,{refreshInterval:2e4,setLoading:s,refreshDataRef:t}),(0,n.jsx)(y.cV,{isOpen:a.isOpen,onClose:()=>l({...a,isOpen:!1}),onConfirm:a.onConfirm,title:a.title,message:a.message})]})}function C(e){let{refreshInterval:s,setLoading:t,refreshDataRef:a}=e,[l,j]=(0,r.useState)([]),[p,f]=(0,r.useState)({key:null,direction:"ascending"}),[b,N]=(0,r.useState)(!1),[k,C]=(0,r.useState)(!0),[_,R]=(0,r.useState)(1),[M,O]=(0,r.useState)(10),[D,I]=(0,r.useState)(null),z=(0,r.useRef)(null),[J,P]=(0,r.useState)([]),[T,A]=(0,r.useState)({}),[F,U]=(0,r.useState)(!1),[V,q]=(0,r.useState)(!1),[Z,W]=(0,r.useState)(!1),[G,B]=(0,r.useState)("active"),[H,K]=(0,r.useState)(!0),[Y,Q]=(0,r.useState)({isOpen:!1,title:"",message:"",onConfirm:null}),X=async()=>{Q({isOpen:!0,title:"Restart Controller",message:"Are you sure you want to restart the controller? This will temporarily interrupt job management.",onConfirm:async()=>{try{W(!0),N(!0),await (0,x.Ce)("restartcontroller",null,null,!0),await $()}catch(e){console.error("Error restarting controller:",e)}finally{W(!1),N(!1)}}})},$=r.useCallback(async()=>{N(!0),t(!0);try{let[e,s]=await Promise.all([(0,x.Vp)(),(0,m.zd)()]),{jobs:t,controllerStopped:n}=e,r=s.find(e=>(0,w.Ym)(e.cluster)),a=r?r.status:"NOT_FOUND",l=!1;"STOPPED"==a&&n&&(l=!0),"LAUNCHING"==a?q(!0):q(!1),j(t),U(l)}catch(e){console.error("Error fetching data:",e),j([])}finally{N(!1),t(!1),C(!1)}},[t]);r.useEffect(()=>{a&&(a.current=$)},[a,$]),(0,r.useEffect)(()=>{j([]);let e=!0;$();let t=setInterval(()=>{e&&$()},s);return()=>{e=!1,clearInterval(t)}},[s,$]),(0,r.useEffect)(()=>{R(1)},[G,l.length]),(0,r.useEffect)(()=>{P([]),K(!0)},[G]);let ee=e=>{let s="ascending";p.key===e&&"ascending"===p.direction&&(s="descending"),f({key:e,direction:s})},es=e=>p.key===e?"ascending"===p.direction?" ↑":" ↓":"",et=r.useMemo(()=>({active:["PENDING","RUNNING","RECOVERING","SUBMITTED","STARTING","CANCELLING"],finished:["SUCCEEDED","FAILED","CANCELLED","FAILED_SETUP","FAILED_PRECHECKS","FAILED_NO_RESOURCE","FAILED_CONTROLLER"]}),[]);r.useMemo(()=>({active:l.filter(e=>et.active.includes(e.status)).length,finished:l.filter(e=>et.finished.includes(e.status)).length}),[l,et]);let en=e=>J.length>0?J.includes(e):et[G].includes(e),er=r.useMemo(()=>J.length>0?l.filter(e=>J.includes(e.status)):H?l.filter(e=>et[G].includes(e.status)):[],[l,G,J,H,et]),ea=r.useMemo(()=>p.key?[...er].sort((e,s)=>e[p.key]<s[p.key]?"ascending"===p.direction?-1:1:e[p.key]>s[p.key]?"ascending"===p.direction?1:-1:0):er,[er,p]),el=Math.ceil(ea.length/M),ei=(_-1)*M,ec=ei+M,eo=ea.slice(ei,ec),ed=e=>{if(J.includes(e)){let s=J.filter(s=>s!==e);0===s.length?(K(!0),P([])):(P(s),K(!1))}else P([...J,e]),K(!1)};return(0,r.useEffect)(()=>{A(l.reduce((e,s)=>(e[s.status]=(e[s.status]||0)+1,e),{}))},[l]),(0,n.jsxs)("div",{className:"relative",children:[(0,n.jsx)("div",{className:"flex flex-col space-y-1 mb-1",children:(0,n.jsxs)("div",{className:"flex flex-wrap items-center text-sm mb-1",children:[(0,n.jsx)("span",{className:"mr-2 text-sm font-medium",children:"Statuses:"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2 items-center",children:[!b&&0===l.length&&!k&&(0,n.jsx)("span",{className:"text-gray-500 mr-2",children:"No jobs found"}),Object.entries(T).map(e=>{let[s,t]=e;return(0,n.jsxs)("button",{onClick:()=>ed(s),className:"px-3 py-1 rounded-full flex items-center space-x-2 ".concat(en(s)||J.includes(s)?(0,v.Cl)(s):"bg-gray-50 text-gray-600 hover:bg-gray-100"),children:[(0,n.jsx)("span",{children:s}),(0,n.jsx)("span",{className:"text-xs ".concat(en(s)||J.includes(s)?"bg-white/50":"bg-gray-200"," px-1.5 py-0.5 rounded"),children:t})]},s)}),l.length>0&&(0,n.jsxs)("div",{className:"flex items-center ml-2 gap-2",children:[(0,n.jsx)("span",{className:"text-gray-500",children:"("}),(0,n.jsx)("button",{onClick:()=>{B("active"),P([]),K(!0)},className:"text-sm font-medium ".concat("active"===G&&H?"text-green-700 underline":"text-gray-600 hover:text-green-700 hover:underline"),children:"show all active jobs"}),(0,n.jsx)("span",{className:"text-gray-500 mx-1",children:"|"}),(0,n.jsx)("button",{onClick:()=>{B("finished"),P([]),K(!0)},className:"text-sm font-medium ".concat("finished"===G&&H?"text-blue-700 underline":"text-gray-600 hover:text-blue-700 hover:underline"),children:"show all finished jobs"}),(0,n.jsx)("span",{className:"text-gray-500",children:")"})]})]})]})}),(0,n.jsx)(d.Zb,{children:(0,n.jsxs)(h.iA,{children:[(0,n.jsx)(h.xD,{children:(0,n.jsxs)(h.SC,{children:[(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("id"),children:["ID",es("id")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("name"),children:["Name",es("name")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("user"),children:["User",es("user")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("submitted_at"),children:["Submitted",es("submitted_at")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("job_duration"),children:["Duration",es("job_duration")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("status"),children:["Status",es("status")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("resources"),children:["Resources",es("resources")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("cluster"),children:["Cluster",es("cluster")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("region"),children:["Region",es("region")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>ee("recoveries"),children:["Recoveries",es("recoveries")]}),(0,n.jsx)(h.ss,{children:"Details"}),(0,n.jsx)(h.ss,{children:"Logs"})]})}),(0,n.jsx)(h.RM,{children:b&&k?(0,n.jsx)(h.SC,{children:(0,n.jsx)(h.pj,{colSpan:12,className:"text-center py-6 text-gray-500",children:(0,n.jsxs)("div",{className:"flex justify-center items-center",children:[(0,n.jsx)(c.Z,{size:20,className:"mr-2"}),(0,n.jsx)("span",{children:"Loading..."})]})})}):eo.length>0?(0,n.jsx)(n.Fragment,{children:eo.map(e=>(0,n.jsxs)(r.Fragment,{children:[(0,n.jsxs)(h.SC,{children:[(0,n.jsx)(h.pj,{children:(0,n.jsx)(i(),{href:"/jobs/".concat(e.id),className:"text-blue-600",children:e.id})}),(0,n.jsx)(h.pj,{children:(0,n.jsx)(i(),{href:"/jobs/".concat(e.id),className:"text-blue-600",children:e.name})}),(0,n.jsx)(h.pj,{children:e.user}),(0,n.jsx)(h.pj,{children:(0,u.GV)(e.submitted_at)}),(0,n.jsx)(h.pj,{children:(0,u.LU)(e.job_duration)}),(0,n.jsx)(h.pj,{children:(0,n.jsx)(v.OE,{status:e.status})}),(0,n.jsx)(h.pj,{children:e.resources}),(0,n.jsx)(h.pj,{children:e.cluster}),(0,n.jsx)(h.pj,{children:e.region}),(0,n.jsx)(h.pj,{children:e.recoveries}),(0,n.jsx)(h.pj,{children:e.details?(0,n.jsx)(L,{text:e.details,rowId:e.id,expandedRowId:D,setExpandedRowId:I}):"-"}),(0,n.jsx)(h.pj,{children:(0,n.jsx)(S,{jobParent:"/jobs",jobId:e.id,managed:!0})})]}),D===e.id&&(0,n.jsx)(E,{text:e.details,colSpan:12,innerRef:z})]},e.id))}):(0,n.jsx)(h.SC,{children:(0,n.jsx)(h.pj,{colSpan:12,className:"text-center py-6",children:(0,n.jsxs)("div",{className:"flex flex-col items-center space-y-4",children:[V&&(0,n.jsxs)("div",{className:"flex flex-col items-center space-y-2",children:[(0,n.jsx)("p",{className:"text-gray-700",children:"The managed job controller is launching. Please wait for it to be ready."}),(0,n.jsxs)("div",{className:"flex items-center",children:[(0,n.jsx)(c.Z,{size:12,className:"mr-2"}),(0,n.jsx)("span",{className:"text-gray-500",children:"Launching..."})]})]}),!F&&!V&&(0,n.jsx)("p",{className:"text-gray-500",children:"No active jobs"}),F&&(0,n.jsxs)("div",{className:"flex flex-col items-center space-y-2",children:[(0,n.jsx)("p",{className:"text-gray-700",children:"The managed job controller has been stopped. Please restart it to check the latest job status."}),(0,n.jsx)(o.z,{variant:"outline",size:"sm",onClick:X,className:"text-sky-blue hover:text-sky-blue-bright",disabled:b||Z,children:Z?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(c.Z,{size:12,className:"mr-2"}),"Restarting..."]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(g,{className:"h-4 w-4 mr-2"}),"Restart Controller"]})})]})]})})})})]})}),ea.length>0&&(0,n.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,n.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,n.jsxs)("div",{className:"flex items-center",children:[(0,n.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,n.jsxs)("div",{className:"relative inline-block",children:[(0,n.jsxs)("select",{value:M,onChange:e=>{O(parseInt(e.target.value,10)),R(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,n.jsx)("option",{value:10,children:"10"}),(0,n.jsx)("option",{value:30,children:"30"}),(0,n.jsx)("option",{value:50,children:"50"}),(0,n.jsx)("option",{value:100,children:"100"}),(0,n.jsx)("option",{value:200,children:"200"})]}),(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-gray-500 absolute right-0 top-1/2 transform -translate-y-1/2 pointer-events-none",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:(0,n.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,n.jsxs)("div",{children:[ei+1," – ",Math.min(ec,ea.length)," of"," ",ea.length]}),(0,n.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,n.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{R(e=>Math.max(e-1,1))},disabled:1===_,className:"text-gray-500 h-8 w-8 p-0",children:(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-left",children:(0,n.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,n.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{R(e=>Math.min(e+1,el))},disabled:_===el||0===el,className:"text-gray-500 h-8 w-8 p-0",children:(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-right",children:(0,n.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})}),(0,n.jsx)(y.cV,{isOpen:Y.isOpen,onClose:()=>Q({...Y,isOpen:!1}),onConfirm:Y.onConfirm,title:Y.title,message:Y.message})]})}function S(e){let{withLabel:s=!1,jobParent:t,jobId:r,managed:l}=e,i=(0,a.useRouter)(),c=(e,s)=>{e.preventDefault(),e.stopPropagation(),i.push({pathname:"".concat(t,"/").concat(r),query:{tab:s}})};return(0,n.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,n.jsx)(u.WH,{content:"View Job Logs",className:"capitalize text-sm text-muted-foreground",children:(0,n.jsxs)("button",{onClick:e=>c(e,"logs"),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center h-8",children:[(0,n.jsx)(b,{className:"w-4 h-4"}),s&&(0,n.jsx)("span",{className:"ml-1.5",children:"Logs"})]})},"logs"),l&&(0,n.jsx)(u.WH,{content:"View Controller Logs",className:"capitalize text-sm text-muted-foreground",children:(0,n.jsxs)("button",{onClick:e=>c(e,"controllerlogs"),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center h-8",children:[(0,n.jsx)(N,{className:"w-4 h-4"}),s&&(0,n.jsx)("span",{className:"ml-2",children:"Controller Logs"})]})},"controllerlogs")]})}function _(e){let{clusterName:s,clusterJobData:t,loading:a}=e,[l,x]=(0,r.useState)(null),[m,j]=(0,r.useState)({key:null,direction:"ascending"}),[p,f]=(0,r.useState)(1),[g,b]=(0,r.useState)(10),N=(0,r.useRef)(null),[y,w]=(0,r.useState)(null);(0,r.useEffect)(()=>{let e=e=>{l&&N.current&&!N.current.contains(e.target)&&x(null)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[l]);let k=r.useMemo(()=>t||[],[t]);(0,r.useEffect)(()=>{JSON.stringify(t)!==JSON.stringify(y)&&w(t)},[t,y]);let C=r.useMemo(()=>m.key?[...k].sort((e,s)=>e[m.key]<s[m.key]?"ascending"===m.direction?-1:1:e[m.key]>s[m.key]?"ascending"===m.direction?1:-1:0):k,[k,m]),_=e=>{let s="ascending";m.key===e&&"ascending"===m.direction&&(s="descending"),j({key:e,direction:s})},R=e=>m.key===e?"ascending"===m.direction?" ↑":" ↓":"",M=Math.ceil(C.length/g),O=(p-1)*g,D=O+g,I=C.slice(O,D);return(0,n.jsxs)("div",{className:"relative",children:[(0,n.jsxs)(d.Zb,{children:[(0,n.jsxs)("div",{className:"flex items-center justify-between p-4",children:[(0,n.jsx)("h3",{className:"text-lg font-semibold",children:"Cluster Jobs"}),a&&(0,n.jsxs)("div",{className:"flex items-center mr-2",children:[(0,n.jsx)(c.Z,{size:15,className:"mt-0"}),(0,n.jsx)("span",{className:"ml-2 text-gray-500 text-sm",children:"Loading..."})]})]}),(0,n.jsxs)(h.iA,{children:[(0,n.jsx)(h.xD,{children:(0,n.jsxs)(h.SC,{children:[(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("id"),children:["ID",R("id")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("job"),children:["Name",R("job")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("user"),children:["User",R("user")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("submitted_at"),children:["Submitted",R("submitted_at")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("job_duration"),children:["Duration",R("job_duration")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("status"),children:["Status",R("status")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("resources"),children:["Resources",R("resources")]}),(0,n.jsx)(h.ss,{className:"whitespace-nowrap",children:"Logs"})]})}),(0,n.jsx)(h.RM,{children:I.length>0?I.map(e=>(0,n.jsxs)(r.Fragment,{children:[(0,n.jsxs)(h.SC,{className:l===e.id?"selected-row":"",children:[(0,n.jsx)(h.pj,{children:(0,n.jsx)(i(),{href:"/clusters/".concat(s,"/").concat(e.id),className:"text-blue-600",children:e.id})}),(0,n.jsx)(h.pj,{children:(0,n.jsx)(i(),{href:"/clusters/".concat(s,"/").concat(e.id),className:"text-blue-600",children:(0,n.jsx)(L,{text:e.job||"Unnamed job",rowId:e.id,expandedRowId:l,setExpandedRowId:x})})}),(0,n.jsx)(h.pj,{children:e.user}),(0,n.jsx)(h.pj,{children:(0,u.GV)(e.submitted_at)}),(0,n.jsx)(h.pj,{children:(0,u.LU)(e.job_duration)}),(0,n.jsx)(h.pj,{children:(0,n.jsx)(v.OE,{status:e.status})}),(0,n.jsx)(h.pj,{children:e.resources}),(0,n.jsx)(h.pj,{className:"flex content-center items-center",children:(0,n.jsx)(S,{jobParent:"/clusters/".concat(s),jobId:e.id,managed:!1})})]}),l===e.id&&(0,n.jsx)(E,{text:e.job||"Unnamed job",colSpan:8,innerRef:N})]},e.id)):(0,n.jsx)(h.SC,{children:(0,n.jsx)(h.pj,{colSpan:8,className:"text-center py-6 text-gray-500",children:"No jobs found"})})})]})]}),C.length>0&&(0,n.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,n.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,n.jsxs)("div",{className:"flex items-center",children:[(0,n.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,n.jsxs)("div",{className:"relative inline-block",children:[(0,n.jsxs)("select",{value:g,onChange:e=>{b(parseInt(e.target.value,10)),f(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,n.jsx)("option",{value:5,children:"5"}),(0,n.jsx)("option",{value:10,children:"10"}),(0,n.jsx)("option",{value:20,children:"20"}),(0,n.jsx)("option",{value:50,children:"50"})]}),(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-gray-500 absolute right-0 top-1/2 transform -translate-y-1/2 pointer-events-none",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:(0,n.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,n.jsxs)("div",{children:[O+1," – ",Math.min(D,C.length)," of"," ",C.length]}),(0,n.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,n.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{f(e=>Math.max(e-1,1))},disabled:1===p,className:"text-gray-500 h-8 w-8 p-0",children:(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-left",children:(0,n.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,n.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{f(e=>Math.min(e+1,M))},disabled:p===M||0===M,className:"text-gray-500 h-8 w-8 p-0",children:(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-right",children:(0,n.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})})]})}function E(e){let{text:s,colSpan:t,innerRef:r}=e;return(0,n.jsx)(h.SC,{className:"expanded-details",children:(0,n.jsx)(h.pj,{colSpan:t,children:(0,n.jsx)("div",{className:"p-4 bg-gray-50 rounded-md border border-gray-200",ref:r,children:(0,n.jsx)("div",{className:"flex justify-between items-start",children:(0,n.jsxs)("div",{className:"flex-1",children:[(0,n.jsx)("p",{className:"text-sm font-medium text-gray-900",children:"Full Details"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-gray-700",style:{whiteSpace:"pre-wrap"},children:s})]})})})})})}function L(e){let{text:s,rowId:t,expandedRowId:a,setExpandedRowId:l}=e,i=s.length>50,c=a===t,o=i?"".concat(s.substring(0,50)):s,d=(0,r.useRef)(null);return(0,n.jsxs)("div",{className:"truncated-details relative max-w-full flex items-center",children:[(0,n.jsx)("span",{className:"truncate",children:o}),i&&(0,n.jsx)("button",{ref:d,type:"button",onClick:e=>{e.preventDefault(),e.stopPropagation(),l(c?null:t)},className:"text-blue-600 hover:text-blue-800 font-medium ml-1 flex-shrink-0","data-button-type":"show-more-less",children:c?"... show less":"... show more"})]})}},8969:function(e,s,t){t.d(s,{Ce:function(){return o},NJ:function(){return c},Pr:function(){return i},Vp:function(){return l}});var n=t(7294),r=t(5821),a=t(3225);async function l(){let{allUsers:e=!0}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{let s=(await fetch("".concat(a.f4,"/jobs/queue"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({all_users:e})})).headers.get("x-request-id"),t=await fetch("".concat(a.f4,"/api/get?request_id=").concat(s));if(500===t.status){try{let e=await t.json();if(e.detail&&e.detail.error)try{let s=JSON.parse(e.detail.error);if(s.type&&s.type===a.IV)return{jobs:[],controllerStopped:!0}}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{jobs:[],controllerStopped:!1}}let n=await t.json();return{jobs:(n.return_value?JSON.parse(n.return_value):[]).map(e=>{let s=[];e.submitted_at&&s.push({time:new Date(1e3*e.submitted_at),event:"Job submitted."}),e.start_at&&s.push({time:new Date(1e3*e.start_at),event:"Job started."}),e.end_at&&("CANCELLING"==e.status||"CANCELLED"==e.status?s.push({time:new Date(1e3*e.end_at),event:"Job cancelled."}):s.push({time:new Date(1e3*e.end_at),event:"Job completed."})),e.last_recovered_at&&e.last_recovered_at!=e.start_at&&s.push({time:new Date(1e3*e.last_recovered_at),event:"Job recovered."});let t=(e.end_at?e.end_at:Date.now()/1e3)-e.submitted_at;return{id:e.job_id,task:e.task_name,name:e.job_name,job_duration:e.job_duration,total_duration:t,status:e.status,resources:e.resources,cluster:e.cluster_resources,region:e.region,recoveries:e.recovery_count,details:e.failure_reason,user:e.user_name,submitted_at:e.submitted_at?new Date(1e3*e.submitted_at):null,events:s}}),controllerStopped:!1}}catch(e){return console.error("Error fetching managed job data:",e),{jobs:[],controllerStopped:!1}}}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,[s,t]=(0,n.useState)(null),[r,a]=(0,n.useState)(!0);return(0,n.useEffect)(()=>{(async function(){try{a(!0);let e=await l({allUsers:!0});t(e)}catch(e){console.error("Error fetching managed job data:",e)}finally{a(!1)}})()},[e]),{jobData:s,loading:r}}async function c(e){let{jobId:s,controller:t=!1,signal:n,onNewLog:l}=e,i=new Promise(e=>{setTimeout(()=>{e({timeout:!0})},1e4)}),c=(async()=>{try{let e=(await fetch("".concat(a.f4,"/jobs/logs"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({controller:t,follow:!1,job_id:s}),...n?{signal:n}:{}})).body.getReader();try{for(;;){let{done:s,value:t}=await e.read();if(s)break;let n=new TextDecoder().decode(t);l(n)}}finally{e.cancel()}return{timeout:!1}}catch(e){if("AbortError"===e.name)return{timeout:!1};throw e}})();if((await Promise.race([c,i])).timeout){(0,r.C)("Log request for job ".concat(s," timed out after ").concat(1e4,"ms"),"error");return}}async function o(e,s,t){let n="",l="",i="",c={};if("restartcontroller"===e)n="Restarting",l="restarted",i="jobs/queue",c={all_users:!0,refresh:!0},s="controller";else throw Error("Invalid action: ".concat(e));(0,r.C)("".concat(n," job ").concat(s,"..."),"info");try{try{let e=(await fetch("".concat(a.f4,"/").concat(i),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)})).headers.get("x-request-id"),o=await fetch("".concat(a.f4,"/api/get?request_id=").concat(e));if(200===o.status)(0,r.C)("Job ".concat(s," ").concat(l," successfully."),"success");else if(500===o.status)try{let e=await o.json();if(e.detail&&e.detail.error)try{let l=JSON.parse(e.detail.error);l.type&&l.type===a.B8?(0,r.C)("".concat(n," job ").concat(s," is not supported!"),"error",1e4):l.type&&l.type===a.h1?(0,r.C)("Cluster ".concat(t," does not exist."),"error"):l.type&&l.type===a.IV?(0,r.C)("Cluster ".concat(t," is not up."),"error"):(0,r.C)("".concat(n," job ").concat(s," failed: ").concat(l.type),"error")}catch(t){(0,r.C)("".concat(n," job ").concat(s," failed: ").concat(e.detail.error),"error")}else(0,r.C)("".concat(n," job ").concat(s," failed with no details."),"error")}catch(e){(0,r.C)("".concat(n," job ").concat(s," failed with parse error."),"error")}else(0,r.C)("".concat(n," job ").concat(s," failed with status ").concat(o.status,"."),"error")}catch(e){console.error("Fetch error:",e),(0,r.C)("Network error ".concat(n," job ").concat(s,": ").concat(e.message),"error")}}catch(e){console.error("Error in handleStop:",e),(0,r.C)("Critical error ".concat(n," job ").concat(s,": ").concat(e.message),"error")}}}}]);
@@ -0,0 +1,15 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[312],{8671:function(e,t,n){n.d(t,{Z:function(){return r}});/**
2
+ * @license lucide-react v0.407.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */let r=(0,n(998).Z)("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]])},3767:function(e,t,n){n.d(t,{Z:function(){return r}});/**
7
+ * @license lucide-react v0.407.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */let r=(0,n(998).Z)("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]])},5235:function(e,t,n){let r;n.d(t,{x8:function(){return eJ},VY:function(){return eH},dk:function(){return eG},aV:function(){return eY},h_:function(){return eX},fC:function(){return eZ},Dx:function(){return eq},xz:function(){return ez}});var o,i=n(7294);function u(e,t,{checkForDefaultPrevented:n=!0}={}){return function(r){if(e?.(r),!1===n||!r.defaultPrevented)return t?.(r)}}function a(e,t){if("function"==typeof e)return e(t);null!=e&&(e.current=t)}function l(...e){return t=>{let n=!1,r=e.map(e=>{let r=a(e,t);return n||"function"!=typeof r||(n=!0),r});if(n)return()=>{for(let t=0;t<r.length;t++){let n=r[t];"function"==typeof n?n():a(e[t],null)}}}}function s(...e){return i.useCallback(l(...e),e)}var c=n(5893),d=n(1276),f=n(7342),p=n(3935),m=i.forwardRef((e,t)=>{let{children:n,...r}=e,o=i.Children.toArray(n),u=o.find(y);if(u){let e=u.props.children,n=o.map(t=>t!==u?t:i.Children.count(e)>1?i.Children.only(null):i.isValidElement(e)?e.props.children:null);return(0,c.jsx)(v,{...r,ref:t,children:i.isValidElement(e)?i.cloneElement(e,void 0,n):null})}return(0,c.jsx)(v,{...r,ref:t,children:n})});m.displayName="Slot";var v=i.forwardRef((e,t)=>{let{children:n,...r}=e;if(i.isValidElement(n)){let e,o;let u=(e=Object.getOwnPropertyDescriptor(n.props,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning?n.ref:(e=Object.getOwnPropertyDescriptor(n,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning?n.props.ref:n.props.ref||n.ref,a=function(e,t){let n={...t};for(let r in t){let o=e[r],i=t[r];/^on[A-Z]/.test(r)?o&&i?n[r]=(...e)=>{i(...e),o(...e)}:o&&(n[r]=o):"style"===r?n[r]={...o,...i}:"className"===r&&(n[r]=[o,i].filter(Boolean).join(" "))}return{...e,...n}}(r,n.props);return n.type!==i.Fragment&&(a.ref=t?l(t,u):u),i.cloneElement(n,a)}return i.Children.count(n)>1?i.Children.only(null):null});v.displayName="SlotClone";var h=({children:e})=>(0,c.jsx)(c.Fragment,{children:e});function y(e){return i.isValidElement(e)&&e.type===h}var g=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","span","svg","ul"].reduce((e,t)=>{let n=i.forwardRef((e,n)=>{let{asChild:r,...o}=e,i=r?m:t;return"undefined"!=typeof window&&(window[Symbol.for("radix-ui")]=!0),(0,c.jsx)(i,{...o,ref:n})});return n.displayName=`Primitive.${t}`,{...e,[t]:n}},{}),E=n(9698),b=n(8724),w="dismissableLayer.update",C=i.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),N=i.forwardRef((e,t)=>{let{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:a,onFocusOutside:l,onInteractOutside:d,onDismiss:f,...p}=e,m=i.useContext(C),[v,h]=i.useState(null),y=v?.ownerDocument??globalThis?.document,[,N]=i.useState({}),D=s(t,e=>h(e)),O=Array.from(m.layers),[P]=[...m.layersWithOutsidePointerEventsDisabled].slice(-1),T=O.indexOf(P),j=v?O.indexOf(v):-1,L=m.layersWithOutsidePointerEventsDisabled.size>0,S=j>=T,M=function(e,t=globalThis?.document){let n=(0,E.W)(e),r=i.useRef(!1),o=i.useRef(()=>{});return i.useEffect(()=>{let e=e=>{if(e.target&&!r.current){let r=function(){x("dismissableLayer.pointerDownOutside",n,i,{discrete:!0})},i={originalEvent:e};"touch"===e.pointerType?(t.removeEventListener("click",o.current),o.current=r,t.addEventListener("click",o.current,{once:!0})):r()}else t.removeEventListener("click",o.current);r.current=!1},i=window.setTimeout(()=>{t.addEventListener("pointerdown",e)},0);return()=>{window.clearTimeout(i),t.removeEventListener("pointerdown",e),t.removeEventListener("click",o.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}(e=>{let t=e.target,n=[...m.branches].some(e=>e.contains(t));!S||n||(a?.(e),d?.(e),e.defaultPrevented||f?.())},y),k=function(e,t=globalThis?.document){let n=(0,E.W)(e),r=i.useRef(!1);return i.useEffect(()=>{let e=e=>{e.target&&!r.current&&x("dismissableLayer.focusOutside",n,{originalEvent:e},{discrete:!1})};return t.addEventListener("focusin",e),()=>t.removeEventListener("focusin",e)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}(e=>{let t=e.target;[...m.branches].some(e=>e.contains(t))||(l?.(e),d?.(e),e.defaultPrevented||f?.())},y);return(0,b.e)(e=>{j!==m.layers.size-1||(r?.(e),!e.defaultPrevented&&f&&(e.preventDefault(),f()))},y),i.useEffect(()=>{if(v)return n&&(0===m.layersWithOutsidePointerEventsDisabled.size&&(o=y.body.style.pointerEvents,y.body.style.pointerEvents="none"),m.layersWithOutsidePointerEventsDisabled.add(v)),m.layers.add(v),R(),()=>{n&&1===m.layersWithOutsidePointerEventsDisabled.size&&(y.body.style.pointerEvents=o)}},[v,y,n,m]),i.useEffect(()=>()=>{v&&(m.layers.delete(v),m.layersWithOutsidePointerEventsDisabled.delete(v),R())},[v,m]),i.useEffect(()=>{let e=()=>N({});return document.addEventListener(w,e),()=>document.removeEventListener(w,e)},[]),(0,c.jsx)(g.div,{...p,ref:D,style:{pointerEvents:L?S?"auto":"none":void 0,...e.style},onFocusCapture:u(e.onFocusCapture,k.onFocusCapture),onBlurCapture:u(e.onBlurCapture,k.onBlurCapture),onPointerDownCapture:u(e.onPointerDownCapture,M.onPointerDownCapture)})});function R(){let e=new CustomEvent(w);document.dispatchEvent(e)}function x(e,t,n,{discrete:r}){let o=n.originalEvent.target,i=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});(t&&o.addEventListener(e,t,{once:!0}),r)?o&&p.flushSync(()=>o.dispatchEvent(i)):o.dispatchEvent(i)}N.displayName="DismissableLayer",i.forwardRef((e,t)=>{let n=i.useContext(C),r=i.useRef(null),o=s(t,r);return i.useEffect(()=>{let e=r.current;if(e)return n.branches.add(e),()=>{n.branches.delete(e)}},[n.branches]),(0,c.jsx)(g.div,{...e,ref:o})}).displayName="DismissableLayerBranch";var D="focusScope.autoFocusOnMount",O="focusScope.autoFocusOnUnmount",P={bubbles:!1,cancelable:!0},T=i.forwardRef((e,t)=>{let{loop:n=!1,trapped:r=!1,onMountAutoFocus:o,onUnmountAutoFocus:u,...a}=e,[l,d]=i.useState(null),f=(0,E.W)(o),p=(0,E.W)(u),m=i.useRef(null),v=s(t,e=>d(e)),h=i.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;i.useEffect(()=>{if(r){let e=function(e){if(h.paused||!l)return;let t=e.target;l.contains(t)?m.current=t:S(m.current,{select:!0})},t=function(e){if(h.paused||!l)return;let t=e.relatedTarget;null===t||l.contains(t)||S(m.current,{select:!0})};document.addEventListener("focusin",e),document.addEventListener("focusout",t);let n=new MutationObserver(function(e){if(document.activeElement===document.body)for(let t of e)t.removedNodes.length>0&&S(l)});return l&&n.observe(l,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",e),document.removeEventListener("focusout",t),n.disconnect()}}},[r,l,h.paused]),i.useEffect(()=>{if(l){M.add(h);let e=document.activeElement;if(!l.contains(e)){let t=new CustomEvent(D,P);l.addEventListener(D,f),l.dispatchEvent(t),t.defaultPrevented||(function(e,{select:t=!1}={}){let n=document.activeElement;for(let r of e)if(S(r,{select:t}),document.activeElement!==n)return}(j(l).filter(e=>"A"!==e.tagName),{select:!0}),document.activeElement===e&&S(l))}return()=>{l.removeEventListener(D,f),setTimeout(()=>{let t=new CustomEvent(O,P);l.addEventListener(O,p),l.dispatchEvent(t),t.defaultPrevented||S(e??document.body,{select:!0}),l.removeEventListener(O,p),M.remove(h)},0)}}},[l,f,p,h]);let y=i.useCallback(e=>{if(!n&&!r||h.paused)return;let t="Tab"===e.key&&!e.altKey&&!e.ctrlKey&&!e.metaKey,o=document.activeElement;if(t&&o){let t=e.currentTarget,[r,i]=function(e){let t=j(e);return[L(t,e),L(t.reverse(),e)]}(t);r&&i?e.shiftKey||o!==i?e.shiftKey&&o===r&&(e.preventDefault(),n&&S(i,{select:!0})):(e.preventDefault(),n&&S(r,{select:!0})):o===t&&e.preventDefault()}},[n,r,h.paused]);return(0,c.jsx)(g.div,{tabIndex:-1,...a,ref:v,onKeyDown:y})});function j(e){let t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:e=>{let t="INPUT"===e.tagName&&"hidden"===e.type;return e.disabled||e.hidden||t?NodeFilter.FILTER_SKIP:e.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t}function L(e,t){for(let n of e)if(!function(e,{upTo:t}){if("hidden"===getComputedStyle(e).visibility)return!0;for(;e&&(void 0===t||e!==t);){if("none"===getComputedStyle(e).display)return!0;e=e.parentElement}return!1}(n,{upTo:t}))return n}function S(e,{select:t=!1}={}){if(e&&e.focus){var n;let r=document.activeElement;e.focus({preventScroll:!0}),e!==r&&(n=e)instanceof HTMLInputElement&&"select"in n&&t&&e.select()}}T.displayName="FocusScope";var M=(r=[],{add(e){let t=r[0];e!==t&&t?.pause(),(r=k(r,e)).unshift(e)},remove(e){r=k(r,e),r[0]?.resume()}});function k(e,t){let n=[...e],r=n.indexOf(t);return -1!==r&&n.splice(r,1),n}var I=n(9981),F=i.forwardRef((e,t)=>{let{container:n,...r}=e,[o,u]=i.useState(!1);(0,I.b)(()=>u(!0),[]);let a=n||o&&globalThis?.document?.body;return a?p.createPortal((0,c.jsx)(g.div,{...r,ref:t}),a):null});function A(e,t){if("function"==typeof e)return e(t);null!=e&&(e.current=t)}F.displayName="Portal";var _=e=>{let t,n;let{present:r,children:o}=e,u=function(e){var t,n;let[r,o]=i.useState(),u=i.useRef({}),a=i.useRef(e),l=i.useRef("none"),[s,c]=(t=e?"mounted":"unmounted",n={mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}},i.useReducer((e,t)=>n[e][t]??e,t));return i.useEffect(()=>{let e=W(u.current);l.current="mounted"===s?e:"none"},[s]),(0,I.b)(()=>{let t=u.current,n=a.current;if(n!==e){let r=l.current,o=W(t);e?c("MOUNT"):"none"===o||t?.display==="none"?c("UNMOUNT"):n&&r!==o?c("ANIMATION_OUT"):c("UNMOUNT"),a.current=e}},[e,c]),(0,I.b)(()=>{if(r){let e;let t=r.ownerDocument.defaultView??window,n=n=>{let o=W(u.current).includes(n.animationName);if(n.target===r&&o&&(c("ANIMATION_END"),!a.current)){let n=r.style.animationFillMode;r.style.animationFillMode="forwards",e=t.setTimeout(()=>{"forwards"===r.style.animationFillMode&&(r.style.animationFillMode=n)})}},o=e=>{e.target===r&&(l.current=W(u.current))};return r.addEventListener("animationstart",o),r.addEventListener("animationcancel",n),r.addEventListener("animationend",n),()=>{t.clearTimeout(e),r.removeEventListener("animationstart",o),r.removeEventListener("animationcancel",n),r.removeEventListener("animationend",n)}}c("ANIMATION_END")},[r,c]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:i.useCallback(e=>{e&&(u.current=getComputedStyle(e)),o(e)},[])}}(r),a="function"==typeof o?o({present:u.isPresent}):i.Children.only(o),l=function(...e){return i.useCallback(function(...e){return t=>{let n=!1,r=e.map(e=>{let r=A(e,t);return n||"function"!=typeof r||(n=!0),r});if(n)return()=>{for(let t=0;t<r.length;t++){let n=r[t];"function"==typeof n?n():A(e[t],null)}}}}(...e),e)}(u.ref,(t=Object.getOwnPropertyDescriptor(a.props,"ref")?.get)&&"isReactWarning"in t&&t.isReactWarning?a.ref:(t=Object.getOwnPropertyDescriptor(a,"ref")?.get)&&"isReactWarning"in t&&t.isReactWarning?a.props.ref:a.props.ref||a.ref);return"function"==typeof o||u.isPresent?i.cloneElement(a,{ref:l}):null};function W(e){return e?.animationName||"none"}_.displayName="Presence";var B=0;function U(){let e=document.createElement("span");return e.setAttribute("data-radix-focus-guard",""),e.tabIndex=0,e.style.outline="none",e.style.opacity="0",e.style.position="fixed",e.style.pointerEvents="none",e}var $=n(7582),K=n(1642),V=n(9495),Z=(0,n(7122)._)(),z=function(){},X=i.forwardRef(function(e,t){var n=i.useRef(null),r=i.useState({onScrollCapture:z,onWheelCapture:z,onTouchMoveCapture:z}),o=r[0],u=r[1],a=e.forwardProps,l=e.children,s=e.className,c=e.removeScrollBar,d=e.enabled,f=e.shards,p=e.sideCar,m=e.noIsolation,v=e.inert,h=e.allowPinchZoom,y=e.as,g=e.gapMode,E=(0,$._T)(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noIsolation","inert","allowPinchZoom","as","gapMode"]),b=(0,V.q)([n,t]),w=(0,$.pi)((0,$.pi)({},E),o);return i.createElement(i.Fragment,null,d&&i.createElement(p,{sideCar:Z,removeScrollBar:c,shards:f,noIsolation:m,inert:v,setCallbacks:u,allowPinchZoom:!!h,lockRef:n,gapMode:g}),a?i.cloneElement(i.Children.only(l),(0,$.pi)((0,$.pi)({},w),{ref:b})):i.createElement(void 0===y?"div":y,(0,$.pi)({},w,{className:s,ref:b}),l))});X.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1},X.classNames={fullWidth:K.zi,zeroRight:K.pF};var Y=n(6781),H=n(7087),q=n(6525),G=!1;if("undefined"!=typeof window)try{var J=Object.defineProperty({},"passive",{get:function(){return G=!0,!0}});window.addEventListener("test",J,J),window.removeEventListener("test",J,J)}catch(e){G=!1}var Q=!!G&&{passive:!1},ee=function(e,t){if(!(e instanceof Element))return!1;var n=window.getComputedStyle(e);return"hidden"!==n[t]&&!(n.overflowY===n.overflowX&&"TEXTAREA"!==e.tagName&&"visible"===n[t])},et=function(e,t){var n=t.ownerDocument,r=t;do{if("undefined"!=typeof ShadowRoot&&r instanceof ShadowRoot&&(r=r.host),en(e,r)){var o=er(e,r);if(o[1]>o[2])return!0}r=r.parentNode}while(r&&r!==n.body);return!1},en=function(e,t){return"v"===e?ee(t,"overflowY"):ee(t,"overflowX")},er=function(e,t){return"v"===e?[t.scrollTop,t.scrollHeight,t.clientHeight]:[t.scrollLeft,t.scrollWidth,t.clientWidth]},eo=function(e,t,n,r,o){var i,u=(i=window.getComputedStyle(t).direction,"h"===e&&"rtl"===i?-1:1),a=u*r,l=n.target,s=t.contains(l),c=!1,d=a>0,f=0,p=0;do{var m=er(e,l),v=m[0],h=m[1]-m[2]-u*v;(v||h)&&en(e,l)&&(f+=h,p+=v),l instanceof ShadowRoot?l=l.host:l=l.parentNode}while(!s&&l!==document.body||s&&(t.contains(l)||t===l));return d&&(o&&1>Math.abs(f)||!o&&a>f)?c=!0:!d&&(o&&1>Math.abs(p)||!o&&-a>p)&&(c=!0),c},ei=function(e){return"changedTouches"in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]},eu=function(e){return[e.deltaX,e.deltaY]},ea=function(e){return e&&"current"in e?e.current:e},el=0,es=[],ec=(0,Y.L)(Z,function(e){var t=i.useRef([]),n=i.useRef([0,0]),r=i.useRef(),o=i.useState(el++)[0],u=i.useState(q.Ws)[0],a=i.useRef(e);i.useEffect(function(){a.current=e},[e]),i.useEffect(function(){if(e.inert){document.body.classList.add("block-interactivity-".concat(o));var t=(0,$.ev)([e.lockRef.current],(e.shards||[]).map(ea),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add("allow-interactivity-".concat(o))}),function(){document.body.classList.remove("block-interactivity-".concat(o)),t.forEach(function(e){return e.classList.remove("allow-interactivity-".concat(o))})}}},[e.inert,e.lockRef.current,e.shards]);var l=i.useCallback(function(e,t){if("touches"in e&&2===e.touches.length||"wheel"===e.type&&e.ctrlKey)return!a.current.allowPinchZoom;var o,i=ei(e),u=n.current,l="deltaX"in e?e.deltaX:u[0]-i[0],s="deltaY"in e?e.deltaY:u[1]-i[1],c=e.target,d=Math.abs(l)>Math.abs(s)?"h":"v";if("touches"in e&&"h"===d&&"range"===c.type)return!1;var f=et(d,c);if(!f)return!0;if(f?o=d:(o="v"===d?"h":"v",f=et(d,c)),!f)return!1;if(!r.current&&"changedTouches"in e&&(l||s)&&(r.current=o),!o)return!0;var p=r.current||o;return eo(p,t,e,"h"===p?l:s,!0)},[]),s=i.useCallback(function(e){if(es.length&&es[es.length-1]===u){var n="deltaY"in e?eu(e):ei(e),r=t.current.filter(function(t){var r;return t.name===e.type&&(t.target===e.target||e.target===t.shadowParent)&&(r=t.delta)[0]===n[0]&&r[1]===n[1]})[0];if(r&&r.should){e.cancelable&&e.preventDefault();return}if(!r){var o=(a.current.shards||[]).map(ea).filter(Boolean).filter(function(t){return t.contains(e.target)});(o.length>0?l(e,o[0]):!a.current.noIsolation)&&e.cancelable&&e.preventDefault()}}},[]),c=i.useCallback(function(e,n,r,o){var i={name:e,delta:n,target:r,should:o,shadowParent:function(e){for(var t=null;null!==e;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}(r)};t.current.push(i),setTimeout(function(){t.current=t.current.filter(function(e){return e!==i})},1)},[]),d=i.useCallback(function(e){n.current=ei(e),r.current=void 0},[]),f=i.useCallback(function(t){c(t.type,eu(t),t.target,l(t,e.lockRef.current))},[]),p=i.useCallback(function(t){c(t.type,ei(t),t.target,l(t,e.lockRef.current))},[]);i.useEffect(function(){return es.push(u),e.setCallbacks({onScrollCapture:f,onWheelCapture:f,onTouchMoveCapture:p}),document.addEventListener("wheel",s,Q),document.addEventListener("touchmove",s,Q),document.addEventListener("touchstart",d,Q),function(){es=es.filter(function(e){return e!==u}),document.removeEventListener("wheel",s,Q),document.removeEventListener("touchmove",s,Q),document.removeEventListener("touchstart",d,Q)}},[]);var m=e.removeScrollBar,v=e.inert;return i.createElement(i.Fragment,null,v?i.createElement(u,{styles:"\n .block-interactivity-".concat(o," {pointer-events: none;}\n .allow-interactivity-").concat(o," {pointer-events: all;}\n")}):null,m?i.createElement(H.jp,{gapMode:e.gapMode}):null)}),ed=i.forwardRef(function(e,t){return i.createElement(X,(0,$.pi)({},e,{ref:t,sideCar:ec}))});ed.classNames=X.classNames;var ef=n(3541),ep="Dialog",[em,ev]=function(e,t=[]){let n=[],r=()=>{let t=n.map(e=>i.createContext(e));return function(n){let r=n?.[e]||t;return i.useMemo(()=>({[`__scope${e}`]:{...n,[e]:r}}),[n,r])}};return r.scopeName=e,[function(t,r){let o=i.createContext(r),u=n.length;n=[...n,r];let a=t=>{let{scope:n,children:r,...a}=t,l=n?.[e]?.[u]||o,s=i.useMemo(()=>a,Object.values(a));return(0,c.jsx)(l.Provider,{value:s,children:r})};return a.displayName=t+"Provider",[a,function(n,a){let l=a?.[e]?.[u]||o,s=i.useContext(l);if(s)return s;if(void 0!==r)return r;throw Error(`\`${n}\` must be used within \`${t}\``)}]},function(...e){let t=e[0];if(1===e.length)return t;let n=()=>{let n=e.map(e=>({useScope:e(),scopeName:e.scopeName}));return function(e){let r=n.reduce((t,{useScope:n,scopeName:r})=>{let o=n(e)[`__scope${r}`];return{...t,...o}},{});return i.useMemo(()=>({[`__scope${t.scopeName}`]:r}),[r])}};return n.scopeName=t.scopeName,n}(r,...t)]}(ep),[eh,ey]=em(ep),eg=e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:o,onOpenChange:u,modal:a=!0}=e,l=i.useRef(null),s=i.useRef(null),[p=!1,m]=(0,f.T)({prop:r,defaultProp:o,onChange:u});return(0,c.jsx)(eh,{scope:t,triggerRef:l,contentRef:s,contentId:(0,d.M)(),titleId:(0,d.M)(),descriptionId:(0,d.M)(),open:p,onOpenChange:m,onOpenToggle:i.useCallback(()=>m(e=>!e),[m]),modal:a,children:n})};eg.displayName=ep;var eE="DialogTrigger",eb=i.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=ey(eE,n),i=s(t,o.triggerRef);return(0,c.jsx)(g.button,{type:"button","aria-haspopup":"dialog","aria-expanded":o.open,"aria-controls":o.contentId,"data-state":eW(o.open),...r,ref:i,onClick:u(e.onClick,o.onOpenToggle)})});eb.displayName=eE;var ew="DialogPortal",[eC,eN]=em(ew,{forceMount:void 0}),eR=e=>{let{__scopeDialog:t,forceMount:n,children:r,container:o}=e,u=ey(ew,t);return(0,c.jsx)(eC,{scope:t,forceMount:n,children:i.Children.map(r,e=>(0,c.jsx)(_,{present:n||u.open,children:(0,c.jsx)(F,{asChild:!0,container:o,children:e})}))})};eR.displayName=ew;var ex="DialogOverlay",eD=i.forwardRef((e,t)=>{let n=eN(ex,e.__scopeDialog),{forceMount:r=n.forceMount,...o}=e,i=ey(ex,e.__scopeDialog);return i.modal?(0,c.jsx)(_,{present:r||i.open,children:(0,c.jsx)(eO,{...o,ref:t})}):null});eD.displayName=ex;var eO=i.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=ey(ex,n);return(0,c.jsx)(ed,{as:m,allowPinchZoom:!0,shards:[o.contentRef],children:(0,c.jsx)(g.div,{"data-state":eW(o.open),...r,ref:t,style:{pointerEvents:"auto",...r.style}})})}),eP="DialogContent",eT=i.forwardRef((e,t)=>{let n=eN(eP,e.__scopeDialog),{forceMount:r=n.forceMount,...o}=e,i=ey(eP,e.__scopeDialog);return(0,c.jsx)(_,{present:r||i.open,children:i.modal?(0,c.jsx)(ej,{...o,ref:t}):(0,c.jsx)(eL,{...o,ref:t})})});eT.displayName=eP;var ej=i.forwardRef((e,t)=>{let n=ey(eP,e.__scopeDialog),r=i.useRef(null),o=s(t,n.contentRef,r);return i.useEffect(()=>{let e=r.current;if(e)return(0,ef.Ry)(e)},[]),(0,c.jsx)(eS,{...e,ref:o,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:u(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:u(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=0===t.button&&!0===t.ctrlKey;(2===t.button||n)&&e.preventDefault()}),onFocusOutside:u(e.onFocusOutside,e=>e.preventDefault())})}),eL=i.forwardRef((e,t)=>{let n=ey(eP,e.__scopeDialog),r=i.useRef(!1),o=i.useRef(!1);return(0,c.jsx)(eS,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,o.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,"pointerdown"!==t.detail.originalEvent.type||(o.current=!0));let i=t.target;n.triggerRef.current?.contains(i)&&t.preventDefault(),"focusin"===t.detail.originalEvent.type&&o.current&&t.preventDefault()}})}),eS=i.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:o,onCloseAutoFocus:u,...a}=e,l=ey(eP,n),d=i.useRef(null),f=s(t,d);return i.useEffect(()=>{let e=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",e[0]??U()),document.body.insertAdjacentElement("beforeend",e[1]??U()),B++,()=>{1===B&&document.querySelectorAll("[data-radix-focus-guard]").forEach(e=>e.remove()),B--}},[]),(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(T,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:o,onUnmountAutoFocus:u,children:(0,c.jsx)(N,{role:"dialog",id:l.contentId,"aria-describedby":l.descriptionId,"aria-labelledby":l.titleId,"data-state":eW(l.open),...a,ref:f,onDismiss:()=>l.onOpenChange(!1)})}),(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(eK,{titleId:l.titleId}),(0,c.jsx)(eV,{contentRef:d,descriptionId:l.descriptionId})]})]})}),eM="DialogTitle",ek=i.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=ey(eM,n);return(0,c.jsx)(g.h2,{id:o.titleId,...r,ref:t})});ek.displayName=eM;var eI="DialogDescription",eF=i.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=ey(eI,n);return(0,c.jsx)(g.p,{id:o.descriptionId,...r,ref:t})});eF.displayName=eI;var eA="DialogClose",e_=i.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=ey(eA,n);return(0,c.jsx)(g.button,{type:"button",...r,ref:t,onClick:u(e.onClick,()=>o.onOpenChange(!1))})});function eW(e){return e?"open":"closed"}e_.displayName=eA;var eB="DialogTitleWarning",[eU,e$]=function(e,t){let n=i.createContext(t),r=e=>{let{children:t,...r}=e,o=i.useMemo(()=>r,Object.values(r));return(0,c.jsx)(n.Provider,{value:o,children:t})};return r.displayName=e+"Provider",[r,function(r){let o=i.useContext(n);if(o)return o;if(void 0!==t)return t;throw Error(`\`${r}\` must be used within \`${e}\``)}]}(eB,{contentName:eP,titleName:eM,docsSlug:"dialog"}),eK=({titleId:e})=>{let t=e$(eB),n=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
12
+
13
+ If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
14
+
15
+ For more information, see https://radix-ui.com/primitives/docs/components/${t.docsSlug}`;return i.useEffect(()=>{e&&!document.getElementById(e)&&console.error(n)},[n,e]),null},eV=({contentRef:e,descriptionId:t})=>{let n=e$("DialogDescriptionWarning"),r=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${n.contentName}}.`;return i.useEffect(()=>{let n=e.current?.getAttribute("aria-describedby");t&&n&&!document.getElementById(t)&&console.warn(r)},[r,e,t]),null},eZ=eg,ez=eb,eX=eR,eY=eD,eH=eT,eq=ek,eG=eF,eJ=e_},5139:function(e,t,n){n.d(t,{j:function(){return i}});let r=e=>"boolean"==typeof e?"".concat(e):0===e?"0":e,o=function(){for(var e,t,n=0,r="";n<arguments.length;)(e=arguments[n++])&&(t=function e(t){var n,r,o="";if("string"==typeof t||"number"==typeof t)o+=t;else if("object"==typeof t){if(Array.isArray(t))for(n=0;n<t.length;n++)t[n]&&(r=e(t[n]))&&(o&&(o+=" "),o+=r);else for(n in t)t[n]&&(o&&(o+=" "),o+=n)}return o}(e))&&(r&&(r+=" "),r+=t);return r},i=(e,t)=>n=>{var i;if((null==t?void 0:t.variants)==null)return o(e,null==n?void 0:n.class,null==n?void 0:n.className);let{variants:u,defaultVariants:a}=t,l=Object.keys(u).map(e=>{let t=null==n?void 0:n[e],o=null==a?void 0:a[e];if(null===t)return null;let i=r(t)||r(o);return u[e][i]}),s=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return void 0===r||(e[n]=r),e},{});return o(e,l,null==t?void 0:null===(i=t.compoundVariants)||void 0===i?void 0:i.reduce((e,t)=>{let{class:n,className:r,...o}=t;return Object.entries(o).every(e=>{let[t,n]=e;return Array.isArray(n)?n.includes({...a,...s}[t]):({...a,...s})[t]===n})?[...e,n,r]:e},[]),null==n?void 0:n.class,null==n?void 0:n.className)}}}]);
@@ -0,0 +1,6 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[37],{9037:function(e,s,t){t.d(s,{Cc:function(){return N},GV:function(){return M}});var n=t(5893),l=t(7294),r=t(8799),a=t(7469),c=t(1664),i=t.n(c),o=t(803),d=t(7673),h=t(8764),x=t(3266),u=t(4545),j=t(3626),m=t(998);/**
2
+ * @license lucide-react v0.407.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */let p=(0,m.Z)("Terminal",[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]]),g=(0,m.Z)("SquareCode",[["path",{d:"M10 9.5 8 12l2 2.5",key:"3mjy60"}],["path",{d:"m14 9.5 2 2.5-2 2.5",key:"1bir2l"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);var k=t(9470),f=t(1266),w=t(9307);function N(){let[e,s]=(0,l.useState)(!1),t=l.useRef(null),[a,c]=(0,l.useState)(!1),[d,h]=(0,l.useState)(!1),[x,u]=(0,l.useState)(null);return(0,n.jsxs)(k.A,{highlighted:"clusters",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between mb-4 h-5",children:[(0,n.jsx)("div",{className:"text-base",children:(0,n.jsx)(i(),{href:"/clusters",className:"text-sky-blue leading-none",children:"Sky Clusters"})}),(0,n.jsxs)("div",{className:"flex items-center",children:[e&&(0,n.jsxs)("div",{className:"flex items-center mr-2",children:[(0,n.jsx)(r.Z,{size:15,className:"mt-0"}),(0,n.jsx)("span",{className:"ml-2 text-gray-500",children:"Loading..."})]}),(0,n.jsxs)(o.z,{variant:"ghost",onClick:()=>{t.current&&t.current()},disabled:e,className:"text-sky-blue hover:text-sky-blue-bright flex items-center",children:[(0,n.jsx)(j.Z,{className:"h-4 w-4 mr-1.5"}),(0,n.jsx)("span",{children:"Refresh"})]})]})]}),(0,n.jsx)(v,{refreshInterval:1e4,setLoading:s,refreshDataRef:t,onOpenSSHModal:e=>{u(e),c(!0)},onOpenVSCodeModal:e=>{u(e),h(!0)}}),(0,n.jsx)(f.Oh,{isOpen:a,onClose:()=>c(!1),cluster:x}),(0,n.jsx)(f._R,{isOpen:d,onClose:()=>h(!1),cluster:x})]})}function v(e){let{refreshInterval:s,setLoading:t,refreshDataRef:c,onOpenSSHModal:j,onOpenVSCodeModal:m}=e,[p,g]=(0,l.useState)([]),[k,f]=(0,l.useState)({key:null,direction:"ascending"}),[N,v]=(0,l.useState)(!1),[y,C]=(0,l.useState)(!0),[b,S]=(0,l.useState)(1),[z,O]=(0,l.useState)(10),R=l.useCallback(async()=>{t(!0),v(!0),g(await (0,x.zd)()),t(!1),v(!1),C(!1)},[t]),V=l.useMemo(()=>(0,u.R0)(p,k.key,k.direction),[p,k]);l.useEffect(()=>{c&&(c.current=R)},[c,R]),(0,l.useEffect)(()=>{g([]);let e=!0;R();let t=setInterval(()=>{e&&R()},s);return()=>{e=!1,clearInterval(t)}},[s,R]),(0,l.useEffect)(()=>{S(1)},[p.length]);let L=e=>{let s="ascending";k.key===e&&"ascending"===k.direction&&(s="descending"),f({key:e,direction:s})},_=e=>k.key===e?"ascending"===k.direction?" ↑":" ↓":"",E=Math.ceil(V.length/z),W=(b-1)*z,Z=W+z,H=V.slice(W,Z);return(0,n.jsxs)("div",{children:[(0,n.jsx)(d.Zb,{children:(0,n.jsxs)(h.iA,{children:[(0,n.jsx)(h.xD,{children:(0,n.jsxs)(h.SC,{children:[(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>L("status"),children:["Status",_("status")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>L("cluster"),children:["Cluster",_("cluster")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>L("user"),children:["User",_("user")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>L("resources_str"),children:["Resources",_("resources_str")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>L("region"),children:["Region",_("region")]}),(0,n.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>L("time"),children:["Started",_("time")]}),(0,n.jsx)(h.ss,{children:"Actions"})]})}),(0,n.jsx)(h.RM,{children:N&&y?(0,n.jsx)(h.SC,{children:(0,n.jsx)(h.pj,{colSpan:8,className:"text-center py-6 text-gray-500",children:(0,n.jsxs)("div",{className:"flex justify-center items-center",children:[(0,n.jsx)(r.Z,{size:20,className:"mr-2"}),(0,n.jsx)("span",{children:"Loading..."})]})})}):H.length>0?H.map((e,s)=>(0,n.jsxs)(h.SC,{children:[(0,n.jsx)(h.pj,{children:(0,n.jsx)(w.OE,{status:e.status})}),(0,n.jsx)(h.pj,{children:(0,n.jsx)(i(),{href:"/clusters/".concat(e.cluster),className:"text-blue-600",children:e.cluster})}),(0,n.jsx)(h.pj,{children:e.user}),(0,n.jsx)(h.pj,{children:e.resources_str}),(0,n.jsx)(h.pj,{children:e.region}),(0,n.jsx)(h.pj,{children:(0,a.GV)(e.time)}),(0,n.jsx)(h.pj,{className:"text-left",children:(0,n.jsx)(M,{cluster:e.cluster,status:e.status,onOpenSSHModal:j,onOpenVSCodeModal:m})})]},s)):(0,n.jsx)(h.SC,{children:(0,n.jsx)(h.pj,{colSpan:8,className:"text-center py-6 text-gray-500",children:"No active clusters"})})})]})}),p.length>0&&(0,n.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,n.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,n.jsxs)("div",{className:"flex items-center",children:[(0,n.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,n.jsxs)("div",{className:"relative inline-block",children:[(0,n.jsxs)("select",{value:z,onChange:e=>{O(parseInt(e.target.value,10)),S(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,n.jsx)("option",{value:10,children:"10"}),(0,n.jsx)("option",{value:30,children:"30"}),(0,n.jsx)("option",{value:50,children:"50"}),(0,n.jsx)("option",{value:100,children:"100"}),(0,n.jsx)("option",{value:200,children:"200"})]}),(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-gray-500 absolute right-0 top-1/2 transform -translate-y-1/2 pointer-events-none",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:(0,n.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,n.jsxs)("div",{children:[W+1," – ",Math.min(Z,p.length)," of"," ",p.length]}),(0,n.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,n.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{S(e=>Math.max(e-1,1))},disabled:1===b,className:"text-gray-500 h-8 w-8 p-0",children:(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-left",children:(0,n.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,n.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{S(e=>Math.min(e+1,E))},disabled:b===E||0===E,className:"text-gray-500 h-8 w-8 p-0",children:(0,n.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-right",children:(0,n.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})})]})}let y=(e,s)=>{s&&s(e)},C=(e,s)=>{s?s(e):window.open("ssh://".concat(e))},b=e=>"RUNNING"===e?["connect","VSCode"]:[],S={connect:(0,n.jsx)(p,{className:"w-4 h-4 text-gray-500 inline-block"}),VSCode:(0,n.jsx)(g,{className:"w-4 h-4 text-gray-500 inline-block"})};function M(e){let{withLabel:s=!1,cluster:t,status:l,onOpenSSHModal:r,onOpenVSCodeModal:c}=e,i=b(l),o=e=>{switch(e){case"connect":C(t,r);break;case"VSCode":y(t,c);break;default:return}};return(0,n.jsx)(n.Fragment,{children:(0,n.jsx)("div",{className:"flex items-center space-x-4",children:Object.entries(S).map(e=>{let t,l,[r,c]=e;switch(r){case"connect":t="Connect",l="Connect with SSH";break;case"VSCode":t="VSCode",l="Open in VS Code"}return(s||(t=""),i.includes(r))?(0,n.jsx)(a.WH,{content:l,className:"capitalize text-sm text-muted-foreground",children:(0,n.jsxs)("button",{onClick:()=>o(r),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center",children:[c,t&&(0,n.jsx)("span",{className:"ml-1.5",children:t})]})},r):(0,n.jsx)(a.WH,{content:l,className:"capitalize text-sm text-muted-foreground",children:(0,n.jsxs)("span",{className:"opacity-30 flex items-center cursor-not-allowed text-sm",title:r,children:[c,t&&(0,n.jsx)("span",{className:"ml-1.5",children:t})]})},r)})})})}}}]);