skypilot-nightly 1.0.0.dev20250527__py3-none-any.whl → 1.0.0.dev20250529__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 (93) hide show
  1. sky/__init__.py +2 -2
  2. sky/adaptors/kubernetes.py +13 -1
  3. sky/backends/cloud_vm_ray_backend.py +2 -2
  4. sky/check.py +4 -1
  5. sky/cli.py +13 -3
  6. sky/client/cli.py +13 -3
  7. sky/client/oauth.py +82 -0
  8. sky/client/sdk.py +60 -10
  9. sky/clouds/kubernetes.py +2 -2
  10. sky/clouds/service_catalog/data_fetchers/fetch_gcp.py +3 -3
  11. sky/dashboard/out/404.html +1 -1
  12. sky/dashboard/out/_next/static/HvNkg7hqKM1p0ptAcdDcF/_buildManifest.js +1 -0
  13. sky/dashboard/out/_next/static/chunks/121-8f55ee3fa6301784.js +20 -0
  14. sky/dashboard/out/_next/static/chunks/{573-82bd40a37af834f1.js → 173-7db8607cefc20f70.js} +5 -5
  15. sky/dashboard/out/_next/static/chunks/236-90e5498a5b00ec29.js +6 -0
  16. sky/dashboard/out/_next/static/chunks/293-351268365226d251.js +1 -0
  17. sky/dashboard/out/_next/static/chunks/303-2c7b0f7af571710b.js +6 -0
  18. sky/dashboard/out/_next/static/chunks/470-4d003c441839094d.js +1 -0
  19. sky/dashboard/out/_next/static/chunks/578-9146658cead92981.js +6 -0
  20. sky/dashboard/out/_next/static/chunks/843-256ec920f6d5f41f.js +11 -0
  21. sky/dashboard/out/_next/static/chunks/856-59a1760784c9e770.js +1 -0
  22. sky/dashboard/out/_next/static/chunks/973-1a09cac61cfcc1e1.js +1 -0
  23. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-159bffb2fa34ed54.js +6 -0
  24. sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-e23fcddf60578a0d.js → [cluster]-9506c00257d10dbd.js} +1 -1
  25. sky/dashboard/out/_next/static/chunks/pages/{clusters-8afda8efa5b74997.js → clusters-943992b84fd6f4ee.js} +1 -1
  26. sky/dashboard/out/_next/static/chunks/pages/config-7c48919fe030bc43.js +6 -0
  27. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-909f1ceb0fcf1b99.js +1 -0
  28. sky/dashboard/out/_next/static/chunks/pages/infra-d4c6875c88771e17.js +1 -0
  29. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-6b80e9e0c6aa16a1.js +6 -0
  30. sky/dashboard/out/_next/static/chunks/pages/{jobs-ff7e8e377d02b651.js → jobs-a4efc09e61988f8d.js} +1 -1
  31. sky/dashboard/out/_next/static/chunks/pages/users-b2634885d67c49a6.js +6 -0
  32. sky/dashboard/out/_next/static/chunks/pages/workspace/{new-63763ffa3edb4508.js → new-579b3203c7c19d84.js} +1 -1
  33. sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-3ede7a13caf23375.js → [name]-9388e38fac73ee8f.js} +1 -1
  34. sky/dashboard/out/_next/static/chunks/pages/workspaces-610c49ae3619ee85.js +1 -0
  35. sky/dashboard/out/_next/static/css/ffd1cd601648c303.css +3 -0
  36. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  37. sky/dashboard/out/clusters/[cluster].html +1 -1
  38. sky/dashboard/out/clusters.html +1 -1
  39. sky/dashboard/out/config.html +1 -1
  40. sky/dashboard/out/index.html +1 -1
  41. sky/dashboard/out/infra/[context].html +1 -0
  42. sky/dashboard/out/infra.html +1 -1
  43. sky/dashboard/out/jobs/[job].html +1 -1
  44. sky/dashboard/out/jobs.html +1 -1
  45. sky/dashboard/out/users.html +1 -1
  46. sky/dashboard/out/workspace/new.html +1 -1
  47. sky/dashboard/out/workspaces/[name].html +1 -1
  48. sky/dashboard/out/workspaces.html +1 -1
  49. sky/exceptions.py +1 -1
  50. sky/global_user_state.py +181 -134
  51. sky/jobs/client/sdk.py +1 -0
  52. sky/jobs/constants.py +2 -0
  53. sky/jobs/controller.py +3 -5
  54. sky/jobs/recovery_strategy.py +148 -102
  55. sky/jobs/scheduler.py +23 -8
  56. sky/jobs/server/core.py +16 -0
  57. sky/jobs/state.py +130 -35
  58. sky/jobs/utils.py +30 -4
  59. sky/provision/kubernetes/utils.py +4 -4
  60. sky/resources.py +16 -1
  61. sky/server/common.py +6 -2
  62. sky/server/html/token_page.html +32 -6
  63. sky/server/server.py +9 -6
  64. sky/setup_files/dependencies.py +8 -1
  65. sky/skylet/constants.py +5 -1
  66. sky/task.py +26 -0
  67. sky/templates/jobs-controller.yaml.j2 +2 -1
  68. sky/utils/db_utils.py +34 -46
  69. sky/utils/schemas.py +12 -0
  70. sky/utils/subprocess_utils.py +2 -3
  71. {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/METADATA +4 -1
  72. {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/RECORD +78 -73
  73. sky/dashboard/out/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_buildManifest.js +0 -1
  74. sky/dashboard/out/_next/static/chunks/236-e220ba0c35bf089e.js +0 -6
  75. sky/dashboard/out/_next/static/chunks/470-1d784f5c8750744a.js +0 -1
  76. sky/dashboard/out/_next/static/chunks/488-50d843fdb5396d32.js +0 -15
  77. sky/dashboard/out/_next/static/chunks/578-24f35aa98d38d638.js +0 -6
  78. sky/dashboard/out/_next/static/chunks/627-31b701e69f52db0c.js +0 -1
  79. sky/dashboard/out/_next/static/chunks/843-e35d71cf1c7f706e.js +0 -11
  80. sky/dashboard/out/_next/static/chunks/990-f85643b521f7ca65.js +0 -1
  81. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-339b59921ccfe266.js +0 -1
  82. sky/dashboard/out/_next/static/chunks/pages/config-72b8c6c2edfd0e39.js +0 -6
  83. sky/dashboard/out/_next/static/chunks/pages/infra-1521baab6992916b.js +0 -1
  84. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-4d913940b4fa6f5a.js +0 -1
  85. sky/dashboard/out/_next/static/chunks/pages/users-9900af52acf8648d.js +0 -1
  86. sky/dashboard/out/_next/static/chunks/pages/workspaces-72330c4d0fc9a4a2.js +0 -1
  87. sky/dashboard/out/_next/static/css/6a1c0d711a4bdaf1.css +0 -3
  88. /sky/dashboard/out/_next/static/{D5bjIfl4Ob3SV3LJz3CO0 → HvNkg7hqKM1p0ptAcdDcF}/_ssgManifest.js +0 -0
  89. /sky/dashboard/out/_next/static/chunks/pages/{_app-3985f074c163a856.js → _app-a631df412d8172de.js} +0 -0
  90. {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/WHEEL +0 -0
  91. {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/entry_points.txt +0 -0
  92. {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/licenses/LICENSE +0 -0
  93. {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.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 = '269ed1497f78a46da5dd05a528000da55eacf551'
8
+ _SKYPILOT_COMMIT_SHA = 'f3edb2141cf7bfea30c552e2812c14f56d7149ab'
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.dev20250527'
38
+ __version__ = '1.0.0.dev20250529'
39
39
  __root_dir__ = os.path.dirname(os.path.abspath(__file__))
40
40
 
41
41
 
@@ -66,12 +66,20 @@ def _api_logging_decorator(logger_src: str, level: int):
66
66
  return decorated_api
67
67
 
68
68
 
69
+ def _get_config_file() -> str:
70
+ # Kubernetes load the kubeconfig from the KUBECONFIG env var on
71
+ # package initialization. So we have to reload the KUBECOFNIG env var
72
+ # everytime in case the KUBECONFIG env var is changed.
73
+ return os.environ.get('KUBECONFIG', '~/.kube/config')
74
+
75
+
69
76
  def _load_config(context: Optional[str] = None):
70
77
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
71
78
 
72
79
  def _load_config_from_kubeconfig(context: Optional[str] = None):
73
80
  try:
74
- kubernetes.config.load_kube_config(context=context)
81
+ kubernetes.config.load_kube_config(config_file=_get_config_file(),
82
+ context=context)
75
83
  except kubernetes.config.config_exception.ConfigException as e:
76
84
  suffix = common_utils.format_exception(e, use_bracket=True)
77
85
  context_name = '(current-context)' if context is None else context
@@ -139,6 +147,10 @@ def _load_config(context: Optional[str] = None):
139
147
  _load_config_from_kubeconfig(context)
140
148
 
141
149
 
150
+ def list_kube_config_contexts():
151
+ return kubernetes.config.list_kube_config_contexts(_get_config_file())
152
+
153
+
142
154
  @_api_logging_decorator('urllib3', logging.ERROR)
143
155
  @annotations.lru_cache(scope='request')
144
156
  def core_api(context: Optional[str] = None):
@@ -1727,12 +1727,12 @@ class RetryingVmProvisioner(object):
1727
1727
  f'{requested_resources}. ')
1728
1728
  elif to_provision.region is not None:
1729
1729
  # For public clouds, provision.region is always set.
1730
- if to_provision.cloud.is_same_cloud(clouds.SSH()):
1730
+ if clouds.SSH().is_same_cloud(to_provision.cloud):
1731
1731
  message = ('Failed to acquire resources in SSH Node Pool '
1732
1732
  f'({to_provision.region.lstrip("ssh-")}) for '
1733
1733
  f'{requested_resources}. The SSH Node Pool may not '
1734
1734
  'have enough resources.')
1735
- elif to_provision.cloud.is_same_cloud(clouds.Kubernetes()):
1735
+ elif clouds.Kubernetes().is_same_cloud(to_provision.cloud):
1736
1736
  message = ('Failed to acquire resources in context '
1737
1737
  f'{to_provision.region} for {requested_resources}. ')
1738
1738
  else:
sky/check.py CHANGED
@@ -143,12 +143,15 @@ def check_capabilities(
143
143
  combinations = list(itertools.product(clouds_to_check, capabilities))
144
144
 
145
145
  cloud2ctx2text: Dict[str, Dict[str, str]] = {}
146
+ if not config_allowed_cloud_names:
147
+ for capability in capabilities:
148
+ global_user_state.set_enabled_clouds([], capability,
149
+ current_workspace_name)
146
150
  if not combinations:
147
151
  echo(
148
152
  _summary_message(enabled_clouds, cloud2ctx2text,
149
153
  current_workspace_name, hide_workspace_str,
150
154
  disallowed_cloud_names))
151
-
152
155
  return {}
153
156
 
154
157
  workspace_str = f' for workspace: {current_workspace_name!r}'
sky/cli.py CHANGED
@@ -862,6 +862,7 @@ def _make_task_or_dag_from_entrypoint_with_overrides(
862
862
  field_to_ignore: Optional[List[str]] = None,
863
863
  # job launch specific
864
864
  job_recovery: Optional[str] = None,
865
+ priority: Optional[int] = None,
865
866
  config_override: Optional[Dict[str, Any]] = None,
866
867
  ) -> Union[sky.Task, sky.Dag]:
867
868
  """Creates a task or a dag from an entrypoint with overrides.
@@ -939,6 +940,9 @@ def _make_task_or_dag_from_entrypoint_with_overrides(
939
940
  task.num_nodes = num_nodes
940
941
  if name is not None:
941
942
  task.name = name
943
+ # job launch specific.
944
+ if priority is not None:
945
+ task.set_job_priority(priority)
942
946
  return task
943
947
 
944
948
 
@@ -4170,6 +4174,12 @@ def jobs():
4170
4174
  default=None,
4171
4175
  type=str,
4172
4176
  help='Recovery strategy to use for managed jobs.')
4177
+ @click.option('--priority',
4178
+ type=click.IntRange(0, 1000),
4179
+ default=None,
4180
+ show_default=True,
4181
+ help=('Job priority from 0 to 1000. A lower number is higher '
4182
+ 'priority. Default is 500.'))
4173
4183
  @click.option(
4174
4184
  '--detach-run',
4175
4185
  '-d',
@@ -4207,6 +4217,7 @@ def jobs_launch(
4207
4217
  disk_size: Optional[int],
4208
4218
  disk_tier: Optional[str],
4209
4219
  ports: Tuple[str],
4220
+ priority: Optional[int],
4210
4221
  detach_run: bool,
4211
4222
  yes: bool,
4212
4223
  async_call: bool,
@@ -4253,6 +4264,7 @@ def jobs_launch(
4253
4264
  disk_tier=disk_tier,
4254
4265
  ports=ports,
4255
4266
  job_recovery=job_recovery,
4267
+ priority=priority,
4256
4268
  config_override=config_override,
4257
4269
  )
4258
4270
 
@@ -4335,8 +4347,6 @@ def jobs_queue(verbose: bool, refresh: bool, skip_finished: bool,
4335
4347
  - ``PENDING``: Job is waiting for a free slot on the jobs controller to be
4336
4348
  accepted.
4337
4349
 
4338
- - ``SUBMITTED``: Job is submitted to and accepted by the jobs controller.
4339
-
4340
4350
  - ``STARTING``: Job is starting (provisioning a cluster for the job).
4341
4351
 
4342
4352
  - ``RUNNING``: Job is running.
@@ -4553,7 +4563,7 @@ def jobs_logs(name: Optional[str], job_id: Optional[int], follow: bool,
4553
4563
  @usage_lib.entrypoint
4554
4564
  def jobs_dashboard():
4555
4565
  """Opens a dashboard for managed jobs."""
4556
- managed_jobs.dashboard()
4566
+ sdk.dashboard(starting_page='jobs')
4557
4567
 
4558
4568
 
4559
4569
  @cli.command(cls=_DocumentedCodeCommand)
sky/client/cli.py CHANGED
@@ -862,6 +862,7 @@ def _make_task_or_dag_from_entrypoint_with_overrides(
862
862
  field_to_ignore: Optional[List[str]] = None,
863
863
  # job launch specific
864
864
  job_recovery: Optional[str] = None,
865
+ priority: Optional[int] = None,
865
866
  config_override: Optional[Dict[str, Any]] = None,
866
867
  ) -> Union[sky.Task, sky.Dag]:
867
868
  """Creates a task or a dag from an entrypoint with overrides.
@@ -939,6 +940,9 @@ def _make_task_or_dag_from_entrypoint_with_overrides(
939
940
  task.num_nodes = num_nodes
940
941
  if name is not None:
941
942
  task.name = name
943
+ # job launch specific.
944
+ if priority is not None:
945
+ task.set_job_priority(priority)
942
946
  return task
943
947
 
944
948
 
@@ -4170,6 +4174,12 @@ def jobs():
4170
4174
  default=None,
4171
4175
  type=str,
4172
4176
  help='Recovery strategy to use for managed jobs.')
4177
+ @click.option('--priority',
4178
+ type=click.IntRange(0, 1000),
4179
+ default=None,
4180
+ show_default=True,
4181
+ help=('Job priority from 0 to 1000. A lower number is higher '
4182
+ 'priority. Default is 500.'))
4173
4183
  @click.option(
4174
4184
  '--detach-run',
4175
4185
  '-d',
@@ -4207,6 +4217,7 @@ def jobs_launch(
4207
4217
  disk_size: Optional[int],
4208
4218
  disk_tier: Optional[str],
4209
4219
  ports: Tuple[str],
4220
+ priority: Optional[int],
4210
4221
  detach_run: bool,
4211
4222
  yes: bool,
4212
4223
  async_call: bool,
@@ -4253,6 +4264,7 @@ def jobs_launch(
4253
4264
  disk_tier=disk_tier,
4254
4265
  ports=ports,
4255
4266
  job_recovery=job_recovery,
4267
+ priority=priority,
4256
4268
  config_override=config_override,
4257
4269
  )
4258
4270
 
@@ -4335,8 +4347,6 @@ def jobs_queue(verbose: bool, refresh: bool, skip_finished: bool,
4335
4347
  - ``PENDING``: Job is waiting for a free slot on the jobs controller to be
4336
4348
  accepted.
4337
4349
 
4338
- - ``SUBMITTED``: Job is submitted to and accepted by the jobs controller.
4339
-
4340
4350
  - ``STARTING``: Job is starting (provisioning a cluster for the job).
4341
4351
 
4342
4352
  - ``RUNNING``: Job is running.
@@ -4553,7 +4563,7 @@ def jobs_logs(name: Optional[str], job_id: Optional[int], follow: bool,
4553
4563
  @usage_lib.entrypoint
4554
4564
  def jobs_dashboard():
4555
4565
  """Opens a dashboard for managed jobs."""
4556
- managed_jobs.dashboard()
4566
+ sdk.dashboard(starting_page='jobs')
4557
4567
 
4558
4568
 
4559
4569
  @cli.command(cls=_DocumentedCodeCommand)
sky/client/oauth.py ADDED
@@ -0,0 +1,82 @@
1
+ """Client-side OAuth module."""
2
+ from http.server import BaseHTTPRequestHandler
3
+ from http.server import HTTPServer
4
+ import threading
5
+ import time
6
+ from typing import Dict, Optional
7
+
8
+ AUTH_TIMEOUT = 300 # 5 minutes
9
+
10
+
11
+ class _AuthCallbackHandler(BaseHTTPRequestHandler):
12
+ """HTTP request handler for OAuth callback."""
13
+
14
+ def __init__(self, token_container: Dict[str, Optional[str]],
15
+ remote_endpoint: str, *args, **kwargs):
16
+ self.token_container = token_container
17
+ self.remote_endpoint = remote_endpoint
18
+ super().__init__(*args, **kwargs)
19
+
20
+ def do_POST(self): # pylint: disable=invalid-name
21
+ """Handle POST request for OAuth callback."""
22
+ data = self.rfile.read(int(self.headers['Content-Length']))
23
+
24
+ if data:
25
+ token = data.decode('utf-8')
26
+ self.token_container['token'] = token
27
+
28
+ # Send success response
29
+ self.send_response(200)
30
+ self.send_header('Content-type', 'text/html')
31
+ self.send_header('Access-Control-Allow-Origin',
32
+ self.remote_endpoint)
33
+ self.end_headers()
34
+ else:
35
+ # Send error response
36
+ self.send_response(400)
37
+ self.send_header('Content-type', 'text/html')
38
+ self.send_header('Access-Control-Allow-Origin',
39
+ self.remote_endpoint)
40
+ self.end_headers()
41
+
42
+ def log_message(self, *args): # pylint: disable=unused-argument
43
+ """Suppress default HTTP server logging."""
44
+ pass
45
+
46
+
47
+ def start_local_auth_server(port: int,
48
+ token_store: Dict[str, Optional[str]],
49
+ remote_endpoint: str,
50
+ timeout: int = AUTH_TIMEOUT) -> HTTPServer:
51
+ """Start a local HTTP server to handle OAuth callback.
52
+
53
+ Args:
54
+ port: Port to bind the server to.
55
+ token_container: Dict to store the received token.
56
+ remote_endpoint: The endpoint of the SkyPilot API server that will send
57
+ the token, needed for CORS.
58
+ timeout: Timeout in seconds to wait for the callback.
59
+
60
+ Returns:
61
+ The HTTP server instance.
62
+ """
63
+
64
+ def handler_factory(*args, **kwargs):
65
+ return _AuthCallbackHandler(token_store, remote_endpoint, *args,
66
+ **kwargs)
67
+
68
+ server = HTTPServer(('localhost', port), handler_factory)
69
+ server.timeout = timeout
70
+
71
+ def serve_until_token():
72
+ """Serve requests until token is received or timeout."""
73
+ start_time = time.time()
74
+ while (token_store['token'] is None and
75
+ time.time() - start_time < timeout):
76
+ server.handle_request()
77
+
78
+ # Start server in a separate thread
79
+ server_thread = threading.Thread(target=serve_until_token, daemon=True)
80
+ server_thread.start()
81
+
82
+ return server
sky/client/sdk.py CHANGED
@@ -36,6 +36,7 @@ from sky import sky_logging
36
36
  from sky import skypilot_config
37
37
  from sky.adaptors import common as adaptors_common
38
38
  from sky.client import common as client_common
39
+ from sky.client import oauth as oauth_lib
39
40
  from sky.server import common as server_common
40
41
  from sky.server.requests import payloads
41
42
  from sky.server.requests import requests as requests_lib
@@ -341,10 +342,11 @@ def validate(
341
342
  @usage_lib.entrypoint
342
343
  @server_common.check_server_healthy_or_start
343
344
  @annotations.client_api
344
- def dashboard() -> None:
345
+ def dashboard(starting_page: Optional[str] = None) -> None:
345
346
  """Starts the dashboard for SkyPilot."""
346
347
  api_server_url = server_common.get_server_url()
347
- url = server_common.get_dashboard_url(api_server_url)
348
+ url = server_common.get_dashboard_url(api_server_url,
349
+ starting_page=starting_page)
348
350
  logger.info(f'Opening dashboard in browser: {url}')
349
351
  webbrowser.open(url)
350
352
 
@@ -1908,6 +1910,7 @@ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
1908
1910
  Args:
1909
1911
  endpoint: The endpoint of the SkyPilot API server, e.g.,
1910
1912
  http://1.2.3.4:46580 or https://skypilot.mydomain.com.
1913
+ get_token: Whether to force getting a new token even if not needed.
1911
1914
 
1912
1915
  Returns:
1913
1916
  None
@@ -1926,14 +1929,60 @@ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
1926
1929
  server_status = server_common.check_server_healthy(endpoint)
1927
1930
  if server_status == server_common.ApiServerStatus.NEEDS_AUTH or get_token:
1928
1931
  # We detected an auth proxy, so go through the auth proxy cookie flow.
1929
- parsed_url = urlparse.urlparse(endpoint)
1930
- token_url = f'{endpoint}/token'
1931
- click.echo('Authentication is needed. Please visit this URL setup up '
1932
- f'the token:{colorama.Style.BRIGHT}\n\n{token_url}'
1933
- f'\n{colorama.Style.RESET_ALL}')
1934
- if webbrowser.open(token_url):
1935
- click.echo('Opening browser...')
1936
- token: str = click.prompt('Paste the token')
1932
+ token: Optional[str] = None
1933
+ server: Optional[oauth_lib.HTTPServer] = None
1934
+ try:
1935
+ callback_port = common_utils.find_free_port(8000)
1936
+
1937
+ token_container: Dict[str, Optional[str]] = {'token': None}
1938
+ logger.debug('Starting local authentication server...')
1939
+ server = oauth_lib.start_local_auth_server(callback_port,
1940
+ token_container,
1941
+ endpoint)
1942
+
1943
+ token_url = (f'{endpoint}/token?local_port={callback_port}')
1944
+ if webbrowser.open(token_url):
1945
+ click.echo(f'{colorama.Fore.GREEN}A web browser has been '
1946
+ f'opened at {token_url}. Please continue the login '
1947
+ f'in the web browser.{colorama.Style.RESET_ALL}\n'
1948
+ f'{colorama.Style.DIM}To manually copy the token, '
1949
+ f'press ctrl+c.{colorama.Style.RESET_ALL}')
1950
+ else:
1951
+ raise ValueError('Failed to open browser.')
1952
+
1953
+ start_time = time.time()
1954
+
1955
+ while (token_container['token'] is None and
1956
+ time.time() - start_time < oauth_lib.AUTH_TIMEOUT):
1957
+ time.sleep(1)
1958
+
1959
+ if token_container['token'] is None:
1960
+ click.echo(f'{colorama.Fore.YELLOW}Authentication timed out '
1961
+ f'after {oauth_lib.AUTH_TIMEOUT} seconds.')
1962
+ else:
1963
+ token = token_container['token']
1964
+
1965
+ except (Exception, KeyboardInterrupt) as e: # pylint: disable=broad-except
1966
+ logger.debug(f'Automatic authentication failed: {e}, '
1967
+ 'falling back to manual token entry.')
1968
+ if isinstance(e, KeyboardInterrupt):
1969
+ click.echo(f'\n{colorama.Style.DIM}Interrupted. Press ctrl+c '
1970
+ f'again to exit.{colorama.Style.RESET_ALL}')
1971
+ # Fall back to manual token entry
1972
+ token_url = f'{endpoint}/token'
1973
+ click.echo('Authentication is needed. Please visit this URL '
1974
+ f'to set up the token:{colorama.Style.BRIGHT}\n\n'
1975
+ f'{token_url}\n{colorama.Style.RESET_ALL}')
1976
+ token = click.prompt('Paste the token')
1977
+ finally:
1978
+ if server is not None:
1979
+ try:
1980
+ server.server_close()
1981
+ except Exception: # pylint: disable=broad-except
1982
+ pass
1983
+ if not token:
1984
+ with ux_utils.print_exception_no_traceback():
1985
+ raise ValueError('Authentication failed.')
1937
1986
 
1938
1987
  # Parse the token.
1939
1988
  # b64decode will ignore invalid characters, but does some length and
@@ -1959,6 +2008,7 @@ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
1959
2008
  else:
1960
2009
  raise ValueError(f'Unsupported token version: {json_data.get("v")}')
1961
2010
 
2011
+ parsed_url = urlparse.urlparse(endpoint)
1962
2012
  cookie_jar = cookiejar.MozillaCookieJar()
1963
2013
  for (name, value) in cookie_dict.items():
1964
2014
  # dict keys in JSON must be strings
sky/clouds/kubernetes.py CHANGED
@@ -853,11 +853,11 @@ class Kubernetes(clouds.Cloud):
853
853
 
854
854
  @classmethod
855
855
  def get_user_identities(cls) -> Optional[List[List[str]]]:
856
- k8s = kubernetes.kubernetes
857
856
  identities = []
857
+ k8s = kubernetes.kubernetes
858
858
  try:
859
859
  all_contexts, current_context = (
860
- k8s.config.list_kube_config_contexts())
860
+ kubernetes.list_kube_config_contexts())
861
861
  except k8s.config.config_exception.ConfigException:
862
862
  return None
863
863
  # Add current context at the head of the list
@@ -179,7 +179,7 @@ TPU_V4_HOST_DF = pd.read_csv(
179
179
  # TODO(woosuk): Make this more robust.
180
180
  # Refer to: https://github.com/skypilot-org/skypilot/issues/1006
181
181
  # Unsupported Series: 'f1', 'm2'
182
- SERIES_TO_DISCRIPTION = {
182
+ SERIES_TO_DESCRIPTION = {
183
183
  'a2': 'A2 Instance',
184
184
  'a3': 'A3 Instance',
185
185
  # TODO(zhwu): GCP does not have A4 instance in SKUs API yet. We keep it here
@@ -338,7 +338,7 @@ def get_vm_df(skus: List[Dict[str, Any]], region_prefix: str) -> 'pd.DataFrame':
338
338
 
339
339
  # Drop the unsupported series.
340
340
  df = df[df['InstanceType'].str.startswith(
341
- tuple(f'{series}-' for series in SERIES_TO_DISCRIPTION))]
341
+ tuple(f'{series}-' for series in SERIES_TO_DESCRIPTION))]
342
342
  df = df[~df['AvailabilityZone'].str.startswith(tuple(TPU_V4_ZONES))]
343
343
 
344
344
  # TODO(woosuk): Make this more efficient.
@@ -356,7 +356,7 @@ def get_vm_df(skus: List[Dict[str, Any]], region_prefix: str) -> 'pd.DataFrame':
356
356
 
357
357
  # Check if the SKU is for the correct series.
358
358
  description = sku['description']
359
- if SERIES_TO_DISCRIPTION[series].lower() not in description.lower():
359
+ if SERIES_TO_DESCRIPTION[series].lower() not in description.lower():
360
360
  continue
361
361
  # Special check for M1 instances.
362
362
  if series == 'm1' and 'M3' in description:
@@ -1 +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/6a1c0d711a4bdaf1.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/6a1c0d711a4bdaf1.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-deda68c926e8d0bc.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-3985f074c163a856.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_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":"D5bjIfl4Ob3SV3LJz3CO0","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"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link rel="preload" href="/dashboard/_next/static/css/ffd1cd601648c303.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/ffd1cd601648c303.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-deda68c926e8d0bc.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-a631df412d8172de.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/HvNkg7hqKM1p0ptAcdDcF/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/HvNkg7hqKM1p0ptAcdDcF/_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":"HvNkg7hqKM1p0ptAcdDcF","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -0,0 +1 @@
1
+ self.__BUILD_MANIFEST=function(s,c,e,a,t,r,n,u,f,i,j,k){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-6b0d9e5031b70c58.js"],"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],"/clusters":[s,t,c,e,a,r,i,"static/chunks/pages/clusters-943992b84fd6f4ee.js"],"/clusters/[cluster]":[s,t,c,e,a,r,n,i,"static/chunks/pages/clusters/[cluster]-9506c00257d10dbd.js"],"/clusters/[cluster]/[job]":[s,c,"static/chunks/pages/clusters/[cluster]/[job]-159bffb2fa34ed54.js"],"/config":[u,s,f,c,e,"static/chunks/pages/config-7c48919fe030bc43.js"],"/infra":[s,c,e,a,j,"static/chunks/pages/infra-d4c6875c88771e17.js"],"/infra/[context]":[s,c,e,a,j,"static/chunks/pages/infra/[context]-909f1ceb0fcf1b99.js"],"/jobs":[s,t,c,e,a,r,n,"static/chunks/pages/jobs-a4efc09e61988f8d.js"],"/jobs/[job]":[s,c,"static/chunks/pages/jobs/[job]-6b80e9e0c6aa16a1.js"],"/users":[s,c,e,a,"static/chunks/pages/users-b2634885d67c49a6.js"],"/workspace/new":[u,s,t,f,c,e,a,r,n,k,"static/chunks/pages/workspace/new-579b3203c7c19d84.js"],"/workspaces":[u,s,t,f,c,e,a,r,n,"static/chunks/pages/workspaces-610c49ae3619ee85.js"],"/workspaces/[name]":[u,s,t,f,c,e,a,r,n,k,"static/chunks/pages/workspaces/[name]-9388e38fac73ee8f.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/[job]","/users","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/173-7db8607cefc20f70.js","static/chunks/470-4d003c441839094d.js","static/chunks/293-351268365226d251.js","static/chunks/856-59a1760784c9e770.js","static/chunks/121-8f55ee3fa6301784.js","static/chunks/973-1a09cac61cfcc1e1.js","static/chunks/236-90e5498a5b00ec29.js","static/chunks/9f96d65d-5a3e4af68c26849e.js","static/chunks/320-afea3ddcc5bd1c6c.js","static/chunks/578-9146658cead92981.js","static/chunks/303-2c7b0f7af571710b.js","static/chunks/843-256ec920f6d5f41f.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -0,0 +1,20 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[121],{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"}]])},3626: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)("RotateCw",[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]])},3767:function(e,t,n){n.d(t,{Z:function(){return r}});/**
12
+ * @license lucide-react v0.407.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */let r=(0,n(998).Z)("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]])},6327:function(e,t,n){n.d(t,{x8:function(){return el},VY:function(){return eo},dk:function(){return ea},aV:function(){return er},h_:function(){return en},fC:function(){return ee},Dx:function(){return ei},xz:function(){return et}});var r=n(7294),o=n(6206),i=n(8771),a=n(5360),l=n(1276),u=n(7342),s=n(6063),d=n(5420),c=n(2651),f=n(9981),p=e=>{let t,n;let{present:o,children:a}=e,l=function(e){var t,n;let[o,i]=r.useState(),a=r.useRef(null),l=r.useRef(e),u=r.useRef("none"),[s,d]=(t=e?"mounted":"unmounted",n={mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}},r.useReducer((e,t)=>n[e][t]??e,t));return r.useEffect(()=>{let e=m(a.current);u.current="mounted"===s?e:"none"},[s]),(0,f.b)(()=>{let t=a.current,n=l.current;if(n!==e){let r=u.current,o=m(t);e?d("MOUNT"):"none"===o||t?.display==="none"?d("UNMOUNT"):n&&r!==o?d("ANIMATION_OUT"):d("UNMOUNT"),l.current=e}},[e,d]),(0,f.b)(()=>{if(o){let e;let t=o.ownerDocument.defaultView??window,n=n=>{let r=m(a.current).includes(n.animationName);if(n.target===o&&r&&(d("ANIMATION_END"),!l.current)){let n=o.style.animationFillMode;o.style.animationFillMode="forwards",e=t.setTimeout(()=>{"forwards"===o.style.animationFillMode&&(o.style.animationFillMode=n)})}},r=e=>{e.target===o&&(u.current=m(a.current))};return o.addEventListener("animationstart",r),o.addEventListener("animationcancel",n),o.addEventListener("animationend",n),()=>{t.clearTimeout(e),o.removeEventListener("animationstart",r),o.removeEventListener("animationcancel",n),o.removeEventListener("animationend",n)}}d("ANIMATION_END")},[o,d]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:r.useCallback(e=>{a.current=e?getComputedStyle(e):null,i(e)},[])}}(o),u="function"==typeof a?a({present:l.isPresent}):r.Children.only(a),s=(0,i.e)(l.ref,(t=Object.getOwnPropertyDescriptor(u.props,"ref")?.get)&&"isReactWarning"in t&&t.isReactWarning?u.ref:(t=Object.getOwnPropertyDescriptor(u,"ref")?.get)&&"isReactWarning"in t&&t.isReactWarning?u.props.ref:u.props.ref||u.ref);return"function"==typeof a||l.isPresent?r.cloneElement(u,{ref:s}):null};function m(e){return e?.animationName||"none"}p.displayName="Presence";var g=n(5320),v=n(7552),y=n(6223),N=n(3541),h=n(8426),D=n(5893),O="Dialog",[b,M]=(0,a.b)(O),[R,x]=b(O),j=e=>{let{__scopeDialog:t,children:n,open:o,defaultOpen:i,onOpenChange:a,modal:s=!0}=e,d=r.useRef(null),c=r.useRef(null),[f,p]=(0,u.T)({prop:o,defaultProp:i??!1,onChange:a,caller:O});return(0,D.jsx)(R,{scope:t,triggerRef:d,contentRef:c,contentId:(0,l.M)(),titleId:(0,l.M)(),descriptionId:(0,l.M)(),open:f,onOpenChange:p,onOpenToggle:r.useCallback(()=>p(e=>!e),[p]),modal:s,children:n})};j.displayName=O;var w="DialogTrigger",I=r.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,a=x(w,n),l=(0,i.e)(t,a.triggerRef);return(0,D.jsx)(g.WV.button,{type:"button","aria-haspopup":"dialog","aria-expanded":a.open,"aria-controls":a.contentId,"data-state":H(a.open),...r,ref:l,onClick:(0,o.M)(e.onClick,a.onOpenToggle)})});I.displayName=w;var C="DialogPortal",[E,_]=b(C,{forceMount:void 0}),T=e=>{let{__scopeDialog:t,forceMount:n,children:o,container:i}=e,a=x(C,t);return(0,D.jsx)(E,{scope:t,forceMount:n,children:r.Children.map(o,e=>(0,D.jsx)(p,{present:n||a.open,children:(0,D.jsx)(c.h,{asChild:!0,container:i,children:e})}))})};T.displayName=C;var k="DialogOverlay",A=r.forwardRef((e,t)=>{let n=_(k,e.__scopeDialog),{forceMount:r=n.forceMount,...o}=e,i=x(k,e.__scopeDialog);return i.modal?(0,D.jsx)(p,{present:r||i.open,children:(0,D.jsx)(P,{...o,ref:t})}):null});A.displayName=k;var F=(0,h.Z8)("DialogOverlay.RemoveScroll"),P=r.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=x(k,n);return(0,D.jsx)(y.Z,{as:F,allowPinchZoom:!0,shards:[o.contentRef],children:(0,D.jsx)(g.WV.div,{"data-state":H(o.open),...r,ref:t,style:{pointerEvents:"auto",...r.style}})})}),W="DialogContent",U=r.forwardRef((e,t)=>{let n=_(W,e.__scopeDialog),{forceMount:r=n.forceMount,...o}=e,i=x(W,e.__scopeDialog);return(0,D.jsx)(p,{present:r||i.open,children:i.modal?(0,D.jsx)(V,{...o,ref:t}):(0,D.jsx)(Z,{...o,ref:t})})});U.displayName=W;var V=r.forwardRef((e,t)=>{let n=x(W,e.__scopeDialog),a=r.useRef(null),l=(0,i.e)(t,n.contentRef,a);return r.useEffect(()=>{let e=a.current;if(e)return(0,N.Ry)(e)},[]),(0,D.jsx)(S,{...e,ref:l,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:(0,o.M)(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:(0,o.M)(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=0===t.button&&!0===t.ctrlKey;(2===t.button||n)&&e.preventDefault()}),onFocusOutside:(0,o.M)(e.onFocusOutside,e=>e.preventDefault())})}),Z=r.forwardRef((e,t)=>{let n=x(W,e.__scopeDialog),o=r.useRef(!1),i=r.useRef(!1);return(0,D.jsx)(S,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(o.current||n.triggerRef.current?.focus(),t.preventDefault()),o.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(o.current=!0,"pointerdown"!==t.detail.originalEvent.type||(i.current=!0));let r=t.target;n.triggerRef.current?.contains(r)&&t.preventDefault(),"focusin"===t.detail.originalEvent.type&&i.current&&t.preventDefault()}})}),S=r.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:o,onOpenAutoFocus:a,onCloseAutoFocus:l,...u}=e,c=x(W,n),f=r.useRef(null),p=(0,i.e)(t,f);return(0,v.EW)(),(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(d.M,{asChild:!0,loop:!0,trapped:o,onMountAutoFocus:a,onUnmountAutoFocus:l,children:(0,D.jsx)(s.XB,{role:"dialog",id:c.contentId,"aria-describedby":c.descriptionId,"aria-labelledby":c.titleId,"data-state":H(c.open),...u,ref:p,onDismiss:()=>c.onOpenChange(!1)})}),(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(J,{titleId:c.titleId}),(0,D.jsx)(Q,{contentRef:f,descriptionId:c.descriptionId})]})]})}),L="DialogTitle",$=r.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=x(L,n);return(0,D.jsx)(g.WV.h2,{id:o.titleId,...r,ref:t})});$.displayName=L;var B="DialogDescription",q=r.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,o=x(B,n);return(0,D.jsx)(g.WV.p,{id:o.descriptionId,...r,ref:t})});q.displayName=B;var z="DialogClose",X=r.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=x(z,n);return(0,D.jsx)(g.WV.button,{type:"button",...r,ref:t,onClick:(0,o.M)(e.onClick,()=>i.onOpenChange(!1))})});function H(e){return e?"open":"closed"}X.displayName=z;var K="DialogTitleWarning",[Y,G]=(0,a.k)(K,{contentName:W,titleName:L,docsSlug:"dialog"}),J=({titleId:e})=>{let t=G(K),n=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
17
+
18
+ If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
19
+
20
+ For more information, see https://radix-ui.com/primitives/docs/components/${t.docsSlug}`;return r.useEffect(()=>{e&&!document.getElementById(e)&&console.error(n)},[n,e]),null},Q=({contentRef:e,descriptionId:t})=>{let n=G("DialogDescriptionWarning"),o=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${n.contentName}}.`;return r.useEffect(()=>{let n=e.current?.getAttribute("aria-describedby");t&&n&&!document.getElementById(t)&&console.warn(o)},[o,e,t]),null},ee=j,et=I,en=T,er=A,eo=U,ei=$,ea=q,el=X},2003:function(e,t,n){n.d(t,{j:function(){return a}});var r=n(512);let o=e=>"boolean"==typeof e?`${e}`:0===e?"0":e,i=r.W,a=(e,t)=>n=>{var r;if((null==t?void 0:t.variants)==null)return i(e,null==n?void 0:n.class,null==n?void 0:n.className);let{variants:a,defaultVariants:l}=t,u=Object.keys(a).map(e=>{let t=null==n?void 0:n[e],r=null==l?void 0:l[e];if(null===t)return null;let i=o(t)||o(r);return a[e][i]}),s=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return void 0===r||(e[n]=r),e},{});return i(e,u,null==t?void 0:null===(r=t.compoundVariants)||void 0===r?void 0:r.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({...l,...s}[t]):({...l,...s})[t]===n})?[...e,n,r]:e},[]),null==n?void 0:n.class,null==n?void 0:n.className)}}}]);