skypilot-nightly 1.0.0.dev20250523__py3-none-any.whl → 1.0.0.dev20250524__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 (82) hide show
  1. sky/__init__.py +2 -2
  2. sky/backends/backend_utils.py +62 -45
  3. sky/backends/cloud_vm_ray_backend.py +3 -1
  4. sky/check.py +332 -170
  5. sky/cli.py +44 -11
  6. sky/client/cli.py +44 -11
  7. sky/client/sdk.py +54 -10
  8. sky/clouds/gcp.py +19 -3
  9. sky/core.py +5 -2
  10. sky/dashboard/out/404.html +1 -1
  11. sky/dashboard/out/_next/static/aHej19bZyl4hoHgrzPCn7/_buildManifest.js +1 -0
  12. sky/dashboard/out/_next/static/chunks/480-ee58038f1a4afd5c.js +1 -0
  13. sky/dashboard/out/_next/static/chunks/488-50d843fdb5396d32.js +15 -0
  14. sky/dashboard/out/_next/static/chunks/498-d7722313e5e5b4e6.js +21 -0
  15. sky/dashboard/out/_next/static/chunks/573-f17bd89d9f9118b3.js +66 -0
  16. sky/dashboard/out/_next/static/chunks/578-7a4795009a56430c.js +6 -0
  17. sky/dashboard/out/_next/static/chunks/734-5f5ce8f347b7f417.js +1 -0
  18. sky/dashboard/out/_next/static/chunks/937.f97f83652028e944.js +1 -0
  19. sky/dashboard/out/_next/static/chunks/938-f347f6144075b0c8.js +1 -0
  20. sky/dashboard/out/_next/static/chunks/9f96d65d-5a3e4af68c26849e.js +1 -0
  21. sky/dashboard/out/_next/static/chunks/pages/_app-dec800f9ef1b10f4.js +1 -0
  22. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-37c042a356f8e608.js +1 -0
  23. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-9529d9e882a0e75c.js +16 -0
  24. sky/dashboard/out/_next/static/chunks/pages/clusters-9e6d1ec6e1ac5b29.js +1 -0
  25. sky/dashboard/out/_next/static/chunks/pages/infra-e690d864aa00e2ea.js +1 -0
  26. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-db6558a5ec687011.js +1 -0
  27. sky/dashboard/out/_next/static/chunks/pages/jobs-73d5e0c369d00346.js +16 -0
  28. sky/dashboard/out/_next/static/chunks/pages/users-2d319455c3f1c3e2.js +1 -0
  29. sky/dashboard/out/_next/static/chunks/pages/workspaces-02a7b60f2ead275f.js +1 -0
  30. sky/dashboard/out/_next/static/chunks/webpack-deda68c926e8d0bc.js +1 -0
  31. sky/dashboard/out/_next/static/css/d2cdba64c9202dd7.css +3 -0
  32. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  33. sky/dashboard/out/clusters/[cluster].html +1 -1
  34. sky/dashboard/out/clusters.html +1 -1
  35. sky/dashboard/out/index.html +1 -1
  36. sky/dashboard/out/infra.html +1 -1
  37. sky/dashboard/out/jobs/[job].html +1 -1
  38. sky/dashboard/out/jobs.html +1 -1
  39. sky/dashboard/out/users.html +1 -0
  40. sky/dashboard/out/workspaces.html +1 -0
  41. sky/data/storage.py +1 -1
  42. sky/global_user_state.py +42 -19
  43. sky/jobs/constants.py +1 -1
  44. sky/jobs/server/core.py +72 -56
  45. sky/jobs/state.py +26 -5
  46. sky/jobs/utils.py +65 -13
  47. sky/optimizer.py +6 -3
  48. sky/provision/fluidstack/instance.py +1 -0
  49. sky/serve/server/core.py +9 -6
  50. sky/server/html/token_page.html +6 -1
  51. sky/server/requests/executor.py +1 -0
  52. sky/server/requests/payloads.py +11 -0
  53. sky/server/server.py +68 -5
  54. sky/skylet/constants.py +4 -1
  55. sky/skypilot_config.py +83 -9
  56. sky/utils/cli_utils/status_utils.py +18 -8
  57. sky/utils/kubernetes/deploy_remote_cluster.py +150 -147
  58. sky/utils/log_utils.py +4 -0
  59. sky/utils/schemas.py +54 -0
  60. {skypilot_nightly-1.0.0.dev20250523.dist-info → skypilot_nightly-1.0.0.dev20250524.dist-info}/METADATA +1 -1
  61. {skypilot_nightly-1.0.0.dev20250523.dist-info → skypilot_nightly-1.0.0.dev20250524.dist-info}/RECORD +66 -59
  62. sky/dashboard/out/_next/static/ECKwDNS9v9y3_IKFZ2lpp/_buildManifest.js +0 -1
  63. sky/dashboard/out/_next/static/chunks/236-1a3a9440417720eb.js +0 -6
  64. sky/dashboard/out/_next/static/chunks/312-c3c8845990db8ffc.js +0 -15
  65. sky/dashboard/out/_next/static/chunks/37-d584022b0da4ac3b.js +0 -6
  66. sky/dashboard/out/_next/static/chunks/393-e1eaa440481337ec.js +0 -1
  67. sky/dashboard/out/_next/static/chunks/480-f28cd152a98997de.js +0 -1
  68. sky/dashboard/out/_next/static/chunks/582-683f4f27b81996dc.js +0 -59
  69. sky/dashboard/out/_next/static/chunks/pages/_app-8cfab319f9fb3ae8.js +0 -1
  70. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-33bc2bec322249b1.js +0 -1
  71. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-e2fc2dd1955e6c36.js +0 -1
  72. sky/dashboard/out/_next/static/chunks/pages/clusters-3a748bd76e5c2984.js +0 -1
  73. sky/dashboard/out/_next/static/chunks/pages/infra-abf08c4384190a39.js +0 -1
  74. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-70756c2dad850a7e.js +0 -1
  75. sky/dashboard/out/_next/static/chunks/pages/jobs-ecd804b9272f4a7c.js +0 -1
  76. sky/dashboard/out/_next/static/chunks/webpack-830f59b8404e96b8.js +0 -1
  77. sky/dashboard/out/_next/static/css/7e7ce4ff31d3977b.css +0 -3
  78. /sky/dashboard/out/_next/static/{ECKwDNS9v9y3_IKFZ2lpp → aHej19bZyl4hoHgrzPCn7}/_ssgManifest.js +0 -0
  79. {skypilot_nightly-1.0.0.dev20250523.dist-info → skypilot_nightly-1.0.0.dev20250524.dist-info}/WHEEL +0 -0
  80. {skypilot_nightly-1.0.0.dev20250523.dist-info → skypilot_nightly-1.0.0.dev20250524.dist-info}/entry_points.txt +0 -0
  81. {skypilot_nightly-1.0.0.dev20250523.dist-info → skypilot_nightly-1.0.0.dev20250524.dist-info}/licenses/LICENSE +0 -0
  82. {skypilot_nightly-1.0.0.dev20250523.dist-info → skypilot_nightly-1.0.0.dev20250524.dist-info}/top_level.txt +0 -0
