skypilot-nightly 1.0.0.dev20251002__py3-none-any.whl → 1.0.0.dev20251004__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 (59) hide show
  1. sky/__init__.py +2 -2
  2. sky/authentication.py +19 -109
  3. sky/backends/cloud_vm_ray_backend.py +42 -27
  4. sky/client/cli/command.py +1 -11
  5. sky/clouds/cudo.py +1 -1
  6. sky/clouds/kubernetes.py +7 -19
  7. sky/dashboard/out/404.html +1 -1
  8. sky/dashboard/out/_next/static/{16g0-hgEgk6Db72hpE8MY → KL03GEega4QqDqTOMtA_w}/_buildManifest.js +1 -1
  9. sky/dashboard/out/_next/static/chunks/3015-8d748834fcc60b46.js +1 -0
  10. sky/dashboard/out/_next/static/chunks/8969-66237729cdf9749e.js +1 -0
  11. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/{[job]-ad77b12fc736dca3.js → [job]-72794fc3fcdd517a.js} +1 -1
  12. sky/dashboard/out/_next/static/chunks/{webpack-7340bc0f0dd8ae74.js → webpack-3286453d56f3c0a0.js} +1 -1
  13. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  14. sky/dashboard/out/clusters/[cluster].html +1 -1
  15. sky/dashboard/out/clusters.html +1 -1
  16. sky/dashboard/out/config.html +1 -1
  17. sky/dashboard/out/index.html +1 -1
  18. sky/dashboard/out/infra/[context].html +1 -1
  19. sky/dashboard/out/infra.html +1 -1
  20. sky/dashboard/out/jobs/[job].html +1 -1
  21. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  22. sky/dashboard/out/jobs.html +1 -1
  23. sky/dashboard/out/users.html +1 -1
  24. sky/dashboard/out/volumes.html +1 -1
  25. sky/dashboard/out/workspace/new.html +1 -1
  26. sky/dashboard/out/workspaces/[name].html +1 -1
  27. sky/dashboard/out/workspaces.html +1 -1
  28. sky/data/storage_utils.py +9 -0
  29. sky/execution.py +24 -2
  30. sky/global_user_state.py +16 -0
  31. sky/jobs/recovery_strategy.py +45 -0
  32. sky/jobs/server/core.py +60 -53
  33. sky/jobs/state.py +21 -1
  34. sky/jobs/utils.py +29 -11
  35. sky/provision/kubernetes/config.py +0 -42
  36. sky/provision/kubernetes/instance.py +1 -33
  37. sky/provision/kubernetes/manifests/fusermount-server-daemonset.yaml +1 -2
  38. sky/provision/kubernetes/network_utils.py +0 -21
  39. sky/provision/kubernetes/utils.py +136 -300
  40. sky/server/auth/loopback.py +38 -0
  41. sky/server/auth/oauth2_proxy.py +6 -0
  42. sky/server/server.py +6 -0
  43. sky/setup_files/dependencies.py +1 -0
  44. sky/templates/kubernetes-ray.yml.j2 +4 -13
  45. sky/utils/context.py +12 -7
  46. sky/utils/env_options.py +4 -0
  47. sky/utils/kubernetes_enums.py +2 -15
  48. sky/utils/schemas.py +17 -6
  49. {skypilot_nightly-1.0.0.dev20251002.dist-info → skypilot_nightly-1.0.0.dev20251004.dist-info}/METADATA +38 -37
  50. {skypilot_nightly-1.0.0.dev20251002.dist-info → skypilot_nightly-1.0.0.dev20251004.dist-info}/RECORD +55 -56
  51. sky/dashboard/out/_next/static/chunks/3015-88c7c8d69b0b6dba.js +0 -1
  52. sky/dashboard/out/_next/static/chunks/8969-d8bc3a2b9cf839a9.js +0 -1
  53. sky/templates/kubernetes-ssh-jump.yml.j2 +0 -94
  54. sky/utils/kubernetes/ssh_jump_lifecycle_manager.py +0 -191
  55. /sky/dashboard/out/_next/static/{16g0-hgEgk6Db72hpE8MY → KL03GEega4QqDqTOMtA_w}/_ssgManifest.js +0 -0
  56. {skypilot_nightly-1.0.0.dev20251002.dist-info → skypilot_nightly-1.0.0.dev20251004.dist-info}/WHEEL +0 -0
  57. {skypilot_nightly-1.0.0.dev20251002.dist-info → skypilot_nightly-1.0.0.dev20251004.dist-info}/entry_points.txt +0 -0
  58. {skypilot_nightly-1.0.0.dev20251002.dist-info → skypilot_nightly-1.0.0.dev20251004.dist-info}/licenses/LICENSE +0 -0
  59. {skypilot_nightly-1.0.0.dev20251002.dist-info → skypilot_nightly-1.0.0.dev20251004.dist-info}/top_level.txt +0 -0
sky/__init__.py CHANGED
@@ -7,7 +7,7 @@ import urllib.request
7
7
  from sky.utils import directory_utils
8
8
 
9
9
  # Replaced with the current commit when building the wheels.
10
- _SKYPILOT_COMMIT_SHA = 'e92268dca4331cab08759798deab9265e753cba8'
10
+ _SKYPILOT_COMMIT_SHA = '727ea9a60a919fd2ea477dea03a4096136355d20'
11
11
 
12
12
 
13
13
  def _get_git_commit():
@@ -37,7 +37,7 @@ def _get_git_commit():
37
37
 
38
38
 
39
39
  __commit__ = _get_git_commit()
40
- __version__ = '1.0.0.dev20251002'
40
+ __version__ = '1.0.0.dev20251004'
41
41
  __root_dir__ = directory_utils.get_sky_dir()
42
42
 
43
43
 
sky/authentication.py CHANGED
@@ -35,10 +35,8 @@ from sky import clouds
35
35
  from sky import exceptions
36
36
  from sky import global_user_state
37
37
  from sky import sky_logging
38
- from sky import skypilot_config
39
38
  from sky.adaptors import gcp
40
39
  from sky.adaptors import ibm
41
- from sky.adaptors import kubernetes
42
40
  from sky.adaptors import runpod
43
41
  from sky.adaptors import seeweb as seeweb_adaptor
44
42
  from sky.adaptors import vast
@@ -47,8 +45,6 @@ from sky.provision.kubernetes import utils as kubernetes_utils
47
45
  from sky.provision.lambda_cloud import lambda_utils
48
46
  from sky.provision.primeintellect import utils as primeintellect_utils
49
47
  from sky.utils import common_utils
50
- from sky.utils import config_utils
51
- from sky.utils import kubernetes_enums
52
48
  from sky.utils import subprocess_utils
53
49
  from sky.utils import ux_utils
54
50
  from sky.utils import yaml_utils
@@ -431,116 +427,30 @@ def setup_ibm_authentication(config: Dict[str, Any]) -> Dict[str, Any]:
431
427
 
432
428
  def setup_kubernetes_authentication(config: Dict[str, Any]) -> Dict[str, Any]:
433
429
  context = kubernetes_utils.get_context_from_config(config['provider'])
434
-
435
- # Default ssh session is established with kubectl port-forwarding with
436
- # ClusterIP service.
437
- nodeport_mode = kubernetes_enums.KubernetesNetworkingMode.NODEPORT
438
- port_forward_mode = kubernetes_enums.KubernetesNetworkingMode.PORTFORWARD
439
- network_mode_str = skypilot_config.get_effective_region_config(
440
- cloud='kubernetes',
441
- region=context,
442
- keys=('networking',),
443
- default_value=port_forward_mode.value)
444
- try:
445
- network_mode = kubernetes_enums.KubernetesNetworkingMode.from_str(
446
- network_mode_str)
447
- except ValueError as e:
448
- # Add message saying "Please check: ~/.sky/config.yaml" to the error
449
- # message.
450
- with ux_utils.print_exception_no_traceback():
451
- raise ValueError(str(e) +
452
- ' Please check: ~/.sky/config.yaml.') from None
453
- _, public_key_path = get_or_generate_keys()
454
-
455
- # Add the user's public key to the SkyPilot cluster.
456
- secret_name = clouds.Kubernetes.SKY_SSH_KEY_SECRET_NAME
457
- secret_field_name = clouds.Kubernetes().ssh_key_secret_field_name
458
430
  namespace = kubernetes_utils.get_namespace_from_config(config['provider'])
459
- k8s = kubernetes.kubernetes
460
- with open(public_key_path, 'r', encoding='utf-8') as f:
461
- public_key = f.read()
462
- if not public_key.endswith('\n'):
463
- public_key += '\n'
464
-
465
- # Generate metadata
466
- secret_metadata = {
467
- 'name': secret_name,
468
- 'labels': {
469
- 'parent': 'skypilot'
470
- }
471
- }
472
- custom_metadata = skypilot_config.get_effective_region_config(
473
- cloud='kubernetes',
474
- region=context,
475
- keys=('custom_metadata',),
476
- default_value={})
477
- config_utils.merge_k8s_configs(secret_metadata, custom_metadata)
478
-
479
- secret = k8s.client.V1Secret(
480
- metadata=k8s.client.V1ObjectMeta(**secret_metadata),
481
- string_data={secret_field_name: public_key})
482
- try:
483
- if kubernetes_utils.check_secret_exists(secret_name, namespace,
484
- context):
485
- logger.debug(f'Key {secret_name} exists in the cluster, '
486
- 'patching it...')
487
- kubernetes.core_api(context).patch_namespaced_secret(
488
- secret_name, namespace, secret)
489
- else:
490
- logger.debug(f'Key {secret_name} does not exist in the cluster, '
491
- 'creating it...')
492
- kubernetes.core_api(context).create_namespaced_secret(
493
- namespace, secret)
494
- except kubernetes.api_exception() as e:
495
- if e.status == 409 and e.reason == 'AlreadyExists':
496
- logger.debug(f'Key {secret_name} was created concurrently, '
497
- 'patching it...')
498
- kubernetes.core_api(context).patch_namespaced_secret(
499
- secret_name, namespace, secret)
500
- else:
501
- raise e
502
-
503
431
  private_key_path, _ = get_or_generate_keys()
504
- if network_mode == nodeport_mode:
505
- ssh_jump_name = clouds.Kubernetes.SKY_SSH_JUMP_NAME
506
- service_type = kubernetes_enums.KubernetesServiceType.NODEPORT
507
- # Setup service for SSH jump pod. We create the SSH jump service here
508
- # because we need to know the service IP address and port to set the
509
- # ssh_proxy_command in the autoscaler config.
510
- kubernetes_utils.setup_ssh_jump_svc(ssh_jump_name, namespace, context,
511
- service_type)
512
- ssh_proxy_cmd = kubernetes_utils.get_ssh_proxy_command(
513
- ssh_jump_name,
514
- nodeport_mode,
515
- private_key_path=private_key_path,
516
- context=context,
517
- namespace=namespace)
518
- elif network_mode == port_forward_mode:
519
- # Using `kubectl port-forward` creates a direct tunnel to the pod and
520
- # does not require a ssh jump pod.
521
- kubernetes_utils.check_port_forward_mode_dependencies()
522
- # TODO(romilb): This can be further optimized. Instead of using the
523
- # head node as a jump pod for worker nodes, we can also directly
524
- # set the ssh_target to the worker node. However, that requires
525
- # changes in the downstream code to return a mapping of node IPs to
526
- # pod names (to be used as ssh_target) and updating the upstream
527
- # SSHConfigHelper to use a different ProxyCommand for each pod.
528
- # This optimization can reduce SSH time from ~0.35s to ~0.25s, tested
529
- # on GKE.
530
- ssh_target = config['cluster_name'] + '-head'
531
- ssh_proxy_cmd = kubernetes_utils.get_ssh_proxy_command(
532
- ssh_target,
533
- port_forward_mode,
534
- private_key_path=private_key_path,
535
- context=context,
536
- namespace=namespace)
537
- else:
538
- # This should never happen because we check for this in from_str above.
539
- raise ValueError(f'Unsupported networking mode: {network_mode_str}')
432
+ # Using `kubectl port-forward` creates a direct tunnel to the pod and
433
+ # does not require a ssh jump pod.
434
+ kubernetes_utils.check_port_forward_mode_dependencies()
435
+ # TODO(romilb): This can be further optimized. Instead of using the
436
+ # head node as a jump pod for worker nodes, we can also directly
437
+ # set the ssh_target to the worker node. However, that requires
438
+ # changes in the downstream code to return a mapping of node IPs to
439
+ # pod names (to be used as ssh_target) and updating the upstream
440
+ # SSHConfigHelper to use a different ProxyCommand for each pod.
441
+ # This optimization can reduce SSH time from ~0.35s to ~0.25s, tested
442
+ # on GKE.
443
+ pod_name = config['cluster_name'] + '-head'
444
+ ssh_proxy_cmd = kubernetes_utils.get_ssh_proxy_command(
445
+ pod_name,
446
+ private_key_path=private_key_path,
447
+ context=context,
448
+ namespace=namespace)
540
449
  config['auth']['ssh_proxy_command'] = ssh_proxy_cmd
541
450
  config['auth']['ssh_private_key'] = private_key_path
542
451
 
543
- return config
452
+ # Add the user's public key to the SkyPilot cluster.
453
+ return configure_ssh_info(config)
544
454
 
545
455
 
546
456
  # ---------------------------------- RunPod ---------------------------------- #
@@ -3277,6 +3277,10 @@ class CloudVmRayBackend(backends.Backend['CloudVmRayResourceHandle']):
3277
3277
  self._requested_features = set()
3278
3278
  self._dump_final_script = False
3279
3279
  self._is_managed = False
3280
+ # Optional planner (via register_info): used under the per-cluster lock
3281
+ # to produce a fresh concrete plan when neither a reusable snapshot nor
3282
+ # a caller plan is available.
3283
+ self._planner = None
3280
3284
 
3281
3285
  # Command for running the setup script. It is only set when the
3282
3286
  # setup needs to be run outside the self._setup() and as part of
@@ -3294,6 +3298,9 @@ class CloudVmRayBackend(backends.Backend['CloudVmRayResourceHandle']):
3294
3298
  self._requested_features)
3295
3299
  self._dump_final_script = kwargs.pop('dump_final_script', False)
3296
3300
  self._is_managed = kwargs.pop('is_managed', False)
3301
+ # Optional planner callback for a fresh plan under lock when no
3302
+ # reusable snapshot/caller plan exists. Keeps optimizer in upper layer.
3303
+ self._planner = kwargs.pop('planner', self._planner)
3297
3304
  assert not kwargs, f'Unexpected kwargs: {kwargs}'
3298
3305
 