sky/cli.py CHANGED
@@ -1781,9 +1781,13 @@ def _show_endpoint(query_clusters: Optional[List[str]],
1781
1781
  return
1782
1782
 
1783
1783
 
1784
- def _show_enabled_infra():
1784
+ def _show_enabled_infra(active_workspace: str, show_workspace: bool):
1785
1785
  """Show the enabled infrastructure."""
1786
- title = (f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Enabled Infra:'
1786
+ workspace_str = ''
1787
+ if show_workspace:
1788
+ workspace_str = f' (workspace: {active_workspace!r})'
1789
+ title = (f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Enabled Infra'
1790
+ f'{workspace_str}:'
1787
1791
  f'{colorama.Style.RESET_ALL} ')
1788
1792
  enabled_clouds = sdk.get(sdk.enabled_clouds())
1789
1793
  enabled_ssh_infras = []
@@ -1954,6 +1958,7 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
1954
1958
  # status query.
1955
1959
  service_status_request_id = serve_lib.status(service_names=None)
1956
1960
 
1961
+ workspace_request_id = None
1957
1962
  if ip or show_endpoints:
1958
1963
  if refresh:
1959
1964
  raise click.UsageError(
@@ -1988,9 +1993,8 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
1988
1993
  ('endpoint port'
1989
1994
  if show_single_endpoint else 'endpoints')))
1990
1995
  else:
1991
- _show_enabled_infra()
1992
- click.echo(f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Clusters'
1993
- f'{colorama.Style.RESET_ALL}')
1996
+ workspace_request_id = sdk.workspaces()
1997
+
1994
1998
  query_clusters: Optional[List[str]] = None if not clusters else clusters
1995
1999
  refresh_mode = common.StatusRefreshMode.NONE
1996
2000
  if refresh:
@@ -2013,9 +2017,20 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
2013
2017
  else:
2014
2018
  normal_clusters.append(cluster_record)
2015
2019
 
2020
+ if workspace_request_id is not None:
2021
+ all_workspaces = sdk.get(workspace_request_id)
2022
+ else:
2023
+ all_workspaces = [constants.SKYPILOT_DEFAULT_WORKSPACE]
2024
+ active_workspace = skypilot_config.get_active_workspace()
2025
+ show_workspace = len(all_workspaces) > 1
2026
+ _show_enabled_infra(active_workspace, show_workspace)
2027
+ click.echo(f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Clusters'
2028
+ f'{colorama.Style.RESET_ALL}')
2029
+
2016
2030
  num_pending_autostop = 0
2017
2031
  num_pending_autostop += status_utils.show_status_table(
2018
- normal_clusters + controllers, verbose, all_users, query_clusters)
2032
+ normal_clusters + controllers, verbose, all_users, query_clusters,
2033
+ show_workspace)
2019
2034
 
2020
2035
  managed_jobs_query_interrupted = False
2021
2036
  if show_managed_jobs:
@@ -3345,9 +3360,16 @@ def _down_or_stop_clusters(
3345
3360
  is_flag=True,
3346
3361
  default=False,
3347
3362
  help='Show the activated account for each cloud.')
3363
+ @click.option(
3364
+ '--workspace',
3365
+ '-w',
3366
+ type=str,
3367
+ help='The workspace to check. If None, all workspaces will be checked.')
3348
3368
  @usage_lib.entrypoint
3349
3369
  # pylint: disable=redefined-outer-name
3350
- def check(infra_list: Tuple[str], verbose: bool):
3370
+ def check(infra_list: Tuple[str],
3371
+ verbose: bool,
3372
+ workspace: Optional[str] = None):
3351
3373
  """Check which clouds are available to use.
3352
3374
 
3353
3375
  This checks access credentials for all clouds supported by SkyPilot. If a
@@ -3370,7 +3392,9 @@ def check(infra_list: Tuple[str], verbose: bool):
3370
3392
  sky check aws gcp
3371
3393
  """
3372
3394
  infra_arg = infra_list if len(infra_list) > 0 else None
3373
- request_id = sdk.check(infra_list=infra_arg, verbose=verbose)
3395
+ request_id = sdk.check(infra_list=infra_arg,
3396
+ verbose=verbose,
3397
+ workspace=workspace)
3374
3398
  sdk.stream_and_get(request_id)
3375
3399
  api_server_url = server_common.get_server_url()
3376
3400
  click.echo()
@@ -4447,7 +4471,8 @@ def jobs_cancel(name: Optional[str], job_ids: Tuple[int], all: bool, yes: bool,
4447
4471
  f'Provided {" ".join(arguments)!r}.')
4448
4472
 
4449
4473
  if not yes:
4450
- job_identity_str = (f'managed jobs with IDs {job_id_str}'
4474
+ plural = 's' if len(job_ids) > 1 else ''
4475
+ job_identity_str = (f'managed job{plural} with ID{plural} {job_id_str}'
4451
4476
  if job_ids else repr(name))
4452
4477
  if all_users:
4453
4478
  job_identity_str = 'all managed jobs FOR ALL USERS'
@@ -6169,10 +6194,14 @@ def api_status(request_ids: Optional[List[str]], all_status: bool,
6169
6194
  '-e',
6170
6195
  required=False,
6171
6196
  help='The SkyPilot API server endpoint.')
6197
+ @click.option('--get-token',
6198
+ is_flag=True,
6199
+ default=False,
6200
+ help='Force token-based login.')
6172
6201
  @usage_lib.entrypoint
6173
- def api_login(endpoint: Optional[str]):
6202
+ def api_login(endpoint: Optional[str], get_token: bool):
6174
6203
  """Logs into a SkyPilot API server."""
6175
- sdk.api_login(endpoint)
6204
+ sdk.api_login(endpoint, get_token)
6176
6205
 
6177
6206
 
6178
6207
  @api.command('info', cls=_DocumentedCodeCommand)
@@ -6184,6 +6213,10 @@ def api_info():
6184
6213
  api_server_info = sdk.api_info()
6185
6214
  user_name = os.getenv(constants.USER_ENV_VAR, getpass.getuser())
6186
6215
  user_hash = common_utils.get_user_hash()
6216
+ api_server_user = api_server_info.get('user')
6217
+ if api_server_user is not None:
6218
+ user_name = api_server_user['name']
6219
+ user_hash = api_server_user['id']
6187
6220
  dashboard_url = server_common.get_dashboard_url(url)
6188
6221
  click.echo(f'Using SkyPilot API server: {url}\n'
6189
6222
  f'{ux_utils.INDENT_SYMBOL}Status: {api_server_info["status"]}, '
sky/client/cli.py CHANGED
@@ -1781,9 +1781,13 @@ def _show_endpoint(query_clusters: Optional[List[str]],
1781
1781
  return
1782
1782
 
1783
1783
 
1784
- def _show_enabled_infra():
1784
+ def _show_enabled_infra(active_workspace: str, show_workspace: bool):
1785
1785
  """Show the enabled infrastructure."""
1786
- title = (f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Enabled Infra:'
1786
+ workspace_str = ''
1787
+ if show_workspace:
1788
+ workspace_str = f' (workspace: {active_workspace!r})'
1789
+ title = (f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Enabled Infra'
1790
+ f'{workspace_str}:'
1787
1791
  f'{colorama.Style.RESET_ALL} ')
1788
1792
  enabled_clouds = sdk.get(sdk.enabled_clouds())
1789
1793
  enabled_ssh_infras = []
@@ -1954,6 +1958,7 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
1954
1958
  # status query.
1955
1959
  service_status_request_id = serve_lib.status(service_names=None)
1956
1960
 
1961
+ workspace_request_id = None
1957
1962
  if ip or show_endpoints:
1958
1963
  if refresh:
1959
1964
  raise click.UsageError(
@@ -1988,9 +1993,8 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
1988
1993
  ('endpoint port'
1989
1994
  if show_single_endpoint else 'endpoints')))
1990
1995
  else:
1991
- _show_enabled_infra()
1992
- click.echo(f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Clusters'
1993
- f'{colorama.Style.RESET_ALL}')
1996
+ workspace_request_id = sdk.workspaces()
1997
+
1994
1998
  query_clusters: Optional[List[str]] = None if not clusters else clusters
1995
1999
  refresh_mode = common.StatusRefreshMode.NONE
1996
2000
  if refresh:
@@ -2013,9 +2017,20 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
2013
2017
  else:
2014
2018
  normal_clusters.append(cluster_record)
2015
2019
 
2020
+ if workspace_request_id is not None:
2021
+ all_workspaces = sdk.get(workspace_request_id)
2022
+ else:
2023
+ all_workspaces = [constants.SKYPILOT_DEFAULT_WORKSPACE]
2024
+ active_workspace = skypilot_config.get_active_workspace()
2025
+ show_workspace = len(all_workspaces) > 1
2026
+ _show_enabled_infra(active_workspace, show_workspace)
2027
+ click.echo(f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Clusters'
2028
+ f'{colorama.Style.RESET_ALL}')
2029
+
2016
2030
  num_pending_autostop = 0
2017
2031
  num_pending_autostop += status_utils.show_status_table(
2018
- normal_clusters + controllers, verbose, all_users, query_clusters)
2032
+ normal_clusters + controllers, verbose, all_users, query_clusters,
2033
+ show_workspace)
2019
2034
 
2020
2035
  managed_jobs_query_interrupted = False
2021
2036
  if show_managed_jobs:
@@ -3345,9 +3360,16 @@ def _down_or_stop_clusters(
3345
3360
  is_flag=True,
3346
3361
  default=False,
3347
3362
  help='Show the activated account for each cloud.')
3363
+ @click.option(
3364
+ '--workspace',
3365
+ '-w',
3366
+ type=str,
3367
+ help='The workspace to check. If None, all workspaces will be checked.')
3348
3368
  @usage_lib.entrypoint
3349
3369
  # pylint: disable=redefined-outer-name
3350
- def check(infra_list: Tuple[str], verbose: bool):
3370
+ def check(infra_list: Tuple[str],
3371
+ verbose: bool,
3372
+ workspace: Optional[str] = None):
3351
3373
  """Check which clouds are available to use.
3352
3374
 
3353
3375
  This checks access credentials for all clouds supported by SkyPilot. If a
@@ -3370,7 +3392,9 @@ def check(infra_list: Tuple[str], verbose: bool):
3370
3392
  sky check aws gcp
3371
3393
  """
3372
3394
  infra_arg = infra_list if len(infra_list) > 0 else None
3373
- request_id = sdk.check(infra_list=infra_arg, verbose=verbose)
3395
+ request_id = sdk.check(infra_list=infra_arg,
3396
+ verbose=verbose,
3397
+ workspace=workspace)
3374
3398
  sdk.stream_and_get(request_id)
3375
3399
  api_server_url = server_common.get_server_url()
3376
3400
  click.echo()
@@ -4447,7 +4471,8 @@ def jobs_cancel(name: Optional[str], job_ids: Tuple[int], all: bool, yes: bool,
4447
4471
  f'Provided {" ".join(arguments)!r}.')
4448
4472
 
4449
4473
  if not yes:
4450
- job_identity_str = (f'managed jobs with IDs {job_id_str}'
4474
+ plural = 's' if len(job_ids) > 1 else ''
4475
+ job_identity_str = (f'managed job{plural} with ID{plural} {job_id_str}'
4451
4476
  if job_ids else repr(name))
4452
4477
  if all_users:
4453
4478
  job_identity_str = 'all managed jobs FOR ALL USERS'
@@ -6169,10 +6194,14 @@ def api_status(request_ids: Optional[List[str]], all_status: bool,
6169
6194
  '-e',
6170
6195
  required=False,
6171
6196
  help='The SkyPilot API server endpoint.')
6197
+ @click.option('--get-token',
6198
+ is_flag=True,
6199
+ default=False,
6200
+ help='Force token-based login.')
6172
6201
  @usage_lib.entrypoint
6173
- def api_login(endpoint: Optional[str]):
6202
+ def api_login(endpoint: Optional[str], get_token: bool):
6174
6203
  """Logs into a SkyPilot API server."""
6175
- sdk.api_login(endpoint)
6204
+ sdk.api_login(endpoint, get_token)
6176
6205
 
6177
6206
 
6178
6207
  @api.command('info', cls=_DocumentedCodeCommand)
@@ -6184,6 +6213,10 @@ def api_info():
6184
6213
  api_server_info = sdk.api_info()
6185
6214
  user_name = os.getenv(constants.USER_ENV_VAR, getpass.getuser())
6186
6215
  user_hash = common_utils.get_user_hash()
6216
+ api_server_user = api_server_info.get('user')
6217
+ if api_server_user is not None:
6218
+ user_name = api_server_user['name']
6219
+ user_hash = api_server_user['id']
6187
6220
  dashboard_url = server_common.get_dashboard_url(url)
6188
6221
  click.echo(f'Using SkyPilot API server: {url}\n'
6189
6222
  f'{ux_utils.INDENT_SYMBOL}Status: {api_server_info["status"]}, '
sky/client/sdk.py CHANGED
@@ -94,12 +94,15 @@ def stream_response(request_id: Optional[str],
94
94
  @server_common.check_server_healthy_or_start
95
95
  @annotations.client_api
96
96
  def check(infra_list: Optional[Tuple[str, ...]],
97
- verbose: bool) -> server_common.RequestId:
97
+ verbose: bool,
98
+ workspace: Optional[str] = None) -> server_common.RequestId:
98
99
  """Checks the credentials to enable clouds.
99
100
 
100
101
  Args:
101
102
  infra: The infra to check.
102
103
  verbose: Whether to show verbose output.
104
+ workspace: The workspace to check. If None, all workspaces will be
105
+ checked.
103
106
 
104
107
  Returns:
105
108
  The request ID of the check request.
@@ -123,7 +126,9 @@ def check(infra_list: Optional[Tuple[str, ...]],
123
126
  f'ignoring {region_zone}')
124
127
  specified_clouds.append(infra.cloud)
125
128
  clouds = tuple(specified_clouds)
126
- body = payloads.CheckBody(clouds=clouds, verbose=verbose)
129
+ body = payloads.CheckBody(clouds=clouds,
130
+ verbose=verbose,
131
+ workspace=workspace)
127
132
  response = requests.post(f'{server_common.get_server_url()}/check',
128
133
  json=json.loads(body.model_dump_json()),
129
134
  cookies=server_common.get_api_cookie_jar())
@@ -133,16 +138,23 @@ def check(infra_list: Optional[Tuple[str, ...]],
133
138
  @usage_lib.entrypoint
134
139
  @server_common.check_server_healthy_or_start
135
140
  @annotations.client_api
136
- def enabled_clouds() -> server_common.RequestId:
141
+ def enabled_clouds(workspace: Optional[str] = None) -> server_common.RequestId:
137
142
  """Gets the enabled clouds.
138
143
 
144
+ Args:
145
+ workspace: The workspace to get the enabled clouds for. If None, the
146
+ active workspace will be used.
147
+
139
148
  Returns:
140
149
  The request ID of the enabled clouds request.
141
150
 
142
151
  Request Returns:
143
152
  A list of enabled clouds in string format.
144
153
  """
145
- response = requests.get(f'{server_common.get_server_url()}/enabled_clouds',
154
+ if workspace is None:
155
+ workspace = skypilot_config.get_active_workspace()
156
+ response = requests.get((f'{server_common.get_server_url()}/enabled_clouds?'
157
+ f'workspace={workspace}'),
146
158
  cookies=server_common.get_api_cookie_jar())
147
159
  return server_common.get_request_id(response)
148
160
 
@@ -278,6 +290,13 @@ def optimize(
278
290
  return server_common.get_request_id(response)
279
291
 
280
292
 
293
+ def workspaces() -> server_common.RequestId:
294
+ """Gets the workspaces."""
295
+ response = requests.get(f'{server_common.get_server_url()}/workspaces',
296
+ cookies=server_common.get_api_cookie_jar())
297
+ return server_common.get_request_id(response)
298
+
299
+
281
300
  @usage_lib.entrypoint
282
301
  @server_common.check_server_healthy_or_start
283
302
  @annotations.client_api
@@ -1731,7 +1750,7 @@ def api_status(
1731
1750
  @usage_lib.entrypoint
1732
1751
  @server_common.check_server_healthy_or_start
1733
1752
  @annotations.client_api
1734
- def api_info() -> Dict[str, str]:
1753
+ def api_info() -> Dict[str, Any]:
1735
1754
  """Gets the server's status, commit and version.
1736
1755
 
1737
1756
  Returns:
@@ -1744,8 +1763,15 @@ def api_info() -> Dict[str, str]:
1744
1763
  'api_version': '1',
1745
1764
  'commit': 'abc1234567890',
1746
1765
  'version': '1.0.0',
1766
+ 'version_on_disk': '1.0.0',
1767
+ 'user': {
1768
+ 'name': 'test@example.com',
1769
+ 'id': '12345abcd',
1770
+ },
1747
1771
  }
1748
1772
 
1773
+ Note that user may be None if we are not using an auth proxy.
1774
+
1749
1775
  """
1750
1776
  response = requests.get(f'{server_common.get_server_url()}/api/health',
1751
1777
  cookies=server_common.get_api_cookie_jar())
@@ -1868,7 +1894,7 @@ def api_server_logs(follow: bool = True, tail: Optional[int] = None) -> None:
1868
1894
 
1869
1895
  @usage_lib.entrypoint
1870
1896
  @annotations.client_api
1871
- def api_login(endpoint: Optional[str] = None) -> None:
1897
+ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
1872
1898
  """Logs into a SkyPilot API server.
1873
1899
 
1874
1900
  This sets the endpoint globally, i.e., all SkyPilot CLI and SDK calls will
@@ -1895,7 +1921,7 @@ def api_login(endpoint: Optional[str] = None) -> None:
1895
1921
  raise click.BadParameter('Endpoint must be a valid URL.')
1896
1922
 
1897
1923
  server_status = server_common.check_server_healthy(endpoint)
1898
- if server_status == server_common.ApiServerStatus.NEEDS_AUTH:
1924
+ if server_status == server_common.ApiServerStatus.NEEDS_AUTH or get_token:
1899
1925
  # We detected an auth proxy, so go through the auth proxy cookie flow.
1900
1926
  parsed_url = urlparse.urlparse(endpoint)
1901
1927
  token_url = f'{endpoint}/token'
@@ -1915,11 +1941,20 @@ def api_login(endpoint: Optional[str] = None) -> None:
1915
1941
  raise ValueError(f'Malformed token: {token}') from e
1916
1942
  logger.debug(f'Token data: {data!r}')
1917
1943
  try:
1918
- cookie_dict = json.loads(data)
1944
+ json_data = json.loads(data)
1919
1945
  except (json.JSONDecodeError, UnicodeDecodeError) as e:
1920
1946
  raise ValueError(f'Malformed token data: {data!r}') from e
1921
- if not isinstance(cookie_dict, dict):
1922
- raise ValueError(f'Malformed token JSON: {cookie_dict}')
1947
+ if not isinstance(json_data, dict):
1948
+ raise ValueError(f'Malformed token JSON: {json_data}')
1949
+
1950
+ if json_data.get('v') == 1:
1951
+ user_hash = json_data.get('user')
1952
+ cookie_dict = json_data['cookies']
1953
+ elif 'v' not in json_data:
1954
+ user_hash = None
1955
+ cookie_dict = json_data
1956
+ else:
1957
+ raise ValueError(f'Unsupported token version: {json_data.get("v")}')
1923
1958
 
1924
1959
  cookie_jar = cookiejar.MozillaCookieJar()
1925
1960
  for (name, value) in cookie_dict.items():
@@ -1962,6 +1997,15 @@ def api_login(endpoint: Optional[str] = None) -> None:
1962
1997
  server_common.get_api_cookie_jar_path())
1963
1998
  cookie_jar.save(cookie_jar_path)
1964
1999
 
2000
+ # If we have a user_hash, save it to the local file
2001
+ if user_hash is not None:
2002
+ if not common_utils.is_valid_user_hash(user_hash):
2003
+ raise ValueError(f'Invalid user hash: {user_hash}')
2004
+ with open(os.path.expanduser('~/.sky/user_hash'),
2005
+ 'w',
2006
+ encoding='utf-8') as f:
2007
+ f.write(user_hash)
2008
+
1965
2009
  # Set the endpoint in the config file
1966
2010
  config_path = pathlib.Path(
1967
2011
  skypilot_config.get_user_config_path()).expanduser()
sky/clouds/gcp.py CHANGED
@@ -997,10 +997,21 @@ class GCP(clouds.Cloud):
997
997
  return GCPIdentityType.SHARED_CREDENTIALS_FILE
998
998
 
999
999
  @classmethod
1000
- @annotations.lru_cache(scope='request',
1001
- maxsize=1) # Cache since getting identity is slow.
1002
1000
  def get_user_identities(cls) -> List[List[str]]:
1003
1001
  """Returns the email address + project id of the active user."""
1002
+ gcp_workspace_config = json.dumps(
1003
+ skypilot_config.get_workspace_cloud('gcp'), sort_keys=True)
1004
+ return cls._get_user_identities(gcp_workspace_config)
1005
+
1006
+ @classmethod
1007
+ @annotations.lru_cache(scope='request', maxsize=5)
1008
+ def _get_user_identities(
1009
+ cls, workspace_config: Optional[str]) -> List[List[str]]:
1010
+ # We add workspace_config in args to avoid caching the GCP identity
1011
+ # for when different workspace configs are used. Use json.dumps to
1012
+ # ensure the config is hashable.
1013
+ del workspace_config # Unused
1014
+
1004
1015
  try:
1005
1016
  account = _run_output('gcloud auth list --filter=status:ACTIVE '
1006
1017
  '--format="value(account)"')
@@ -1031,7 +1042,8 @@ class GCP(clouds.Cloud):
1031
1042
  f'{common_utils.format_exception(e, use_bracket=True)}'
1032
1043
  ) from e
1033
1044
  # TODO: Return a list of identities in the profile when we support
1034
- # automatic switching for GCP. Currently we only support one identity.
1045
+ # automatic switching for GCP. Currently we only support one
1046
+ # identity.
1035
1047
  return [[f'{account} [project_id={project_id}]']]
1036
1048
 
1037
1049
  @classmethod
@@ -1061,6 +1073,10 @@ class GCP(clouds.Cloud):
1061
1073
  return 'dryrun-project-id'
1062
1074
  # pylint: disable=import-outside-toplevel
1063
1075
  from google import auth # type: ignore
1076
+ config_project_id = skypilot_config.get_workspace_cloud('gcp').get(
1077
+ 'project_id', None)
1078
+ if config_project_id:
1079
+ return config_project_id
1064
1080
  _, project_id = auth.default()
1065
1081
  if project_id is None:
1066
1082
  raise exceptions.CloudUserIdentityError(
sky/core.py CHANGED
@@ -17,6 +17,7 @@ from sky import global_user_state
17
17
  from sky import models
18
18
  from sky import optimizer
19
19
  from sky import sky_logging
20
+ from sky import skypilot_config
20
21
  from sky import task as task_lib
21
22
  from sky.backends import backend_utils
22
23
  from sky.clouds import cloud as sky_cloud
@@ -1009,9 +1010,11 @@ def storage_delete(name: str) -> None:
1009
1010
  # = Catalog Observe =
1010
1011
  # ===================
1011
1012
  @usage_lib.entrypoint
1012
- def enabled_clouds() -> List[clouds.Cloud]:
1013
+ def enabled_clouds(workspace: Optional[str] = None) -> List[clouds.Cloud]:
1014
+ if workspace is None:
1015
+ workspace = skypilot_config.get_active_workspace()
1013
1016
  return global_user_state.get_cached_enabled_clouds(
1014
- sky_cloud.CloudCapability.COMPUTE)
1017
+ sky_cloud.CloudCapability.COMPUTE, workspace=workspace)
1015
1018
 
1016
1019
 
1017
1020
  @usage_lib.entrypoint
@@ -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/7e7ce4ff31d3977b.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/7e7ce4ff31d3977b.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-830f59b8404e96b8.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-8cfab319f9fb3ae8.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/ECKwDNS9v9y3_IKFZ2lpp/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ECKwDNS9v9y3_IKFZ2lpp/_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":"ECKwDNS9v9y3_IKFZ2lpp","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/d2cdba64c9202dd7.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/d2cdba64c9202dd7.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-dec800f9ef1b10f4.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/aHej19bZyl4hoHgrzPCn7/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/aHej19bZyl4hoHgrzPCn7/_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":"aHej19bZyl4hoHgrzPCn7","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -0,0 +1 @@
1
+ self.__BUILD_MANIFEST=function(s,c,e,t,a,r){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-6b0d9e5031b70c58.js"],"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],"/clusters":[s,e,c,t,r,"static/chunks/pages/clusters-9e6d1ec6e1ac5b29.js"],"/clusters/[cluster]":[s,e,c,t,a,r,"static/chunks/pages/clusters/[cluster]-9529d9e882a0e75c.js"],"/clusters/[cluster]/[job]":[s,c,"static/chunks/pages/clusters/[cluster]/[job]-37c042a356f8e608.js"],"/infra":[s,c,"static/chunks/pages/infra-e690d864aa00e2ea.js"],"/jobs":[s,e,c,t,a,"static/chunks/pages/jobs-73d5e0c369d00346.js"],"/jobs/[job]":[s,c,"static/chunks/pages/jobs/[job]-db6558a5ec687011.js"],"/users":[s,c,"static/chunks/pages/users-2d319455c3f1c3e2.js"],"/workspaces":["static/chunks/9f96d65d-5a3e4af68c26849e.js",s,e,"static/chunks/498-d7722313e5e5b4e6.js",c,t,a,"static/chunks/pages/workspaces-02a7b60f2ead275f.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/infra","/jobs","/jobs/[job]","/users","/workspaces"]}}("static/chunks/573-f17bd89d9f9118b3.js","static/chunks/480-ee58038f1a4afd5c.js","static/chunks/488-50d843fdb5396d32.js","static/chunks/734-5f5ce8f347b7f417.js","static/chunks/938-f347f6144075b0c8.js","static/chunks/578-7a4795009a56430c.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[480],{3850:function(e,t,n){n.d(t,{E9:function(){return w},J$:function(){return c},PC:function(){return f},Ps:function(){return a},QT:function(){return h},Vp:function(){return x},W2:function(){return i},Ye:function(){return d},aD:function(){return j},fp:function(){return u},fy:function(){return p},h0:function(){return m},lM:function(){return y},mU:function(){return g},oy:function(){return v}});var r=n(5893);n(7294);var s=n(8507),o=n(8586),l=n(9611);function a(e){return(0,r.jsx)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",stroke:"currentColor",strokeWidth:"0",strokeLinecap:"round",strokeLinejoin:"round",children:(0,r.jsx)("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"})})}function i(e){return(0,r.jsx)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:(0,r.jsx)("circle",{cx:"10",cy:"10",r:"8"})})}function c(e){return(0,r.jsx)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:(0,r.jsx)("circle",{cx:"10",cy:"10",r:"8"})})}function d(e){return(0,r.jsx)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",strokeLinejoin:"round",children:(0,r.jsx)("path",{d:"M6 12l4 4 8-8"})})}function u(e){return(0,r.jsxs)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",stroke:"currentColor",strokeWidth:"0",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1"}),(0,r.jsx)("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1"})]})}function h(e){return(0,r.jsxs)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2"}),(0,r.jsx)("rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2"}),(0,r.jsx)("line",{x1:"6",x2:"6.01",y1:"6",y2:"6"}),(0,r.jsx)("line",{x1:"6",x2:"6.01",y1:"18",y2:"18"})]})}function x(e){return(0,r.jsxs)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"}),(0,r.jsx)("rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"})]})}function f(e){return(0,r.jsxs)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("rect",{x:"4",y:"4",width:"16",height:"16",rx:"2",ry:"2"}),(0,r.jsx)("rect",{x:"9",y:"9",width:"6",height:"6"}),(0,r.jsx)("line",{x1:"9",y1:"1",x2:"9",y2:"4"}),(0,r.jsx)("line",{x1:"15",y1:"1",x2:"15",y2:"4"}),(0,r.jsx)("line",{x1:"9",y1:"20",x2:"9",y2:"23"}),(0,r.jsx)("line",{x1:"15",y1:"20",x2:"15",y2:"23"}),(0,r.jsx)("line",{x1:"20",y1:"9",x2:"23",y2:"9"}),(0,r.jsx)("line",{x1:"20",y1:"14",x2:"23",y2:"14"}),(0,r.jsx)("line",{x1:"1",y1:"9",x2:"4",y2:"9"}),(0,r.jsx)("line",{x1:"1",y1:"14",x2:"4",y2:"14"})]})}function m(e){return(0,r.jsxs)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"}),(0,r.jsx)("polyline",{points:"15 3 21 3 21 9"}),(0,r.jsx)("line",{x1:"10",y1:"14",x2:"21",y2:"3"})]})}function p(e){return(0,r.jsx)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:(0,r.jsx)("path",{d:"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"})})}function g(e){return(0,r.jsx)("svg",{...e,xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:(0,r.jsx)("path",{transform:"scale(0.85) translate(1.8, 1.8)",d:"M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zM18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z"})})}function w(e){return(0,r.jsx)("svg",{...e,stroke:"currentColor",fill:"currentColor",strokeWidth:"0",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,r.jsxs)("g",{children:[(0,r.jsx)("path",{fill:"none",d:"M0 0h24v24H0z"}),(0,r.jsx)("path",{d:"M3 18.5V5a3 3 0 0 1 3-3h14a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5A3.5 3.5 0 0 1 3 18.5zM19 20v-3H6.5a1.5 1.5 0 0 0 0 3H19zM10 4H6a1 1 0 0 0-1 1v10.337A3.486 3.486 0 0 1 6.5 15H19V4h-2v8l-3.5-2-3.5 2V4z"})]})})}let j=s.Z,v=o.Z;function y(e){return(0,r.jsx)(l.Z,{...e})}},9470:function(e,t,n){n.d(t,{A:function(){return w}});var r=n(5893),s=n(7294),o=n(5675),l=n.n(o),a=n(1163),i=n(1664),c=n.n(i),d=n(3850),u=n(3225),h=n(6989),x=n(3001);let f=(0,s.createContext)(null);function m(e){let{children:t}=e,[n,o]=(0,s.useState)(!0);return(0,r.jsx)(f.Provider,{value:{isSidebarOpen:n,toggleSidebar:()=>{o(e=>!e)}},children:t})}function p(){let e,t;let n=(0,a.useRouter)(),o=(0,x.X)(),[i,f]=(0,s.useState)(null),[m,p]=(0,s.useState)(!1),g=(0,s.useRef)(null);(0,s.useEffect)(()=>{fetch("".concat(u.f4,"/api/health")).then(e=>e.json()).then(e=>{e.user&&e.user.name&&f(e.user.name)}).catch(e=>{console.error("Error fetching user data:",e)})},[]),(0,s.useEffect)(()=>{function e(e){g.current&&!g.current.contains(e.target)&&p(!1)}return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[g]);let w=e=>n.pathname.startsWith(e),j=e=>{let t=w(e);return"inline-flex items-center border-b-2 ".concat(t?"border-transparent text-blue-600":"border-transparent hover:text-blue-600"," ").concat(o?"px-2 py-1":"px-1 pt-1 space-x-2")};return(0,r.jsx)("div",{className:"fixed top-0 left-0 right-0 bg-white z-30 h-14 px-4 border-b border-gray-200 shadow-sm",children:(0,r.jsxs)("div",{className:"flex items-center h-full",children:[(0,r.jsx)("div",{className:"flex items-center ".concat(o?"space-x-2 mr-2":"space-x-4 mr-6"),children:(0,r.jsx)(c(),{href:"/",className:"flex items-center px-1 pt-1 h-full",prefetch:!1,children:(0,r.jsx)("div",{className:"h-20 w-20 flex items-center justify-center",children:(0,r.jsx)(l(),{src:"".concat(u.GW,"/skypilot.svg"),alt:"SkyPilot Logo",width:80,height:80,priority:!0,className:"w-full h-full object-contain"})})})}),(0,r.jsxs)("div",{className:"flex items-center ".concat(o?"space-x-1":"space-x-2 md:space-x-4"," ").concat(o?"mr-2":"mr-6"),children:[(0,r.jsxs)(c(),{href:"/clusters",className:j("/clusters"),prefetch:!1,children:[(0,r.jsx)(d.QT,{className:"w-4 h-4"}),!o&&(0,r.jsx)("span",{children:"Clusters"})]}),(0,r.jsxs)(c(),{href:"/jobs",className:j("/jobs"),prefetch:!1,children:[(0,r.jsx)(d.Vp,{className:"w-4 h-4"}),!o&&(0,r.jsx)("span",{children:"Jobs"})]}),(0,r.jsx)("div",{className:"border-l border-gray-200 h-6 mx-1"}),(0,r.jsxs)(c(),{href:"/infra",className:j("/infra"),prefetch:!1,children:[(0,r.jsx)(d.PC,{className:"w-4 h-4"}),!o&&(0,r.jsx)("span",{children:"Infra"})]}),(0,r.jsxs)(c(),{href:"/workspaces",className:j("/workspaces"),prefetch:!1,children:[(0,r.jsx)(d.E9,{className:"w-4 h-4"}),!o&&(0,r.jsx)("span",{children:"Workspaces"})]}),(0,r.jsxs)(c(),{href:"/users",className:j("/users"),prefetch:!1,children:[(0,r.jsx)(d.oy,{className:"w-4 h-4"}),!o&&(0,r.jsx)("span",{children:"Users"})]})]}),(0,r.jsxs)("div",{className:"flex items-center space-x-1 ".concat(o?"ml-0":"ml-auto"),children:[(0,r.jsx)(h.WH,{content:"Documentation",className:"text-sm text-muted-foreground",children:(0,r.jsxs)("a",{href:"https://skypilot.readthedocs.io/en/latest/",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center px-2 py-1 text-gray-600 hover:text-blue-600 transition-colors duration-150 cursor-pointer",title:"Docs",children:[!o&&(0,r.jsx)("span",{className:"mr-1",children:"Docs"}),(0,r.jsx)(d.h0,{className:"".concat(o?"w-4 h-4":"w-3.5 h-3.5")})]})}),(0,r.jsx)("div",{className:"border-l border-gray-200 h-6 mx-1"}),(0,r.jsx)(h.WH,{content:"GitHub Repository",className:"text-sm text-muted-foreground",children:(0,r.jsx)("a",{href:"https://github.com/skypilot-org/skypilot",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center justify-center p-2 rounded-full text-gray-600 hover:bg-gray-100 transition-colors duration-150 cursor-pointer",title:"GitHub",children:(0,r.jsx)(d.fy,{className:"".concat(o?"w-4 h-4":"w-5 h-5")})})}),(0,r.jsx)(h.WH,{content:"Join Slack",className:"text-sm text-muted-foreground",children:(0,r.jsx)("a",{href:"https://slack.skypilot.co/",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center justify-center p-2 rounded-full text-gray-600 hover:bg-gray-100 transition-colors duration-150 cursor-pointer",title:"Slack",children:(0,r.jsx)(d.mU,{className:"".concat(o?"w-4 h-4":"w-5 h-5")})})}),(0,r.jsx)(h.WH,{content:"Leave Feedback",className:"text-sm text-muted-foreground",children:(0,r.jsx)("a",{href:"https://github.com/skypilot-org/skypilot/issues/new",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center justify-center p-2 rounded-full text-gray-600 hover:bg-gray-100 transition-colors duration-150 cursor-pointer",title:"Leave Feedback",children:(0,r.jsx)(d.aD,{className:"".concat(o?"w-4 h-4":"w-5 h-5")})})})]}),i&&(0,r.jsxs)("div",{className:"relative ml-2",ref:g,children:[(0,r.jsx)("button",{onClick:()=>p(!m),className:"inline-flex items-center justify-center p-2 rounded-full text-gray-600 hover:bg-gray-100 transition-colors duration-150 cursor-pointer",title:"User Profile",children:(0,r.jsx)(d.lM,{className:"".concat(o?"w-5 h-5":"w-6 h-6")})}),m&&(0,r.jsxs)("div",{className:"absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg z-50 border border-gray-200",children:[(e=i,t=null,i&&i.includes("@")&&(e=i.split("@")[0],t=i),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("div",{className:"px-4 pt-2 pb-1 text-sm font-medium text-gray-900",children:e}),t&&(0,r.jsx)("div",{className:"px-4 pt-0 pb-2 text-xs text-gray-500",children:t})]})),(0,r.jsx)("div",{className:"border-t border-gray-200 mx-1 my-1"}),(0,r.jsx)(c(),{href:"/users",className:"block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-blue-600",onClick:()=>p(!1),prefetch:!1,children:"See all users"})]})]})]})})}function g(e){let{children:t,highlighted:n}=e;return(0,x.X)(),(0,r.jsxs)("div",{className:"min-h-screen bg-gray-50",children:[(0,r.jsx)("div",{className:"fixed top-0 left-0 right-0 z-50 shadow-sm",children:(0,r.jsx)(p,{})}),(0,r.jsx)("div",{className:"transition-all duration-200 ease-in-out min-h-screen",style:{paddingTop:"56px"},children:(0,r.jsx)("main",{className:"p-6",children:t})})]})}function w(e){return(0,r.jsx)(m,{children:(0,r.jsx)(g,{...e})})}},8950:function(e,t,n){n.d(t,{Bw:function(){return m},Ph:function(){return d},Ql:function(){return p},i4:function(){return h},ki:function(){return u}});var r=n(5893),s=n(7294),o=n(2067),l=n(5895),a=n(7242),i=n(282),c=n(2350);let d=o.fC;o.ZA;let u=o.B4,h=s.forwardRef((e,t)=>{let{className:n,children:s,...a}=e;return(0,r.jsxs)(o.xz,{ref:t,className:(0,c.cn)("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",n),...a,children:[s,(0,r.jsx)(o.JO,{asChild:!0,children:(0,r.jsx)(l.Z,{className:"h-4 w-4 opacity-50"})})]})});h.displayName=o.xz.displayName;let x=s.forwardRef((e,t)=>{let{className:n,...s}=e;return(0,r.jsx)(o.u_,{ref:t,className:(0,c.cn)("flex cursor-default items-center justify-center py-1",n),...s,children:(0,r.jsx)(a.Z,{className:"h-4 w-4"})})});x.displayName=o.u_.displayName;let f=s.forwardRef((e,t)=>{let{className:n,...s}=e;return(0,r.jsx)(o.$G,{ref:t,className:(0,c.cn)("flex cursor-default items-center justify-center py-1",n),...s,children:(0,r.jsx)(l.Z,{className:"h-4 w-4"})})});f.displayName=o.$G.displayName;let m=s.forwardRef((e,t)=>{let{className:n,children:s,position:l="popper",...a}=e;return(0,r.jsx)(o.h_,{children:(0,r.jsxs)(o.VY,{ref:t,className:(0,c.cn)("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2","popper"===l&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",n),position:l,...a,children:[(0,r.jsx)(x,{}),(0,r.jsx)(o.l_,{className:(0,c.cn)("p-1","popper"===l&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:s}),(0,r.jsx)(f,{})]})})});m.displayName=o.VY.displayName,s.forwardRef((e,t)=>{let{className:n,...s}=e;return(0,r.jsx)(o.__,{ref:t,className:(0,c.cn)("py-1.5 pl-8 pr-2 text-sm font-semibold",n),...s})}).displayName=o.__.displayName;let p=s.forwardRef((e,t)=>{let{className:n,children:s,...l}=e;return(0,r.jsxs)(o.ck,{ref:t,className:(0,c.cn)("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",n),...l,children:[(0,r.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,r.jsx)(o.wU,{children:(0,r.jsx)(i.Z,{className:"h-4 w-4"})})}),(0,r.jsx)(o.eT,{children:s})]})});p.displayName=o.ck.displayName,s.forwardRef((e,t)=>{let{className:n,...s}=e;return(0,r.jsx)(o.Z0,{ref:t,className:(0,c.cn)("-mx-1 my-1 h-px bg-muted",n),...s})}).displayName=o.Z0.displayName},6989:function(e,t,n){n.d(t,{$B:function(){return g},GV:function(){return d},LU:function(){return m},Md:function(){return f},WH:function(){return x},q8:function(){return p},yc:function(){return i}});var r=n(5893),s=n(7294),o=n(3302),l=n(1886),a=n(8950);let i=3e4;function c(e){return e.charAt(0).toUpperCase()+e.slice(1)}function d(e){if(!e)return"N/A";let t=new Date;return 7>Math.abs((t-e)/864e5)?(0,r.jsx)(x,{content:u(e),className:"capitalize text-sm text-muted-foreground",children:c((0,l.B)(e,t,{addSuffix:!0}))}):(0,r.jsx)(x,{content:c(u(e)),className:"text-sm text-muted-foreground",children:c(e.toLocaleString("en-CA",{year:"numeric",month:"2-digit",day:"2-digit"}).replace(",",""))})}function u(e){return e.toLocaleString("en-CA",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1,timeZoneName:"short"}).replace(",","")}let h={placement:"bottom",color:"default"},x=e=>{let{children:t,...n}=e,s=n.content;return n.content=void 0,(0,r.jsx)(o.e,{...h,...n,content:(0,r.jsx)("span",{className:"left-full w-max px-2 py-1 text-sm text-gray-100 bg-gray-500 text-sm capitalize rounded",children:s}),children:t})},f=e=>{let{children:t,...n}=e,s=n.content;return n.content=void 0,(0,r.jsx)(o.e,{...h,...n,content:(0,r.jsx)("span",{className:"left-full w-max px-2 py-1 text-sm text-gray-100 bg-gray-500 text-sm rounded",children:s}),children:t})};function m(e){if(!e&&0!==e)return"-";let t=e=Math.floor(e),n="",r=0;for(let e of[{value:86400,label:"d"},{value:3600,label:"h"},{value:60,label:"m"},{value:1,label:"s"}])if(t>=e.value&&r<2){let s=Math.floor(t/e.value);n+="".concat(s).concat(e.label," "),t%=e.value,r++}return n.trim()||"0s"}function p(e){return e?(e=e.split("\n").filter(e=>!e.match(/<rich_.*?\[bold cyan\]/)&&!e.match(/<rich_.*>.*<\/rich_.*>/)&&!e.match(/├──/)&&!e.match(/└──/)).join("\n").replace(/\x1b\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGKH]/g,"")).split("\n").map(e=>{let t=e.match(/^([IWED])\s+(\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+([^:]+:\d+\])(.*)/);if(t){let[e,n,r,s,o]=t,l={I:"INFO",W:"WARNING",E:"ERROR",D:"DEBUG"}[n]||"";return'<span class="log-line '.concat(l,'"><span class="level">').concat(n,'</span><span class="timestamp">').concat(r,'</span><span class="location">').concat(s,'</span><span class="message">').concat(o,"</span></span>")}let n=e.match(/^(\([^)]+\))(.*)$/);if(n){let[e,t,r]=n;return'<span class="log-line"><span class="log-prefix">'.concat(t,'</span><span class="log-rest">').concat(r,"</span></span>")}return'<span class="log-line"><span class="message">'.concat(e,"</span></span>")}).join("\n"):""}function g(e){let{logs:t,controller:n=!1}=e,[o,l]=(0,s.useState)("all"),[i,c]=(0,s.useState)(t),[d,u]=(0,s.useState)([]);return(0,s.useEffect)(()=>{u(function(e){let t;let n=/\((head|worker\d+),/g,r=new Set;for(;null!==(t=n.exec(e));)r.add(t[1]);return Array.from(r).sort((e,t)=>"head"===e?-1:"head"===t?1:e.localeCompare(t,void 0,{numeric:!0,sensitivity:"base"}))}(t))},[t]),(0,s.useEffect)(()=>{"all"===o?c(t):c(t.split("\n").filter(e=>e.includes("(".concat(o,","))).join("\n"))},[o,t]),(0,r.jsxs)("div",{children:[(0,r.jsx)("style",{children:'\n .logs-container {\n background-color: #f7f7f7;\n padding: 16px;\n max-height: calc(100vh - 300px);\n overflow-y: auto;\n overflow-x: hidden;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n line-height: 1.5;\n border-radius: 6px;\n min-height: fit-content;\n }\n\n .log-line {\n display: block;\n white-space: pre-wrap;\n margin: 2px 0;\n }\n\n .log-line .level {\n display: inline;\n width: 1ch;\n margin-right: 1ch;\n font-weight: bold;\n }\n\n .log-line.INFO .level {\n color: #2563eb;\n }\n\n .log-line.WARNING .level {\n color: #d97706;\n }\n\n .log-line.ERROR .level {\n color: #dc2626;\n }\n\n .log-line.DEBUG .level {\n color: #6b7280;\n }\n\n .log-line .timestamp {\n color: #059669;\n margin-right: 1ch;\n white-space: nowrap;\n }\n\n .log-line .location {\n color: #6366f1;\n margin-right: 1ch;\n white-space: nowrap;\n }\n\n .log-line .message {\n color: #111827;\n word-break: break-word;\n white-space: pre-wrap;\n }\n\n .log-line .log-prefix {\n color: #6366f1;\n font-weight: 500;\n }\n\n .log-line .log-rest {\n color: #111827;\n word-break: break-word;\n white-space: pre-wrap;\n }\n'}),!n&&(0,r.jsx)("div",{style:{marginBottom:"1rem"},children:(0,r.jsxs)(a.Ph,{onValueChange:e=>l(e),value:o,children:[(0,r.jsx)(a.i4,{"aria-label":"Node",className:"focus:ring-0 focus:ring-offset-0",children:(0,r.jsx)(a.ki,{placeholder:"Select Node"})}),(0,r.jsxs)(a.Bw,{children:[(0,r.jsx)(a.Ql,{value:"all",children:"All Nodes"}),d.map(e=>(0,r.jsx)(a.Ql,{value:e,children:e},e))]})]})}),(0,r.jsx)("div",{className:"logs-container",dangerouslySetInnerHTML:{__html:p(i)}})]})}},5821:function(e,t,n){n.d(t,{C:function(){return r}});function r(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"info",n=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 s=document.createElement("div");switch(s.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":s.className+=" bg-green-100 border-green-500 text-green-800";break;case"error":s.className+=" bg-red-100 border-red-500 text-red-800";break;case"warning":s.className+=" bg-yellow-100 border-yellow-500 text-yellow-800";break;default:s.className+=" bg-blue-100 border-blue-500 text-blue-800"}return s.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(s),s.querySelector("button").addEventListener("click",()=>{r.removeChild(s)}),setTimeout(()=>{r.contains(s)&&r.removeChild(s)},n),s}},3001:function(e,t,n){n.d(t,{X:function(){return s}});var r=n(7294);function s(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:768,[t,n]=(0,r.useState)(!1);return(0,r.useEffect)(()=>{let t=()=>{n(window.innerWidth<e)};return t(),window.addEventListener("resize",t),()=>{window.removeEventListener("resize",t)}},[e]),t}},2350:function(e,t,n){n.d(t,{cn:function(){return o}});var r=n(512),s=n(8388);function o(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return(0,s.m6)((0,r.W)(t))}}}]);
@@ -0,0 +1,15 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[488],{8671:function(e,n,t){t.d(n,{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,t(998).Z)("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]])},3767:function(e,n,t){t.d(n,{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,t(998).Z)("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]])},6327:function(e,n,t){t.d(n,{x8:function(){return ea},VY:function(){return eo},dk:function(){return el},aV:function(){return er},h_:function(){return et},fC:function(){return ee},Dx:function(){return ei},xz:function(){return en}});var r=t(7294),o=t(6206),i=t(8771),l=t(5360),a=t(1276),u=t(7342),s=t(6063),d=t(5420),c=t(2651),f=t(9981),p=e=>{let n,t;let{present:o,children:l}=e,a=function(e){var n,t;let[o,i]=r.useState(),l=r.useRef(null),a=r.useRef(e),u=r.useRef("none"),[s,d]=(n=e?"mounted":"unmounted",t={mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}},r.useReducer((e,n)=>t[e][n]??e,n));return r.useEffect(()=>{let e=m(l.current);u.current="mounted"===s?e:"none"},[s]),(0,f.b)(()=>{let n=l.current,t=a.current;if(t!==e){let r=u.current,o=m(n);e?d("MOUNT"):"none"===o||n?.display==="none"?d("UNMOUNT"):t&&r!==o?d("ANIMATION_OUT"):d("UNMOUNT"),a.current=e}},[e,d]),(0,f.b)(()=>{if(o){let e;let n=o.ownerDocument.defaultView??window,t=t=>{let r=m(l.current).includes(t.animationName);if(t.target===o&&r&&(d("ANIMATION_END"),!a.current)){let t=o.style.animationFillMode;o.style.animationFillMode="forwards",e=n.setTimeout(()=>{"forwards"===o.style.animationFillMode&&(o.style.animationFillMode=t)})}},r=e=>{e.target===o&&(u.current=m(l.current))};return o.addEventListener("animationstart",r),o.addEventListener("animationcancel",t),o.addEventListener("animationend",t),()=>{n.clearTimeout(e),o.removeEventListener("animationstart",r),o.removeEventListener("animationcancel",t),o.removeEventListener("animationend",t)}}d("ANIMATION_END")},[o,d]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:r.useCallback(e=>{l.current=e?getComputedStyle(e):null,i(e)},[])}}(o),u="function"==typeof l?l({present:a.isPresent}):r.Children.only(l),s=(0,i.e)(a.ref,(n=Object.getOwnPropertyDescriptor(u.props,"ref")?.get)&&"isReactWarning"in n&&n.isReactWarning?u.ref:(n=Object.getOwnPropertyDescriptor(u,"ref")?.get)&&"isReactWarning"in n&&n.isReactWarning?u.props.ref:u.props.ref||u.ref);return"function"==typeof l||a.isPresent?r.cloneElement(u,{ref:s}):null};function m(e){return e?.animationName||"none"}p.displayName="Presence";var g=t(5320),v=t(7552),y=t(6223),N=t(3541),h=t(8426),D=t(5893),O="Dialog",[b,R]=(0,l.b)(O),[x,M]=b(O),j=e=>{let{__scopeDialog:n,children:t,open:o,defaultOpen:i,onOpenChange:l,modal:s=!0}=e,d=r.useRef(null),c=r.useRef(null),[f,p]=(0,u.T)({prop:o,defaultProp:i??!1,onChange:l,caller:O});return(0,D.jsx)(x,{scope:n,triggerRef:d,contentRef:c,contentId:(0,a.M)(),titleId:(0,a.M)(),descriptionId:(0,a.M)(),open:f,onOpenChange:p,onOpenToggle:r.useCallback(()=>p(e=>!e),[p]),modal:s,children:t})};j.displayName=O;var w="DialogTrigger",I=r.forwardRef((e,n)=>{let{__scopeDialog:t,...r}=e,l=M(w,t),a=(0,i.e)(n,l.triggerRef);return(0,D.jsx)(g.WV.button,{type:"button","aria-haspopup":"dialog","aria-expanded":l.open,"aria-controls":l.contentId,"data-state":H(l.open),...r,ref:a,onClick:(0,o.M)(e.onClick,l.onOpenToggle)})});I.displayName=w;var C="DialogPortal",[E,_]=b(C,{forceMount:void 0}),T=e=>{let{__scopeDialog:n,forceMount:t,children:o,container:i}=e,l=M(C,n);return(0,D.jsx)(E,{scope:n,forceMount:t,children:r.Children.map(o,e=>(0,D.jsx)(p,{present:t||l.open,children:(0,D.jsx)(c.h,{asChild:!0,container:i,children:e})}))})};T.displayName=C;var A="DialogOverlay",k=r.forwardRef((e,n)=>{let t=_(A,e.__scopeDialog),{forceMount:r=t.forceMount,...o}=e,i=M(A,e.__scopeDialog);return i.modal?(0,D.jsx)(p,{present:r||i.open,children:(0,D.jsx)(P,{...o,ref:n})}):null});k.displayName=A;var F=(0,h.Z8)("DialogOverlay.RemoveScroll"),P=r.forwardRef((e,n)=>{let{__scopeDialog:t,...r}=e,o=M(A,t);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:n,style:{pointerEvents:"auto",...r.style}})})}),W="DialogContent",U=r.forwardRef((e,n)=>{let t=_(W,e.__scopeDialog),{forceMount:r=t.forceMount,...o}=e,i=M(W,e.__scopeDialog);return(0,D.jsx)(p,{present:r||i.open,children:i.modal?(0,D.jsx)(V,{...o,ref:n}):(0,D.jsx)(S,{...o,ref:n})})});U.displayName=W;var V=r.forwardRef((e,n)=>{let t=M(W,e.__scopeDialog),l=r.useRef(null),a=(0,i.e)(n,t.contentRef,l);return r.useEffect(()=>{let e=l.current;if(e)return(0,N.Ry)(e)},[]),(0,D.jsx)(Z,{...e,ref:a,trapFocus:t.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:(0,o.M)(e.onCloseAutoFocus,e=>{e.preventDefault(),t.triggerRef.current?.focus()}),onPointerDownOutside:(0,o.M)(e.onPointerDownOutside,e=>{let n=e.detail.originalEvent,t=0===n.button&&!0===n.ctrlKey;(2===n.button||t)&&e.preventDefault()}),onFocusOutside:(0,o.M)(e.onFocusOutside,e=>e.preventDefault())})}),S=r.forwardRef((e,n)=>{let t=M(W,e.__scopeDialog),o=r.useRef(!1),i=r.useRef(!1);return(0,D.jsx)(Z,{...e,ref:n,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:n=>{e.onCloseAutoFocus?.(n),n.defaultPrevented||(o.current||t.triggerRef.current?.focus(),n.preventDefault()),o.current=!1,i.current=!1},onInteractOutside:n=>{e.onInteractOutside?.(n),n.defaultPrevented||(o.current=!0,"pointerdown"!==n.detail.originalEvent.type||(i.current=!0));let r=n.target;t.triggerRef.current?.contains(r)&&n.preventDefault(),"focusin"===n.detail.originalEvent.type&&i.current&&n.preventDefault()}})}),Z=r.forwardRef((e,n)=>{let{__scopeDialog:t,trapFocus:o,onOpenAutoFocus:l,onCloseAutoFocus:a,...u}=e,c=M(W,t),f=r.useRef(null),p=(0,i.e)(n,f);return(0,v.EW)(),(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(d.M,{asChild:!0,loop:!0,trapped:o,onMountAutoFocus:l,onUnmountAutoFocus:a,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,n)=>{let{__scopeDialog:t,...r}=e,o=M(L,t);return(0,D.jsx)(g.WV.h2,{id:o.titleId,...r,ref:n})});$.displayName=L;var B="DialogDescription",z=r.forwardRef((e,n)=>{let{__scopeDialog:t,...r}=e,o=M(B,t);return(0,D.jsx)(g.WV.p,{id:o.descriptionId,...r,ref:n})});z.displayName=B;var X="DialogClose",q=r.forwardRef((e,n)=>{let{__scopeDialog:t,...r}=e,i=M(X,t);return(0,D.jsx)(g.WV.button,{type:"button",...r,ref:n,onClick:(0,o.M)(e.onClick,()=>i.onOpenChange(!1))})});function H(e){return e?"open":"closed"}q.displayName=X;var K="DialogTitleWarning",[Y,G]=(0,l.k)(K,{contentName:W,titleName:L,docsSlug:"dialog"}),J=({titleId:e})=>{let n=G(K),t=`\`${n.contentName}\` requires a \`${n.titleName}\` for the component to be accessible for screen reader users.
12
+
13
+ If you want to hide the \`${n.titleName}\`, you can wrap it with our VisuallyHidden component.
14
+
15
+ For more information, see https://radix-ui.com/primitives/docs/components/${n.docsSlug}`;return r.useEffect(()=>{e&&!document.getElementById(e)&&console.error(t)},[t,e]),null},Q=({contentRef:e,descriptionId:n})=>{let t=G("DialogDescriptionWarning"),o=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${t.contentName}}.`;return r.useEffect(()=>{let t=e.current?.getAttribute("aria-describedby");n&&t&&!document.getElementById(n)&&console.warn(o)},[o,e,n]),null},ee=j,en=I,et=T,er=k,eo=U,ei=$,el=z,ea=q},2003:function(e,n,t){t.d(n,{j:function(){return l}});var r=t(512);let o=e=>"boolean"==typeof e?`${e}`:0===e?"0":e,i=r.W,l=(e,n)=>t=>{var r;if((null==n?void 0:n.variants)==null)return i(e,null==t?void 0:t.class,null==t?void 0:t.className);let{variants:l,defaultVariants:a}=n,u=Object.keys(l).map(e=>{let n=null==t?void 0:t[e],r=null==a?void 0:a[e];if(null===n)return null;let i=o(n)||o(r);return l[e][i]}),s=t&&Object.entries(t).reduce((e,n)=>{let[t,r]=n;return void 0===r||(e[t]=r),e},{});return i(e,u,null==n?void 0:null===(r=n.compoundVariants)||void 0===r?void 0:r.reduce((e,n)=>{let{class:t,className:r,...o}=n;return Object.entries(o).every(e=>{let[n,t]=e;return Array.isArray(t)?t.includes({...a,...s}[n]):({...a,...s})[n]===t})?[...e,t,r]:e},[]),null==t?void 0:t.class,null==t?void 0:t.className)}}}]);