3299
3306
  def check_resources_fit_cluster(
@@ -5843,33 +5850,41 @@ class CloudVmRayBackend(backends.Backend['CloudVmRayResourceHandle']):
5843
5850
  common_utils.check_cluster_name_is_valid(cluster_name)
5844
5851
 
5845
5852
  if to_provision is None:
5846
- # The cluster is recently terminated either by autostop or manually
5847
- # terminated on the cloud. We should use the previously terminated
5848
- # resources to provision the cluster.
5849
- #
5850
- # FIXME(zongheng): this assert can be hit by using two terminals.
5851
- # First, create a 'dbg' cluster. Then:
5852
- # Terminal 1: sky down dbg -y
5853
- # Terminal 2: sky launch -c dbg -- echo
5854
- # Run it in order. Terminal 2 will show this error after terminal 1
5855
- # succeeds in downing the cluster and releasing the lock.
5856
- assert isinstance(
5857
- handle_before_refresh, CloudVmRayResourceHandle), (
5858
- f'Trying to launch cluster {cluster_name!r} recently '
5859
- 'terminated on the cloud, but the handle is not a '
5860
- f'CloudVmRayResourceHandle ({handle_before_refresh}).')
5861
- status_before_refresh_str = None
5862
- if status_before_refresh is not None:
5863
- status_before_refresh_str = status_before_refresh.value
5864
-
5865
- logger.info(
5866
- f'The cluster {cluster_name!r} (status: '
5867
- f'{status_before_refresh_str}) was not found on the cloud: it '
5868
- 'may be autodowned, manually terminated, or its launch never '
5869
- 'succeeded. Provisioning a new cluster by using the same '
5870
- 'resources as its original launch.')
5871
- to_provision = handle_before_refresh.launched_resources
5872
- self.check_resources_fit_cluster(handle_before_refresh, task)
5853
+ # Recently terminated after refresh. OPTIMIZE usually ran outside
5854
+ # the lock, so that decision may be stale by now. Under the lock,
5855
+ # ensure we always have a concrete plan via the following order:
5856
+ # 1) Reuse last placement snapshot (if available);
5857
+ # 2) Else, call injected planner for a fresh plan.
5858
+ # If we still have a pre-refresh handle snapshot with a concrete
5859
+ # placement, prefer reusing it.
5860
+ if (isinstance(handle_before_refresh, CloudVmRayResourceHandle) and
5861
+ handle_before_refresh.launched_resources is not None):
5862
+ to_provision = handle_before_refresh.launched_resources
5863
+ # Ensure the requested task fits the previous placement.
5864
+ self.check_resources_fit_cluster(handle_before_refresh, task)
5865
+ # Mirror the original message for reuse path.
5866
+ status_before_refresh_str = None
5867
+ if status_before_refresh is not None:
5868
+ status_before_refresh_str = status_before_refresh.value
5869
+ logger.info(
5870
+ f'The cluster {cluster_name!r} (status: '
5871
+ f'{status_before_refresh_str}) was not found on the cloud: '
5872
+ 'it may be autodowned, manually terminated, or its launch '
5873
+ 'never succeeded. Provisioning a new cluster by using the '
5874
+ 'same resources as its original launch.')
5875
+ elif self._planner is not None:
5876
+ to_provision = self._planner(task)
5877
+ logger.info(
5878
+ 'Previous placement snapshot missing; computing a fresh '
5879
+ 'plan for provisioning.')
5880
+ else:
5881
+ # Without a snapshot or planner, we cannot proceed safely.
5882
+ # Surface a user-friendly error without a long traceback.
5883
+ with ux_utils.print_exception_no_traceback():
5884
+ raise RuntimeError(
5885
+ 'No concrete launch plan available after recent cloud '
5886
+ f'termination of cluster {cluster_name!r}. Ensure the '
5887
+ 'OPTIMIZE stage runs or provide concrete resources.')
5873
5888
 
5874
5889
  return RetryingVmProvisioner.ToProvisionConfig(
5875
5890
  cluster_name,
sky/client/cli/command.py CHANGED
@@ -1803,17 +1803,7 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
1803
1803
  return None
1804
1804
 
1805
1805
  def submit_workspace() -> Optional[server_common.RequestId[Dict[str, Any]]]:
1806
- try:
1807
- return sdk.workspaces()
1808
- except RuntimeError:
1809
- # Backward compatibility for API server before #5660.
1810
- # TODO(zhwu): remove this after 0.10.0.
1811
- logger.warning(f'{colorama.Style.DIM}SkyPilot API server is '
1812
- 'in an old version, and may miss feature: '
1813
- 'workspaces. Update with: sky api stop; '
1814
- 'sky api start'
1815
- f'{colorama.Style.RESET_ALL}')
1816
- return None
1806
+ return sdk.workspaces()
1817
1807
 
1818
1808
  active_workspace = skypilot_config.get_active_workspace()
1819
1809
 
sky/clouds/cudo.py CHANGED
@@ -288,7 +288,7 @@ class Cudo(clouds.Cloud):
288
288
  cls) -> Tuple[bool, Optional[Union[str, Dict[str, str]]]]:
289
289
  """Checks if the user has access credentials to
290
290
  Cudo's compute service."""
291
- if not common.can_import_modules(['cudo_api']):
291
+ if not common.can_import_modules(['cudo_compute']):
292
292
  return False, (f'{cls._DEPENDENCY_HINT}\n'
293
293
  f'{cls._INDENT_PREFIX}')
294
294
 
sky/clouds/kubernetes.py CHANGED
@@ -25,6 +25,7 @@ from sky.provision.kubernetes.utils import normalize_tpu_accelerator_name
25
25
  from sky.skylet import constants
26
26
  from sky.utils import annotations
27
27
  from sky.utils import common_utils
28
+ from sky.utils import env_options
28
29
  from sky.utils import kubernetes_enums
29
30
  from sky.utils import registry
30
31
  from sky.utils import resources_utils
@@ -47,9 +48,6 @@ _FUSERMOUNT_SHARED_DIR = '/var/run/fusermount'
47
48
  class Kubernetes(clouds.Cloud):
48
49
  """Kubernetes."""
49
50
 
50
- SKY_SSH_KEY_SECRET_NAME = 'sky-ssh-keys'
51
- SKY_SSH_JUMP_NAME = 'sky-ssh-jump-pod'
52
-
53
51
  # Limit the length of the cluster name to avoid exceeding the limit of 63
54
52
  # characters for Kubernetes resources. We limit to 42 characters (63-21) to
55
53
  # allow additional characters for creating ingress services to expose ports.
@@ -98,14 +96,6 @@ class Kubernetes(clouds.Cloud):
98
96
  # Set of contexts that has logged as temporarily unreachable
99
97
  logged_unreachable_contexts: Set[str] = set()
100
98
 
101
- @property
102
- def ssh_key_secret_field_name(self):
103
- # Use a fresh user hash to avoid conflicts in the secret object naming.
104
- # This can happen when the controller is reusing the same user hash
105
- # through USER_ID_ENV_VAR but has a different SSH key.
106
- fresh_user_hash = common_utils.generate_user_hash()
107
- return f'ssh-publickey-{fresh_user_hash}'
108
-
109
99
  @classmethod
110
100
  def _unsupported_features_for_resources(
111
101
  cls, resources: 'resources_lib.Resources'
@@ -188,6 +178,12 @@ class Kubernetes(clouds.Cloud):
188
178
  ctx for ctx in all_contexts if not ctx.startswith('ssh-')
189
179
  ]
190
180
 
181
+ allow_all_contexts = allowed_contexts == 'all' or (
182
+ allowed_contexts is None and
183
+ env_options.Options.ALLOW_ALL_KUBERNETES_CONTEXTS.get())
184
+ if allow_all_contexts:
185
+ allowed_contexts = all_contexts
186
+
191
187
  if allowed_contexts is None:
192
188
  # Try kubeconfig if present
193
189
  current_context = (
@@ -517,9 +513,6 @@ class Kubernetes(clouds.Cloud):
517
513
  return image_id
518
514
 
519
515
  image_id = _get_image_id(resources)
520
- # TODO(romilb): Create a lightweight image for SSH jump host
521
- ssh_jump_image = catalog.get_image_id_from_tag(self.IMAGE_CPU,
522
- clouds='kubernetes')
523
516
 
524
517
  # Set environment variables for the pod. Note that SkyPilot env vars
525
518
  # are set separately when the task is run. These env vars are
@@ -693,13 +686,8 @@ class Kubernetes(clouds.Cloud):
693
686
  'accelerator_count': str(acc_count),
694
687
  'timeout': str(timeout),
695
688
  'k8s_port_mode': port_mode.value,
696
- 'k8s_networking_mode': network_utils.get_networking_mode(
697
- None, context=context).value,
698
- 'k8s_ssh_key_secret_name': self.SKY_SSH_KEY_SECRET_NAME,
699
689
  'k8s_acc_label_key': k8s_acc_label_key,
700
690
  'k8s_acc_label_values': k8s_acc_label_values,
701
- 'k8s_ssh_jump_name': self.SKY_SSH_JUMP_NAME,
702
- 'k8s_ssh_jump_image': ssh_jump_image,
703
691
  'k8s_service_account_name': k8s_service_account_name,
704
692
  'k8s_automount_sa_token': 'true',
705
693
  'k8s_fuse_device_required': fuse_device_required,
@@ -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-7340bc0f0dd8ae74.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-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/16g0-hgEgk6Db72hpE8MY/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/16g0-hgEgk6Db72hpE8MY/_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":"16g0-hgEgk6Db72hpE8MY","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-3286453d56f3c0a0.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-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/KL03GEega4QqDqTOMtA_w/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/KL03GEega4QqDqTOMtA_w/_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":"KL03GEega4QqDqTOMtA_w","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- self.__BUILD_MANIFEST=function(s,c,a,t,e,f,b,u,n,o,j,i,r,k){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-469814d711d63b1b.js"],"/clusters/[cluster]":[s,c,a,f,b,"static/chunks/4676-9da7fdbde90b5549.js",o,t,e,u,j,n,i,"static/chunks/6856-5fdc9b851a18acdb.js",r,k,"static/chunks/9037-d0c00018a5ba198c.js","static/chunks/pages/clusters/[cluster]-e052384df65ef200.js"],"/clusters/[cluster]/[job]":[s,c,a,f,t,e,n,"static/chunks/pages/clusters/[cluster]/[job]-ad77b12fc736dca3.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-aabba60d57826e0f.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-6563820e094f68ca.js"],"/jobs":["static/chunks/pages/jobs-1f70d9faa564804f.js"],"/jobs/pools/[pool]":[s,c,a,b,o,t,e,u,"static/chunks/pages/jobs/pools/[pool]-509b2977a6373bf6.js"],"/jobs/[job]":[s,c,a,f,b,o,t,e,u,n,"static/chunks/pages/jobs/[job]-dd64309c3fe67ed2.js"],"/users":["static/chunks/pages/users-018bf31cda52e11b.js"],"/volumes":["static/chunks/pages/volumes-739726d6b823f532.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-7528cc0ef8c522c5.js"],"/workspaces/[name]":[s,c,a,f,b,"static/chunks/1836-37fede578e2da5f8.js",t,e,u,j,n,i,r,k,"static/chunks/1141-159df2d4c441a9d1.js","static/chunks/pages/workspaces/[name]-af76bb06dbb3954f.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-01359c57e018caa4.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-d8bc3a2b9cf839a9.js","static/chunks/6135-4b4d5e824b7f9d3c.js","static/chunks/754-d0da8ab45f9509e9.js","static/chunks/6990-f6818c84ed8f1c86.js","static/chunks/1121-d0782b9251f0fcd3.js","static/chunks/6601-06114c982db410b6.js","static/chunks/3015-88c7c8d69b0b6dba.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
1
+ self.__BUILD_MANIFEST=function(s,c,a,e,t,f,u,n,b,o,j,i,r,k){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-469814d711d63b1b.js"],"/clusters/[cluster]":[s,c,a,f,u,"static/chunks/4676-9da7fdbde90b5549.js",o,e,t,n,j,b,i,"static/chunks/6856-5fdc9b851a18acdb.js",r,k,"static/chunks/9037-d0c00018a5ba198c.js","static/chunks/pages/clusters/[cluster]-e052384df65ef200.js"],"/clusters/[cluster]/[job]":[s,c,a,f,e,t,b,"static/chunks/pages/clusters/[cluster]/[job]-72794fc3fcdd517a.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-aabba60d57826e0f.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-6563820e094f68ca.js"],"/jobs":["static/chunks/pages/jobs-1f70d9faa564804f.js"],"/jobs/pools/[pool]":[s,c,a,u,o,e,t,n,"static/chunks/pages/jobs/pools/[pool]-509b2977a6373bf6.js"],"/jobs/[job]":[s,c,a,f,u,o,e,t,n,b,"static/chunks/pages/jobs/[job]-dd64309c3fe67ed2.js"],"/users":["static/chunks/pages/users-018bf31cda52e11b.js"],"/volumes":["static/chunks/pages/volumes-739726d6b823f532.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-7528cc0ef8c522c5.js"],"/workspaces/[name]":[s,c,a,f,u,"static/chunks/1836-37fede578e2da5f8.js",e,t,n,j,b,i,r,k,"static/chunks/1141-159df2d4c441a9d1.js","static/chunks/pages/workspaces/[name]-af76bb06dbb3954f.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-01359c57e018caa4.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-66237729cdf9749e.js","static/chunks/6135-4b4d5e824b7f9d3c.js","static/chunks/754-d0da8ab45f9509e9.js","static/chunks/6990-f6818c84ed8f1c86.js","static/chunks/1121-d0782b9251f0fcd3.js","static/chunks/6601-06114c982db410b6.js","static/chunks/3015-8d748834fcc60b46.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3015],{23015:function(e,s,t){t.r(s),t.d(s,{ClusterJobs:function(){return H},ManagedJobs:function(){return Z},ManagedJobsTable:function(){return B},Status2Actions:function(){return q},filterJobsByName:function(){return J},filterJobsByPool:function(){return O},filterJobsByUser:function(){return W},filterJobsByWorkspace:function(){return U},statusGroups:function(){return z}});var r=t(85893),a=t(67294),l=t(11163),n=t(41664),i=t.n(n),c=t(55739),o=t(30803),d=t(37673),u=t(68764),h=t(36989),x=t(51214),m=t(68969),p=t(6378);class j{_generateFilterKey(e){let{allUsers:s=!0,nameMatch:t,userMatch:r,workspaceMatch:a,poolMatch:l,statuses:n}=e;return["allUsers:".concat(s),t?"name:".concat(t):"",r?"user:".concat(r):"",a?"workspace:".concat(a):"",l?"pool:".concat(l):"",n&&n.length>0?"statuses:".concat(n.sort().join(",")):""].filter(Boolean).join("|")||"default"}_getCacheStatus(e){let s=this.fullDataCache.get(e),t=Date.now();if(!s)return{isCached:!1,isFresh:!1,age:0,maxAge:12e4,hasData:!1};let r=t-s.timestamp;return{isCached:!0,isFresh:r<12e4,age:r,maxAge:12e4,hasData:s.jobs&&Array.isArray(s.jobs),data:s}}async getPaginatedJobs(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{page:s=1,limit:t=10,...r}=e,a=this._generateFilterKey(r);try{let e=this._getCacheStatus(a);if(e.isCached&&e.hasData){let l=e.data;if(!l.jobs||Array.isArray(l.jobs)&&0===l.jobs.length){if(!this.prefetching.has(a)){let e=this._loadFullDataset(r,a).catch(()=>{}).finally(()=>this.prefetching.delete(a));this.prefetching.set(a,e)}}else{let n=(s-1)*t,i=l.jobs.slice(n,n+t);if(!this.prefetching.has(a)&&(!e.isFresh||e.age>e.maxAge/2)){let e=this._loadFullDataset(r,a).catch(()=>{}).finally(()=>this.prefetching.delete(a));this.prefetching.set(a,e)}return{jobs:i,total:l.total,totalNoFilter:l.totalNoFilter||l.total,controllerStopped:l.controllerStopped,statusCounts:l.statusCounts||{},fromCache:!0,cacheStatus:e.isFresh?"local_cache_hit":"local_cache_stale_hit"}}}let l=await p.default.get(m.getManagedJobs,[{...r,page:s,limit:t}]),n=(null==l?void 0:l.jobs)||[],i="number"==typeof(null==l?void 0:l.total)?l.total:n.length,c=!!(null==l?void 0:l.controllerStopped);if(!this.prefetching.has(a)){let e=this._loadFullDataset(r,a).catch(e=>{console.warn("Background prefetch of full jobs failed:",e)}).finally(()=>{this.prefetching.delete(a)});this.prefetching.set(a,e)}return{jobs:n,total:i,totalNoFilter:(null==l?void 0:l.totalNoFilter)||i,controllerStopped:c,statusCounts:(null==l?void 0:l.statusCounts)||{},fromCache:!1,cacheStatus:"server_page_fetch"}}catch(e){return console.error("Error in getPaginatedJobs:",e),{jobs:[],total:0,totalNoFilter:0,controllerStopped:!1,statusCounts:{},fromCache:!1,cacheStatus:"error"}}}async _loadFullDataset(e,s){let t=await p.default.get(m.getManagedJobs,[e]);if(t.controllerStopped||!t.jobs)return t;let r={jobs:t.jobs,total:t.jobs.length,totalNoFilter:t.totalNoFilter||t.jobs.length,controllerStopped:!1,statusCounts:t.statusCounts||{},timestamp:Date.now()};return this.fullDataCache.set(s,r),r}isDataLoading(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=this._generateFilterKey(e);return this.isLoading.has(s)||this.prefetching.has(s)}isDataCached(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=this._generateFilterKey(e),t=this._getCacheStatus(s);return t.isCached&&t.isFresh&&t.hasData}getCacheStatus(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=this._generateFilterKey(e);return this._getCacheStatus(s)}invalidateCache(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if(e){let s=this._generateFilterKey(e);this.fullDataCache.delete(s),this.isLoading.delete(s),this.prefetching.delete(s)}else this.fullDataCache.clear(),this.isLoading.clear(),this.prefetching.clear();p.default.invalidateFunction(m.getManagedJobs)}getCacheStats(){let e={cachedFilters:Array.from(this.fullDataCache.keys()),loadingFilters:Array.from(this.isLoading.keys()),prefetchingFilters:Array.from(this.prefetching.keys()),cacheSize:this.fullDataCache.size,loadingCount:this.isLoading.size,prefetchingCount:this.prefetching.size};for(let[s,t]of(e.detailedStatus={},this.fullDataCache.entries())){let r=this._getCacheStatus(s);e.detailedStatus[s]={age:r.age,isFresh:r.isFresh,hasData:r.hasData,jobCount:t.jobs?t.jobs.length:0}}return e}constructor(){this.fullDataCache=new Map,this.isLoading=new Map,this.prefetching=new Map}}let f=new j;var g=t(23266),b=t(17324),v=t(53081),w=t(13626),y=t(23293),N=t(6521),k=t(16826),C=t(92128),S=t(94545),_=t(99307),L=t(20546),E=t(23001),R=t(88950);let D=(e,s)=>{let t={...e.query},r=[],a=[],l=[];s.map((e,s)=>{var t;r.push(null!==(t=e.property.toLowerCase())&&void 0!==t?t:""),a.push(e.operator),l.push(e.value)}),t.property=r,t.operator=a,t.value=l,e.replace({pathname:e.pathname,query:t},void 0,{shallow:!0})},F=(e,s)=>{let t={...e.query},r=t.property,a=t.operator,l=t.value;if(void 0===r)return[];let n=[],i=Array.isArray(r)?r.length:1;if(1===i)n.push({property:s.get(r),operator:a,value:l});else for(let e=0;e<i;e++)n.push({property:s.get(r[e]),operator:a[e],value:l[e]});return n},M=e=>{var s,t;let{propertyList:l=[],valueList:n,setFilters:i,updateURLParams:c,placeholder:o="Filter items"}=e,d=(0,a.useRef)(null),u=(0,a.useRef)(null),[h,x]=(0,a.useState)(!1),[m,p]=(0,a.useState)(""),[j,f]=(0,a.useState)((null===(s=l[0])||void 0===s?void 0:s.value)||"status"),[g,b]=(0,a.useState)([]);(0,a.useEffect)(()=>{let e=e=>{u.current&&!u.current.contains(e.target)&&d.current&&!d.current.contains(e.target)&&x(!1)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[]),(0,a.useEffect)(()=>{let e=[];n&&"object"==typeof n&&(e=n[j]||[]),""!==m.trim()&&(e=e.filter(e=>e&&e.toString().toLowerCase().includes(m.toLowerCase()))),b(e)},[j,n,m]);let v=e=>{let s=l.find(s=>s.value===e);return s?s.label:e},w=e=>{i(s=>{let t=[...s,{property:v(j),operator:":",value:e}];return c(t),t}),x(!1),p(""),d.current.focus()};return(0,r.jsxs)("div",{className:"flex flex-row border border-gray-300 rounded-md overflow-visible",children:[(0,r.jsx)("div",{className:"border-r border-gray-300 flex-shrink-0",children:(0,r.jsxs)(R.Ph,{onValueChange:f,value:j,children:[(0,r.jsx)(R.i4,{"aria-label":"Filter Property",className:"focus:ring-0 focus:ring-offset-0 border-none rounded-l-md rounded-r-none w-20 sm:w-24 md:w-32 h-8 text-xs sm:text-sm",children:(0,r.jsx)(R.ki,{placeholder:(null===(t=l[0])||void 0===t?void 0:t.label)||"Status"})}),(0,r.jsx)(R.Bw,{children:l.map((e,s)=>(0,r.jsx)(R.Ql,{value:e.value,children:e.label},"property-item-".concat(s)))})]})}),(0,r.jsxs)("div",{className:"relative flex-1",children:[(0,r.jsx)("input",{type:"text",ref:d,placeholder:o,value:m,onChange:e=>{p(e.target.value),h||x(!0)},onFocus:()=>{x(!0)},onKeyDown:e=>{"Enter"===e.key&&""!==m.trim()?(i(e=>{let s=[...e,{property:v(j),operator:":",value:m}];return c(s),s}),p(""),x(!1)):"Escape"===e.key&&(x(!1),d.current.blur())},className:"h-8 w-full sm:w-96 px-3 pr-8 text-sm border-none rounded-l-none rounded-r-md focus:ring-0 focus:outline-none",autoComplete:"off"}),m&&(0,r.jsx)("button",{onClick:()=>{p(""),x(!1)},className:"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600",title:"Clear filter",tabIndex:-1,children:(0,r.jsx)("svg",{className:"h-4 w-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})}),h&&g.length>0&&(0,r.jsx)("div",{ref:u,className:"absolute z-50 mt-1 w-full bg-white border border-gray-200 rounded-md shadow-lg max-h-60 overflow-y-auto",style:{zIndex:9999},children:g.map((e,s)=>(0,r.jsx)("div",{className:"px-3 py-2 cursor-pointer hover:bg-gray-50 text-sm ".concat(s!==g.length-1?"border-b border-gray-100":""),onClick:()=>w(e),children:(0,r.jsx)("span",{className:"text-sm text-gray-700",children:e})},"".concat(e,"-").concat(s)))})]})]})},I=e=>{let{filters:s=[],setFilters:t,updateURLParams:a}=e,l=e=>{t(s=>{let t=s.filter((s,t)=>t!==e);return a(t),t})};return(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("div",{className:"flex items-center gap-4 py-2 px-2",children:(0,r.jsxs)("div",{className:"flex flex-wrap items-content gap-2",children:[s.map((e,s)=>(0,r.jsx)(A,{filter:e,onRemove:()=>l(s)},"filteritem-".concat(s))),s.length>0&&(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("button",{onClick:()=>{a([]),t([])},className:"rounded-full px-4 py-1 text-sm text-gray-700 bg-gray-200 hover:bg-gray-300",children:"Clear filters"})})]})})})},A=e=>{let{filter:s,onRemove:t}=e;return(0,r.jsx)(r.Fragment,{children:(0,r.jsxs)("div",{className:"flex items-center text-blue-600 bg-blue-100 px-1 py-1 rounded-full text-sm",children:[(0,r.jsxs)("div",{className:"flex items-center gap-1 px-2",children:[(0,r.jsx)("span",{children:"".concat(s.property," ")}),(0,r.jsx)("span",{children:"".concat(s.operator," ")}),(0,r.jsx)("span",{children:" ".concat(s.value)})]}),(0,r.jsx)("button",{onClick:()=>t(),className:"p-0.5 ml-1 transform text-gray-400 hover:text-gray-600 bg-blue-500 hover:bg-blue-600 rounded-full flex flex-col items-center",title:"Clear filter",children:(0,r.jsx)("svg",{className:"h-3 w-3",fill:"none",stroke:"white",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:5,d:"M6 18L18 6M6 6l12 12"})})})]})})},z={active:["PENDING","RUNNING","RECOVERING","SUBMITTED","STARTING","CANCELLING"],finished:["SUCCEEDED","FAILED","CANCELLED","FAILED_SETUP","FAILED_PRECHECKS","FAILED_NO_RESOURCE","FAILED_CONTROLLER"]},P=[{label:"Name",value:"name"},{label:"User",value:"user"},{label:"Workspace",value:"workspace"},{label:"Pool",value:"pool"}];function J(e,s){if(!s||""===s.trim())return e;let t=s.toLowerCase().trim();return e.filter(e=>(e.name||"").toLowerCase().includes(t))}function U(e,s){return s&&"ALL_WORKSPACES"!==s?e.filter(e=>(e.workspace||"default").toLowerCase()===s.toLowerCase()):e}function W(e,s){return s&&"ALL_USERS"!==s?e.filter(e=>(e.user_hash||e.user)===s):e}function O(e,s){if(!s||""===s.trim())return e;let t=s.toLowerCase().trim();return e.filter(e=>(e.pool||"").toLowerCase().includes(t))}let T=e=>{if(!e)return"-";let s=e instanceof Date?e:new Date(1e3*e);return(0,r.jsx)(h.Zg,{date:s})};function Z(){let e=(0,l.useRouter)(),[s,t]=(0,a.useState)(!1),[n,c]=(0,a.useState)(!0),[o,d]=(0,a.useState)(!0),u=a.useRef(null),x=a.useRef(null),[j,g]=(0,a.useState)([]),[w,y]=(0,a.useState)([]),N=async function(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];t(!0),!e&&o&&c(!0);try{let[e]=await Promise.all([p.default.get(m.vs,[{}])]);g(e.pools||[])}catch(e){console.error("Error fetching data:",e)}finally{t(!1),!e&&o&&(c(!1),d(!1))}};(0,a.useEffect)(()=>{N()},[]);let k=s=>{D(e,s)},C=a.useCallback(()=>{let s=new Map;s.set("",""),s.set("status","Status"),s.set("name","Name"),s.set("user","User"),s.set("workspace","Workspace"),s.set("pool","Pool"),y(F(e,s))},[e,y]);return(0,a.useEffect)(()=>{e.isReady&&C()},[e.isReady,e.query.tab,C]),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-2 mb-1",children:[(0,r.jsx)("div",{className:"text-base",children:(0,r.jsx)(i(),{href:"/jobs",className:"text-sky-blue hover:underline leading-none",children:"Managed Jobs"})}),(0,r.jsx)("div",{className:"w-full sm:w-auto",children:(0,r.jsx)(M,{propertyList:P,valueList:{},setFilters:y,updateURLParams:k,placeholder:"Filter jobs"})})]}),(0,r.jsx)(I,{filters:w,setFilters:y,updateURLParams:k}),(0,r.jsx)(B,{refreshInterval:h.yc,setLoading:t,refreshDataRef:u,filters:w,onRefresh:()=>{f.invalidateCache(),p.default.invalidate(m.vs,[{}]),p.default.invalidate(b.getWorkspaces),p.default.invalidate(v.R),u.current&&u.current(),x.current&&x.current()},poolsData:j,poolsLoading:n}),(0,r.jsx)("div",{className:"mb-4",children:(0,r.jsx)(V,{refreshInterval:h.yc,setLoading:t,refreshDataRef:x})})]})}function B(e){let{refreshInterval:s,setLoading:t,refreshDataRef:l,filters:n,onRefresh:j,poolsData:b,poolsLoading:v}=e,[N,k]=(0,a.useState)([]),[R,D]=(0,a.useState)(0),[F,M]=(0,a.useState)(0),[I,A]=(0,a.useState)({key:null,direction:"ascending"}),[P,J]=(0,a.useState)(!1),[U,W]=(0,a.useState)(!0),[O,Z]=(0,a.useState)(1),[B,H]=(0,a.useState)(10),[V,Y]=(0,a.useState)(null),Q=(0,a.useRef)(null),[X,$]=(0,a.useState)([]),[ee,es]=(0,a.useState)({}),[et,er]=(0,a.useState)({}),[ea,el]=(0,a.useState)(!1),[en,ei]=(0,a.useState)(!1),[ec,eo]=(0,a.useState)(!1),[ed,eu]=(0,a.useState)("all"),[eh,ex]=(0,a.useState)(!0),[em,ep]=(0,a.useState)({isOpen:!1,title:"",message:"",onConfirm:null}),ej=(0,E.X)(),ef=(0,a.useRef)(0),eg=async()=>{ep({isOpen:!0,title:"Restart Controller",message:"Are you sure you want to restart the controller?",onConfirm:async()=>{try{eo(!0),J(!0),await (0,m.Ce)("restartcontroller"),await eb()}catch(e){console.error("Error restarting controller:",e)}finally{eo(!1),J(!1)}}})},eb=a.useCallback(async function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=!1!==e.includeStatus,r=ef.current+1;ef.current=r,J(!0),t(!0);try{let e,t;let a=e=>{let s=(n||[]).find(s=>(s.property||"").toLowerCase()===e);return s&&s.value?String(s.value):void 0};X.length>0?t=X:eh?"active"===ed?t=z.active:"finished"===ed&&(t=z.finished):t=[];let l={allUsers:!0,nameMatch:a("name"),userMatch:a("user"),workspaceMatch:a("workspace"),poolMatch:a("pool"),statuses:t,page:O,limit:B},i=null;if(f.isDataCached(l),f.isDataLoading(l),s){let[s,t]=await Promise.all([f.getPaginatedJobs(l),p.default.get(g.getClusters)]);e=s,i=t}else e=await f.getPaginatedJobs(l);let{jobs:c=[],total:o=0,totalNoFilter:d=0,controllerStopped:u=!1,cacheStatus:h="unknown",statusCounts:x={}}=e||{},m=!1,j=!1;if(s&&i){let e=null==i?void 0:i.find(e=>(0,S.Ym)(e.cluster)),s=e?e.status:"NOT_FOUND";"STOPPED"==s&&u&&(m=!0),"LAUNCHING"==s&&(j=!0)}r===ef.current&&(k(c),D(o||0),M(d||0),el(!!m),ei(!!j),er(x),W(!1))}catch(e){console.error("Error fetching data:",e),r===ef.current&&(k([]),el(!1),W(!1))}finally{r===ef.current&&(J(!1),t(!1))}},[t,n,O,B,X,eh,ed]);a.useEffect(()=>{l&&(l.current=eb)},[l,eb]);let ev=a.useRef(eb);a.useEffect(()=>{ev.current=eb},[eb]);let ew=a.useRef(!0);a.useEffect(()=>{eb({includeStatus:!0}),ew.current=!1},[]),a.useEffect(()=>{ew.current||eb({includeStatus:!1})},[O]),a.useEffect(()=>{ew.current||eb({includeStatus:!0})},[n,B]),a.useEffect(()=>{ew.current||eb({includeStatus:!0})},[ed,X,eh]),(0,a.useEffect)(()=>{let e=setInterval(()=>{ev.current&&ev.current({includeStatus:!0})},s);return()=>{clearInterval(e)}},[s]),(0,a.useEffect)(()=>{Z(1)},[ed]),(0,a.useEffect)(()=>{Z(1)},[n,B]),(0,a.useEffect)(()=>{$([]),ex(!0)},[ed]);let ey=e=>{let s="ascending";I.key===e&&"ascending"===I.direction&&(s="descending"),A({key:e,direction:s})},eN=e=>I.key===e?"ascending"===I.direction?" ↑":" ↓":"";a.useMemo(()=>{let e=N||[];return{active:e.filter(e=>z.active.includes(e.status)).length,finished:e.filter(e=>z.finished.includes(e.status)).length}},[N]);let ek=e=>X.length>0?X.includes(e):"all"===ed||z[ed].includes(e),eC=a.useMemo(()=>N,[N]),eS=a.useMemo(()=>I.key?[...eC].sort((e,s)=>e[I.key]<s[I.key]?"ascending"===I.direction?-1:1:e[I.key]>s[I.key]?"ascending"===I.direction?1:-1:0):eC,[eC,I]),e_=(O-1)*B,eL=R>0?Math.ceil(R/B):0,eE=R>0?Math.min(e_+eS.length,R):0,eR=e=>{if(X.includes(e)){let s=X.filter(s=>s!==e);0===s.length?(ex(!0),$([])):($(s),ex(!1))}else $([...X,e]),ex(!1);Z(1)};return(0,a.useEffect)(()=>{es(et)},[et]),(0,r.jsxs)("div",{className:"relative",children:[(0,r.jsx)("div",{className:"flex flex-col space-y-1 mb-1",children:(0,r.jsxs)("div",{className:"flex flex-wrap items-center justify-between text-sm mb-1",children:[(0,r.jsxs)("div",{className:"flex flex-wrap items-center",children:[(0,r.jsx)("span",{className:"mr-2 text-sm font-medium",children:"Statuses:"}),(0,r.jsxs)("div",{className:"flex flex-wrap gap-2 items-center",children:[!P&&0===F&&!U&&(0,r.jsx)("span",{className:"text-gray-500 mr-2",children:"No jobs found"}),Object.entries(ee).map(e=>{let[s,t]=e;return(0,r.jsxs)("button",{onClick:()=>eR(s),className:"px-3 py-0.5 rounded-full flex items-center space-x-2 ".concat(ek(s)||X.includes(s)?(0,_.Cl)(s):"bg-gray-50 text-gray-600 hover:bg-gray-100"),children:[(0,r.jsx)("span",{children:s}),(0,r.jsx)("span",{className:"text-xs ".concat(ek(s)||X.includes(s)?"bg-white/50":"bg-gray-200"," px-1.5 py-0.5 rounded"),children:t})]},s)}),F>0&&(0,r.jsxs)("div",{className:"flex items-center ml-2 gap-2",children:[(0,r.jsx)("span",{className:"text-gray-500",children:"("}),(0,r.jsx)("button",{onClick:()=>{a.startTransition(()=>{eu("all"),$([]),ex(!0),Z(1)})},className:"text-sm font-medium ".concat("all"===ed&&eh?"text-purple-700 underline":"text-gray-600 hover:text-purple-700 hover:underline"),children:"show all jobs"}),(0,r.jsx)("span",{className:"text-gray-500 mx-1",children:"|"}),(0,r.jsx)("button",{onClick:()=>{a.startTransition(()=>{eu("active"),$([]),ex(!0),Z(1)})},className:"text-sm font-medium ".concat("active"===ed&&eh?"text-green-700 underline":"text-gray-600 hover:text-green-700 hover:underline"),children:"show all active jobs"}),(0,r.jsx)("span",{className:"text-gray-500 mx-1",children:"|"}),(0,r.jsx)("button",{onClick:()=>{a.startTransition(()=>{eu("finished"),$([]),ex(!0),Z(1)})},className:"text-sm font-medium ".concat("finished"===ed&&eh?"text-blue-700 underline":"text-gray-600 hover:text-blue-700 hover:underline"),children:"show all finished jobs"}),(0,r.jsx)("span",{className:"text-gray-500",children:")"})]})]})]}),(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[P&&(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(c.Z,{size:15,className:"mt-0"}),(0,r.jsx)("span",{className:"ml-2 text-gray-500 text-sm",children:"Loading..."})]}),(0,r.jsxs)("button",{onClick:()=>{j&&j()},disabled:P,className:"text-sky-blue hover:text-sky-blue-bright flex items-center text-sm",children:[(0,r.jsx)(w.Z,{className:"h-4 w-4 mr-1.5"}),(0,r.jsx)("span",{children:"Refresh"})]})]})]})}),ej&&ea&&0===eS.length&&!P&&!U&&(0,r.jsx)("div",{className:"mb-4 p-4 bg-gray-50 rounded-lg border",children:(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-3",children:[(0,r.jsxs)("p",{className:"text-gray-700 text-center text-sm",children:["Job controller stopped.",(0,r.jsx)("br",{}),"Restart to check status."]}),(0,r.jsx)(o.z,{variant:"outline",size:"sm",onClick:eg,className:"text-sky-blue hover:text-sky-blue-bright",disabled:P||ec,children:ec?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(c.Z,{size:12,className:"mr-2"}),"Restarting..."]}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(y.Z,{className:"h-4 w-4 mr-2"}),"Restart"]})})]})}),(0,r.jsx)(d.Zb,{children:(0,r.jsx)("div",{className:"overflow-x-auto rounded-lg",children:(0,r.jsxs)(u.iA,{className:"min-w-full",children:[(0,r.jsx)(u.xD,{children:(0,r.jsxs)(u.SC,{children:[(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("id"),children:["ID",eN("id")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("name"),children:["Name",eN("name")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("user"),children:["User",eN("user")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("workspace"),children:["Workspace",eN("workspace")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("submitted_at"),children:["Submitted",eN("submitted_at")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("job_duration"),children:["Duration",eN("job_duration")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("status"),children:["Status",eN("status")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("resources_str"),children:["Requested",eN("resources_str")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("infra"),children:["Infra",eN("infra")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("cluster"),children:["Resources",eN("cluster")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("recoveries"),children:["Recoveries",eN("recoveries")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>ey("pool"),children:["Worker Pool",eN("pool")]}),(0,r.jsx)(u.ss,{children:"Details"}),(0,r.jsx)(u.ss,{children:"Logs"})]})}),(0,r.jsx)(u.RM,{children:P&&U?(0,r.jsx)(u.SC,{children:(0,r.jsx)(u.pj,{colSpan:12,className:"text-center py-6 text-gray-500",children:(0,r.jsxs)("div",{className:"flex justify-center items-center",children:[(0,r.jsx)(c.Z,{size:20,className:"mr-2"}),(0,r.jsx)("span",{children:"Loading..."})]})})}):eS.length>0?(0,r.jsx)(r.Fragment,{children:eS.map(e=>(0,r.jsxs)(a.Fragment,{children:[(0,r.jsxs)(u.SC,{children:[(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/jobs/".concat(e.id),className:"text-blue-600",children:e.id})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/jobs/".concat(e.id),className:"text-blue-600",children:e.name})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(L.H,{username:e.user,userHash:e.user_hash})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/workspaces",className:"text-gray-700 hover:text-blue-600 hover:underline",children:e.workspace||"default"})}),(0,r.jsx)(u.pj,{children:T(e.submitted_at)}),(0,r.jsx)(u.pj,{children:(0,h.LU)(e.job_duration)}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(_.OE,{status:e.status})}),(0,r.jsx)(u.pj,{children:e.requested_resources}),(0,r.jsx)(u.pj,{children:e.infra&&"-"!==e.infra?(0,r.jsx)(h.Md,{content:e.full_infra||e.infra,className:"text-sm text-muted-foreground",children:(0,r.jsxs)("span",{children:[(0,r.jsx)(i(),{href:"/infra",className:"text-blue-600 hover:underline",children:e.cloud||e.infra.split("(")[0].trim()}),e.infra.includes("(")&&(0,r.jsx)("span",{children:" "+(()=>{let s=x.MO.NAME_TRUNCATE_LENGTH,t=e.infra.substring(e.infra.indexOf("(")),r=t.substring(1,t.length-1);if(r.length<=s)return t;let a="".concat(r.substring(0,Math.floor((s-3)/2)),"...").concat(r.substring(r.length-Math.ceil((s-3)/2)));return"(".concat(a,")")})()})]})}):(0,r.jsx)("span",{children:e.infra||"-"})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(h.Md,{content:e.resources_str_full||e.resources_str,className:"text-sm text-muted-foreground",children:(0,r.jsx)("span",{children:e.resources_str})})}),(0,r.jsx)(u.pj,{children:e.recoveries}),(0,r.jsx)(u.pj,{children:(0,r.jsx)("div",{className:v?"blur-sm transition-all duration-300":"",children:v?"-":(0,h.os)(e.pool,e.pool_hash,b)})}),(0,r.jsx)(u.pj,{children:e.details?(0,r.jsx)(G,{text:e.details,rowId:e.id,expandedRowId:V,setExpandedRowId:Y}):"-"}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(q,{jobParent:"/jobs",jobId:e.id,managed:!0,workspace:e.workspace})})]}),V===e.id&&(0,r.jsx)(K,{text:e.details,colSpan:13,innerRef:Q})]},e.task_job_id))}):(0,r.jsx)(u.SC,{children:(0,r.jsx)(u.pj,{colSpan:13,className:"text-center py-6",children:(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-4",children:[en&&(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-2",children:[(0,r.jsx)("p",{className:"text-gray-700",children:"The managed job controller is launching. It will be ready shortly."}),(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(c.Z,{size:12,className:"mr-2"}),(0,r.jsx)("span",{className:"text-gray-500",children:"Launching..."})]})]}),!ea&&!en&&(0,r.jsx)("p",{className:"text-gray-500",children:"No active jobs"}),!ej&&ea&&(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-3 px-4",children:[(0,r.jsx)("p",{className:"text-gray-700 text-center text-sm sm:text-base max-w-md",children:"The managed job controller has been stopped. Restart to check the latest job status."}),(0,r.jsx)(o.z,{variant:"outline",size:"sm",onClick:eg,className:"text-sky-blue hover:text-sky-blue-bright",disabled:P||ec,children:ec?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(c.Z,{size:12,className:"mr-2"}),"Restarting..."]}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(y.Z,{className:"h-4 w-4 mr-2"}),"Restart Controller"]})})]})]})})})})]})})}),(0,r.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,r.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,r.jsxs)("div",{className:"relative inline-block",children:[(0,r.jsxs)("select",{value:B,onChange:e=>{H(parseInt(e.target.value,10)),Z(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,r.jsx)("option",{value:10,children:"10"}),(0,r.jsx)("option",{value:30,children:"30"}),(0,r.jsx)("option",{value:50,children:"50"}),(0,r.jsx)("option",{value:100,children:"100"}),(0,r.jsx)("option",{value:200,children:"200"})]}),(0,r.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,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,r.jsx)("div",{children:R>0?"".concat(e_+1," – ").concat(eE," of ").concat(R):"0 – 0 of 0"}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{Z(e=>Math.max(e-1,1))},disabled:1===O||!eS||0===eS.length,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.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,r.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{eL>0&&O<eL&&Z(e=>e+1)},disabled:0===eL||O>=eL||!eS||0===eS.length,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.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,r.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})}),(0,r.jsx)(C.cV,{isOpen:em.isOpen,onClose:()=>ep({...em,isOpen:!1}),onConfirm:em.onConfirm,title:em.title,message:em.message,confirmClassName:"bg-blue-600 hover:bg-blue-700 text-white"})]})}function q(e){let{withLabel:s=!1,jobParent:t,jobId:a,managed:n,workspace:i="default"}=e,c=(0,l.useRouter)(),o=(e,s)=>{e.preventDefault(),e.stopPropagation(),c.push({pathname:"".concat(t,"/").concat(a),query:{tab:s}})},d=function(e){let s=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(e.preventDefault(),e.stopPropagation(),n)(0,m.jh)({jobId:parseInt(a),controller:s});else{let e=t.match(/\/clusters\/(.+)/);if(e){let s=e[1];(0,g.GH)({clusterName:s,jobIds:[a],workspace:i})}}};return(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(h.WH,{content:"View Job Logs",className:"capitalize text-sm text-muted-foreground",children:(0,r.jsxs)("button",{onClick:e=>o(e,"logs"),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center h-8",children:[(0,r.jsx)(N.Z,{className:"w-4 h-4"}),s&&(0,r.jsx)("span",{className:"ml-1.5",children:"Logs"})]})},"logs"),(0,r.jsx)(h.WH,{content:"Download Job Logs",className:"capitalize text-sm text-muted-foreground",children:(0,r.jsxs)("button",{onClick:e=>d(e,!1),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center h-8",children:[(0,r.jsx)(k.Z,{className:"w-4 h-4"}),s&&(0,r.jsx)("span",{className:"ml-1.5",children:"Download"})]})},"downloadlogs")]})}function H(e){let{clusterName:s,clusterJobData:t,loading:l,refreshClusterJobsOnly:n,userFilter:x=null,nameFilter:m=null,workspace:p="default"}=e,[j,f]=(0,a.useState)(null),[g,b]=(0,a.useState)({key:null,direction:"ascending"}),[v,y]=(0,a.useState)(1),[N,k]=(0,a.useState)(10),C=(0,a.useRef)(null),[S,E]=(0,a.useState)(null);(0,a.useEffect)(()=>{let e=e=>{j&&C.current&&!C.current.contains(e.target)&&f(null)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[j]);let R=a.useMemo(()=>{let e=t||[];return x&&"ALL_USERS"!==x&&(e=W(e,x)),m&&(e=J(e,m)),e},[t,x,m]);(0,a.useEffect)(()=>{JSON.stringify(t)!==JSON.stringify(S)&&E(t)},[t,S]);let D=a.useMemo(()=>g.key?[...R].sort((e,s)=>e[g.key]<s[g.key]?"ascending"===g.direction?-1:1:e[g.key]>s[g.key]?"ascending"===g.direction?1:-1:0):R,[R,g]),F=e=>{let s="ascending";g.key===e&&"ascending"===g.direction&&(s="descending"),b({key:e,direction:s})},M=e=>g.key===e?"ascending"===g.direction?" ↑":" ↓":"",I=Math.ceil(D.length/N),A=(v-1)*N,z=A+N,P=D.slice(A,z);return(0,r.jsxs)("div",{className:"relative",children:[(0,r.jsxs)(d.Zb,{children:[(0,r.jsxs)("div",{className:"flex items-center justify-between p-4",children:[(0,r.jsx)("h3",{className:"text-lg font-semibold",children:"Cluster Jobs"}),(0,r.jsx)("div",{className:"flex items-center",children:n&&(0,r.jsxs)("button",{onClick:n,disabled:l,className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center text-sm ml-2",children:[(0,r.jsx)(w.Z,{className:"w-4 h-4 mr-1"}),"Refresh Jobs"]})})]}),(0,r.jsxs)(u.iA,{children:[(0,r.jsx)(u.xD,{children:(0,r.jsxs)(u.SC,{children:[(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("id"),children:["ID",M("id")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("job"),children:["Name",M("job")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("user"),children:["User",M("user")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("workspace"),children:["Workspace",M("workspace")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("submitted_at"),children:["Submitted",M("submitted_at")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("job_duration"),children:["Duration",M("job_duration")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("status"),children:["Status",M("status")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap",onClick:()=>F("resources"),children:["Resources",M("resources")]}),(0,r.jsx)(u.ss,{className:"whitespace-nowrap",children:"Logs"})]})}),(0,r.jsx)(u.RM,{children:l?(0,r.jsx)(u.SC,{children:(0,r.jsx)(u.pj,{colSpan:9,className:"text-center py-12 text-gray-500",children:(0,r.jsxs)("div",{className:"flex justify-center items-center",children:[(0,r.jsx)(c.Z,{size:24,className:"mr-2"}),(0,r.jsx)("span",{children:"Loading cluster jobs..."})]})})}):P.length>0?P.map(e=>(0,r.jsxs)(a.Fragment,{children:[(0,r.jsxs)(u.SC,{className:j===e.id?"selected-row":"",children:[(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/clusters/".concat(s,"/").concat(e.id),className:"text-blue-600",children:e.id})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/clusters/".concat(s,"/").concat(e.id),className:"text-blue-600",children:(0,r.jsx)(G,{text:e.job||"Unnamed job",rowId:e.id,expandedRowId:j,setExpandedRowId:f})})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(L.H,{username:e.user,userHash:e.user_hash})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/workspaces",className:"text-gray-700 hover:text-blue-600 hover:underline",children:e.workspace||"default"})}),(0,r.jsx)(u.pj,{children:T(e.submitted_at)}),(0,r.jsx)(u.pj,{children:(0,h.LU)(e.job_duration)}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(_.OE,{status:e.status})}),(0,r.jsx)(u.pj,{children:e.resources}),(0,r.jsx)(u.pj,{className:"flex content-center items-center",children:(0,r.jsx)(q,{jobParent:"/clusters/".concat(s),jobId:e.id,managed:!1,workspace:p})})]}),j===e.id&&(0,r.jsx)(K,{text:e.job||"Unnamed job",colSpan:9,innerRef:C})]},e.id)):(0,r.jsx)(u.SC,{children:(0,r.jsx)(u.pj,{colSpan:8,className:"text-center py-6 text-gray-500",children:"No jobs found"})})})]})]}),D&&D.length>0&&(0,r.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,r.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,r.jsxs)("div",{className:"relative inline-block",children:[(0,r.jsxs)("select",{value:N,onChange:e=>{k(parseInt(e.target.value,10)),y(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,r.jsx)("option",{value:5,children:"5"}),(0,r.jsx)("option",{value:10,children:"10"}),(0,r.jsx)("option",{value:20,children:"20"}),(0,r.jsx)("option",{value:50,children:"50"})]}),(0,r.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,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,r.jsxs)("div",{children:[A+1," – ",Math.min(z,D.length)," of"," ",D.length]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{y(e=>Math.max(e-1,1))},disabled:1===v,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.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,r.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{y(e=>Math.min(e+1,I))},disabled:v===I||0===I,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.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,r.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})})]})}function K(e){let{text:s,colSpan:t,innerRef:a}=e;return(0,r.jsx)(u.SC,{className:"expanded-details",children:(0,r.jsx)(u.pj,{colSpan:t,children:(0,r.jsx)("div",{className:"p-4 bg-gray-50 rounded-md border border-gray-200",ref:a,children:(0,r.jsx)("div",{className:"flex justify-between items-start",children:(0,r.jsxs)("div",{className:"flex-1",children:[(0,r.jsx)("p",{className:"text-sm font-medium text-gray-900",children:"Full Details"}),(0,r.jsx)("p",{className:"mt-1 text-sm text-gray-700",style:{whiteSpace:"pre-wrap"},children:s})]})})})})})}function G(e){let{text:s,rowId:t,expandedRowId:l,setExpandedRowId:n}=e,i=s||"",c=i.length>50,o=l===t,d=c?"".concat(i.substring(0,50)):i,u=(0,a.useRef)(null);return(0,r.jsxs)("div",{className:"truncated-details relative max-w-full flex items-center",children:[(0,r.jsx)("span",{className:"truncate",children:d}),c&&(0,r.jsx)("button",{ref:u,type:"button",onClick:e=>{e.preventDefault(),e.stopPropagation(),n(o?null:t)},className:"text-blue-600 hover:text-blue-800 font-medium ml-1 flex-shrink-0","data-button-type":"show-more-less",children:o?"... show less":"... show more"})]})}function V(e){let{refreshInterval:s,setLoading:t,refreshDataRef:l}=e,[n,o]=(0,a.useState)([]),[x,j]=(0,a.useState)({key:null,direction:"ascending"}),[f,g]=(0,a.useState)(!1),[b,v]=(0,a.useState)(!0),[w,y]=(0,a.useState)(1),[N,k]=(0,a.useState)(10),C=a.useCallback(async()=>{g(!0),t(!0);try{let{pools:e=[]}=await p.default.get(m.vs,[{}])||{};o(e),v(!1)}catch(e){console.error("Error fetching pools data:",e),o([]),v(!1)}finally{g(!1),t(!1)}},[t]);a.useEffect(()=>{l&&(l.current=C)},[l,C]),(0,a.useEffect)(()=>{o([]);let e=!0;C();let t=setInterval(()=>{e&&C()},s);return()=>{e=!1,clearInterval(t)}},[s,C]);let S=e=>{let s="ascending";x.key===e&&"ascending"===x.direction&&(s="descending"),j({key:e,direction:s})},L=e=>x.key===e?"ascending"===x.direction?" ↑":" ↓":"",E=a.useMemo(()=>x.key?[...n].sort((e,s)=>e[x.key]<s[x.key]?"ascending"===x.direction?-1:1:e[x.key]>s[x.key]?"ascending"===x.direction?1:-1:0):n,[n,x]),R=Math.ceil(E.length/N),D=(w-1)*N,F=D+N,M=E.slice(D,F),I=e=>{if(!e||!e.replica_info||0===e.replica_info.length)return"0 (target: 0)";let s=e.replica_info.filter(e=>"READY"===e.status).length,t=e.target_num_replicas||0;return"".concat(s," (target: ").concat(t,")")},A=e=>{let{jobCounts:s}=e;return(0,r.jsx)(h.x9,{jobCounts:s,getStatusStyle:_.Cl})},z=e=>{let{replicaInfo:s}=e;return(0,r.jsx)(h.Kl,{replicaInfo:s})};return(0,r.jsxs)(d.Zb,{children:[(0,r.jsx)("div",{className:"overflow-x-auto rounded-lg",children:(0,r.jsxs)(u.iA,{className:"min-w-full table-fixed",children:[(0,r.jsx)(u.xD,{children:(0,r.jsxs)(u.SC,{children:[(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap w-32",onClick:()=>S("name"),children:["Pool",L("name")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap w-40",onClick:()=>S("job_counts"),children:["Jobs",L("job_counts")]}),(0,r.jsx)(u.ss,{className:"whitespace-nowrap w-20",children:"Workers"}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap w-36",onClick:()=>S("requested_resources_str"),children:["Worker Details",L("requested_resources_str")]}),(0,r.jsxs)(u.ss,{className:"sortable whitespace-nowrap w-40",onClick:()=>S("requested_resources_str"),children:["Worker Resources",L("requested_resources_str")]})]})}),(0,r.jsx)(u.RM,{children:f&&b?(0,r.jsx)(u.SC,{children:(0,r.jsx)(u.pj,{colSpan:5,className:"text-center py-6 text-gray-500",children:(0,r.jsxs)("div",{className:"flex justify-center items-center",children:[(0,r.jsx)(c.Z,{size:20,className:"mr-2"}),(0,r.jsx)("span",{children:"Loading..."})]})})}):M.length>0?M.map(e=>(0,r.jsxs)(u.SC,{children:[(0,r.jsx)(u.pj,{children:(0,r.jsx)(i(),{href:"/jobs/pools/".concat(e.name),className:"text-blue-600 hover:text-blue-800",children:e.name})}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(A,{jobCounts:e.jobCounts})}),(0,r.jsx)(u.pj,{children:I(e)}),(0,r.jsx)(u.pj,{children:(0,r.jsx)(z,{replicaInfo:e.replica_info})}),(0,r.jsx)(u.pj,{children:e.requested_resources_str||"-"})]},e.name)):(0,r.jsx)(u.SC,{children:(0,r.jsx)(u.pj,{colSpan:5,className:"text-center py-6 text-gray-500",children:"No pools found"})})})]})}),M.length>0&&R>1&&(0,r.jsxs)("div",{className:"flex items-center justify-between px-4 py-3 border-t border-gray-200",children:[(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)("span",{className:"text-sm text-gray-700",children:"Rows per page:"}),(0,r.jsxs)("select",{value:N,onChange:e=>{k(parseInt(e.target.value,10)),y(1)},className:"border border-gray-300 rounded px-2 py-1 text-sm",children:[(0,r.jsx)("option",{value:5,children:"5"}),(0,r.jsx)("option",{value:10,children:"10"}),(0,r.jsx)("option",{value:25,children:"25"}),(0,r.jsx)("option",{value:50,children:"50"})]})]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsxs)("span",{className:"text-sm text-gray-700",children:[D+1,"-",Math.min(F,E.length)," of"," ",E.length]}),(0,r.jsx)("button",{onClick:()=>{y(e=>Math.max(e-1,1))},disabled:1===w,className:"px-2 py-1 text-sm border border-gray-300 rounded disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50",children:"Previous"}),(0,r.jsx)("button",{onClick:()=>{y(e=>Math.min(e+1,R))},disabled:w===R,className:"px-2 py-1 text-sm border border-gray-300 rounded disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50",children:"Next"})]})]})]})}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8969],{68969:function(e,t,o){o.d(t,{Ce:function(){return p},NJ:function(){return h},UA:function(){return u},aT:function(){return l},getManagedJobs:function(){return i},jh:function(){return g},vs:function(){return d}});var r=o(67294),a=o(15821),n=o(93225),s=o(6378),c=o(47145);async function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{var t;let{allUsers:o=!0,skipFinished:r=!1,nameMatch:a,userMatch:s,workspaceMatch:i,poolMatch:l,page:d,limit:u,statuses:h}=e,p={all_users:o,verbose:!0,skip_finished:r};void 0!==a&&(p.name_match=a),void 0!==s&&(p.user_match=s),void 0!==i&&(p.workspace_match=i),void 0!==l&&(p.pool_match=l),void 0!==d&&(p.page=d),void 0!==u&&(p.limit=u),void 0!==h&&h.length>0&&(p.statuses=h);let g=(await c.x.post("/jobs/queue/v2",p)).headers.get("X-Skypilot-Request-ID"),b=await c.x.get("/api/get?request_id=".concat(g));if(500===b.status){try{let e=await b.json();if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);if(t.type&&t.type===n.iW)return{jobs:[],total:0,controllerStopped:!0}}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{jobs:[],total:0,controllerStopped:!1}}let f=await b.json(),m=f.return_value?JSON.parse(f.return_value):[],_=Array.isArray(m)?m:(null==m?void 0:m.jobs)||[],y=Array.isArray(m)?_.length:null!==(t=null==m?void 0:m.total)&&void 0!==t?t:_.length,w=(null==m?void 0:m.total_no_filter)||y,j=(null==m?void 0:m.status_counts)||{};return{jobs:_.map(e=>{var t;let o=0;e.end_at&&e.submitted_at?o=e.end_at-e.submitted_at:e.submitted_at&&(o=Date.now()/1e3-e.submitted_at);let r=[];e.submitted_at&&r.push({type:"PENDING",timestamp:e.submitted_at}),e.start_at&&r.push({type:"RUNNING",timestamp:e.start_at}),e.end_at&&r.push({type:e.status,timestamp:e.end_at});let a="",n="",s="",c="",i="";try{if(a=e.cloud||"",s=e.cluster_resources,n=e.region||"",a&&(c=a,n&&(c+="/".concat(n))),i=c,e.accelerators){let t=Object.entries(e.accelerators).map(e=>{let[t,o]=e;return"".concat(o,"x").concat(t)}).join(", ");t&&(i+=" (".concat(t,")"))}}catch(t){s=e.cluster_resources}return{id:e.job_id,task_job_id:e._job_id,task:e.task_name,name:e.job_name,job_duration:e.job_duration,total_duration:o,workspace:e.workspace,status:e.status,requested_resources:e.resources,resources_str:s,resources_str_full:e.cluster_resources_full||s,cloud:a,region:e.region,infra:c,full_infra:i,recoveries:e.recovery_count,details:e.details||e.failure_reason,user:e.user_name,user_hash:e.user_hash,submitted_at:e.submitted_at?new Date(1e3*e.submitted_at):null,events:r,dag_yaml:e.user_yaml,entrypoint:e.entrypoint,git_commit:(null===(t=e.metadata)||void 0===t?void 0:t.git_commit)||"-",pool:e.pool,pool_hash:e.pool_hash,current_cluster_name:e.current_cluster_name,job_id_on_pool_cluster:e.job_id_on_pool_cluster}}),total:y,totalNoFilter:w,controllerStopped:!1,statusCounts:j}}catch(e){return console.error("Error fetching managed job data:",e),{jobs:[],total:0,totalNoFilter:0,controllerStopped:!1,statusCounts:{}}}}async function l(e){let{allUsers:t=!0,nameMatch:o,userMatch:r,workspaceMatch:a,poolMatch:n,page:s=1,limit:c=10,useClientPagination:l=!0}=e||{};try{if(!l)return await i(e);let d=await i({allUsers:t,nameMatch:o,userMatch:r,workspaceMatch:a,poolMatch:n});if(d.controllerStopped||!d.jobs)return d;let u=d.jobs,h=u.length,p=(s-1)*c;return{jobs:u.slice(p,p+c),total:h,controllerStopped:!1}}catch(e){return console.error("Error fetching managed job data with client pagination:",e),{jobs:[],total:0,controllerStopped:!1}}}async function d(){try{let e=(await c.x.post("/jobs/pool_status",{pool_names:null})).headers.get("X-Skypilot-Request-ID"),t=await c.x.get("/api/get?request_id=".concat(e));if(500===t.status){try{let e=await t.json();if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);if(t.type&&t.type===n.iW)return{pools:[],controllerStopped:!0}}catch(e){console.error("Failed to parse error JSON:",e)}}catch(e){console.error("Failed to parse response JSON:",e)}throw Error("Server error")}let o=await t.json(),r=o.return_value?JSON.parse(o.return_value):[],a={jobs:[]};try{let e=await i({allUsers:!0,skipFinished:!0});e.controllerStopped||(a=e)}catch(e){console.warn("Failed to fetch jobs for pool job counts:",e)}let s={},l=["SUCCEEDED","FAILED","FAILED_SETUP","FAILED_PRECHECKS","FAILED_NO_RESOURCE","FAILED_CONTROLLER","CANCELLED"];return a.jobs&&Array.isArray(a.jobs)&&a.jobs.forEach(e=>{let t=e.pool,o=e.status;t&&!l.includes(o)&&(s[t]||(s[t]={}),s[t][o]=(s[t][o]||0)+1)}),{pools:r.map(e=>({...e,jobCounts:s[e.name]||{}})),controllerStopped:!1}}catch(e){throw console.error("Error fetching pools:",e),e}}function u(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,[o,a]=(0,r.useState)(null),[n,c]=(0,r.useState)(!0);return(0,r.useEffect)(()=>{(async function(){if(e)try{var t;c(!0);let o=await s.default.get(i,[{allUsers:!0}]),r=null==o?void 0:null===(t=o.jobs)||void 0===t?void 0:t.find(t=>String(t.id)===String(e));r?a({jobs:[r],controllerStopped:o.controllerStopped||!1}):a({jobs:[],controllerStopped:o.controllerStopped||!1})}catch(e){console.error("Error fetching single managed job data:",e),a({jobs:[],controllerStopped:!1})}finally{c(!1)}})()},[e,t]),{jobData:o,loading:n}}async function h(e){let t,{jobId:o,controller:r=!1,signal:s,onNewLog:c}=e,i=Date.now(),l=new Promise(e=>{let o=()=>{let r=Date.now()-i;r>=3e4?e({timeout:!0}):t=setTimeout(o,3e4-r)};t=setTimeout(o,3e4)}),d=window.location.origin,u="".concat(d).concat(n.f4),h=(async()=>{try{let e=(await fetch("".concat(u,"/jobs/logs"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({controller:r,follow:!1,job_id:o,tail:1e4}),...s?{signal:s}:{}})).body.getReader();try{for(;;){let{done:t,value:o}=await e.read();if(t)break;i=Date.now();let r=new TextDecoder().decode(o);c(r)}}finally{if(!s||!s.aborted)try{e.cancel()}catch(e){"AbortError"!==e.name&&console.warn("Error canceling reader:",e)}t&&clearTimeout(t)}return{timeout:!1}}catch(e){if(t&&clearTimeout(t),"AbortError"===e.name)return{timeout:!1};throw e}})(),p=await Promise.race([h,l]);if(t&&clearTimeout(t),p.timeout){(0,a.C)("Log request for job ".concat(o," timed out after ").concat(30,"s of inactivity"),"warning");return}}async function p(e,t,o){let r="",s="",c="",i={};if("restartcontroller"===e)r="Restarting",s="restarted",c="jobs/queue/v2",i={all_users:!0,refresh:!0},t="controller";else throw Error("Invalid action: ".concat(e));(0,a.C)("".concat(r," job ").concat(t,"..."),"info");let l=window.location.origin,d="".concat(l).concat(n.f4);try{try{let e=(await fetch("".concat(d,"/").concat(c),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)})).headers.get("X-Skypilot-Request-ID"),l=await fetch("".concat(d,"/api/get?request_id=").concat(e));if(200===l.status)(0,a.C)("Job ".concat(t," ").concat(s," successfully."),"success");else if(500===l.status)try{let e=await l.json();if(e.detail&&e.detail.error)try{let s=JSON.parse(e.detail.error);s.type&&s.type===n.Bo?(0,a.C)("".concat(r," job ").concat(t," is not supported!"),"error",1e4):s.type&&s.type===n.mF?(0,a.C)("Cluster ".concat(o," does not exist."),"error"):s.type&&s.type===n.iW?(0,a.C)("Cluster ".concat(o," is not up."),"error"):(0,a.C)("".concat(r," job ").concat(t," failed: ").concat(s.type),"error")}catch(o){(0,a.C)("".concat(r," job ").concat(t," failed: ").concat(e.detail.error),"error")}else(0,a.C)("".concat(r," job ").concat(t," failed with no details."),"error")}catch(e){(0,a.C)("".concat(r," job ").concat(t," failed with parse error."),"error")}else(0,a.C)("".concat(r," job ").concat(t," failed with status ").concat(l.status,"."),"error")}catch(e){console.error("Fetch error:",e),(0,a.C)("Network error ".concat(r," job ").concat(t,": ").concat(e.message),"error")}}catch(e){console.error("Error in handleStop:",e),(0,a.C)("Critical error ".concat(r," job ").concat(t,": ").concat(e.message),"error")}}async function g(e){let{jobId:t=null,name:o=null,controller:r=!1}=e;try{let e=await c.x.fetch("/jobs/download_logs",{job_id:t,name:o,controller:r,refresh:!1}),s=Object.values(e||{});if(!s.length){(0,a.C)("No logs found to download.","warning");return}let i=window.location.origin,l="".concat(i).concat(n.f4,"/download"),d=await fetch("".concat(l,"?relative=items"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({folder_paths:s})});if(!d.ok){let e=await d.text();throw Error("Download failed: ".concat(d.status," ").concat(e))}let u=await d.blob(),h=window.URL.createObjectURL(u),p=document.createElement("a"),g=new Date().toISOString().replace(/[:.]/g,"-"),b=t?"job-".concat(t):o?"job-".concat(o):"job";p.href=h,p.download="managed-".concat(b,"-").concat(r?"controller-logs":"logs","-").concat(g,".zip"),document.body.appendChild(p),p.click(),p.remove(),window.URL.revokeObjectURL(h)}catch(e){console.error("Error downloading managed job logs:",e),(0,a.C)("Error downloading managed job logs: ".concat(e.message),"error")}}},15821:function(e,t,o){o.d(t,{C:function(){return r}});function r(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"info",o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:5e3,r=document.getElementById("toast-container");r||((r=document.createElement("div")).id="toast-container",r.className="fixed top-0 right-0 p-4 z-[9999] flex flex-col items-end space-y-2",document.body.appendChild(r));let a=document.createElement("div");switch(a.className="rounded-md border-l-4 p-4 shadow-md flex items-center justify-between max-w-md w-full mb-2 pointer-events-auto",t){case"success":a.className+=" bg-green-100 border-green-500 text-green-800";break;case"error":a.className+=" bg-red-100 border-red-500 text-red-800";break;case"warning":a.className+=" bg-yellow-100 border-yellow-500 text-yellow-800";break;default:a.className+=" bg-blue-100 border-blue-500 text-blue-800"}return a.innerHTML='\n <div class="flex-1 mr-2">\n <p class="text-sm font-medium">'.concat(e,'</p>\n </div>\n <button class="text-gray-500 hover:text-gray-700 focus:outline-none" aria-label="Close toast">\n <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n '),r.appendChild(a),a.querySelector("button").addEventListener("click",()=>{r.removeChild(a)}),setTimeout(()=>{r.contains(a)&&r.removeChild(a)},o),a}},6378:function(e,t,o){o.r(t),o.d(t,{DashboardCache:function(){return n},dashboardCache:function(){return s}});let r=o(51214).ej.DEFAULT_TTL;function a(e){let t=5381;for(let o=0;o<e.length;o++)t=(t<<5)+t+e.charCodeAt(o);return t>>>0}class n{setPreloader(e){this.preloader=e}async get(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},a=o.ttl||r,n=!1!==o.refreshOnAccess,s=this._generateKey(e,t),c=e.name||"anonymous",i=this.cache.get(s),l=Date.now();if(i&&l-i.lastUpdated<a){let o=Math.round((l-i.lastUpdated)/1e3);if(this._debug("Cache HIT for ".concat(c," (age: ").concat(o,"s, TTL: ").concat(Math.round(a/1e3),"s)")),n&&(this.cache.set(s,{data:i.data,lastUpdated:l}),this._debug("Cache TTL refreshed for ".concat(c))),!this.backgroundJobs.has(s)){var d;(null===(d=this.preloader)||void 0===d?void 0:d.wasRecentlyPreloaded(e,t))?this._debug("Skipping background refresh for ".concat(c," - recently preloaded")):this._refreshInBackground(e,t,s)}return i.data}if(this.pendingRequests.has(s))return this._debug("Request deduplication: Waiting for pending request for ".concat(c)),this.pendingRequests.get(s);let u=(async()=>{try{let o=await e(...t);return this.cache.set(s,{data:o,lastUpdated:Date.now()}),o}catch(e){if(i)return console.warn("Failed to fetch fresh data for ".concat(s,", returning stale data:"),e),i.data;throw e}finally{this.pendingRequests.delete(s)}})();return this.pendingRequests.set(s,u),u}invalidate(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],o=this._generateKey(e,t);this.cache.delete(o),this.backgroundJobs.delete(o),this.pendingRequests.delete(o)}invalidateFunction(e){let t=a(e.toString()),o=[];for(let e of this.cache.keys())e.startsWith("".concat(t,"_"))&&o.push(e);o.forEach(e=>{this.cache.delete(e),this.backgroundJobs.delete(e),this.pendingRequests.delete(e)})}clear(){this.cache.clear(),this.backgroundJobs.clear(),this.pendingRequests.clear()}getStats(){return{cacheSize:this.cache.size,backgroundJobs:this.backgroundJobs.size,pendingRequests:this.pendingRequests.size,keys:Array.from(this.cache.keys())}}getDetailedStats(){let e=Date.now(),t=[];for(let[o,r]of this.cache.entries()){let a=e-r.lastUpdated;t.push({key:o,age:Math.round(a/1e3),lastUpdated:new Date(r.lastUpdated).toISOString(),hasBackgroundJob:this.backgroundJobs.has(o),hasPendingRequest:this.pendingRequests.has(o)})}return{cacheSize:this.cache.size,backgroundJobs:this.backgroundJobs.size,pendingRequests:this.pendingRequests.size,entries:t.sort((e,t)=>e.age-t.age)}}setDebugMode(e){this.debugMode=e}_debug(e){for(var t=arguments.length,o=Array(t>1?t-1:0),r=1;r<t;r++)o[r-1]=arguments[r];this.debugMode&&console.log("[DashboardCache] ".concat(e),...o)}_refreshInBackground(e,t,o){this.backgroundJobs.set(o,!0),e(...t).then(e=>{this.cache.set(o,{data:e,lastUpdated:Date.now()})}).catch(e=>{console.warn("Background refresh failed for ".concat(o,":"),e)}).finally(()=>{this.backgroundJobs.delete(o)})}_generateKey(e,t){let o=a(e.toString()),r=t.length>0?JSON.stringify(t):"";return"".concat(o,"_").concat(r)}constructor(){this.cache=new Map,this.backgroundJobs=new Map,this.pendingRequests=new Map,this.debugMode=!1,this.preloader=null}}let s=new n;t.default=s}}]);