skypilot-nightly 1.0.0.dev20250915__py3-none-any.whl → 1.0.0.dev20250918__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of skypilot-nightly might be problematic. Click here for more details.

Files changed (78) hide show
  1. sky/__init__.py +4 -2
  2. sky/adaptors/primeintellect.py +1 -0
  3. sky/adaptors/seeweb.py +68 -4
  4. sky/authentication.py +25 -0
  5. sky/backends/__init__.py +3 -2
  6. sky/backends/backend_utils.py +16 -12
  7. sky/backends/cloud_vm_ray_backend.py +61 -4
  8. sky/catalog/primeintellect_catalog.py +95 -0
  9. sky/client/sdk.py +6 -0
  10. sky/clouds/__init__.py +2 -0
  11. sky/clouds/primeintellect.py +314 -0
  12. sky/core.py +10 -3
  13. sky/dashboard/out/404.html +1 -1
  14. sky/dashboard/out/_next/static/chunks/3015-ba5be550eb80fd8c.js +1 -0
  15. sky/dashboard/out/_next/static/chunks/5339.4a881570243431a5.js +51 -0
  16. sky/dashboard/out/_next/static/chunks/{6856-e0754534b3015377.js → 6856-9a2538f38c004652.js} +1 -1
  17. sky/dashboard/out/_next/static/chunks/{6990-11c8e9b982e8ffec.js → 6990-f6818c84ed8f1c86.js} +1 -1
  18. sky/dashboard/out/_next/static/chunks/8969-a3e3f0683e19d340.js +1 -0
  19. sky/dashboard/out/_next/static/chunks/9037-472ee1222cb1e158.js +6 -0
  20. sky/dashboard/out/_next/static/chunks/{webpack-d1e29b3aa66bf4cf.js → webpack-487697b47d8c5e50.js} +1 -1
  21. sky/dashboard/out/_next/static/{dG6B0i0HO4jIoKb4ZFYJ_ → k1mo5xWZrV9djgjd0moOT}/_buildManifest.js +1 -1
  22. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  23. sky/dashboard/out/clusters/[cluster].html +1 -1
  24. sky/dashboard/out/clusters.html +1 -1
  25. sky/dashboard/out/config.html +1 -1
  26. sky/dashboard/out/index.html +1 -1
  27. sky/dashboard/out/infra/[context].html +1 -1
  28. sky/dashboard/out/infra.html +1 -1
  29. sky/dashboard/out/jobs/[job].html +1 -1
  30. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  31. sky/dashboard/out/jobs.html +1 -1
  32. sky/dashboard/out/users.html +1 -1
  33. sky/dashboard/out/volumes.html +1 -1
  34. sky/dashboard/out/workspace/new.html +1 -1
  35. sky/dashboard/out/workspaces/[name].html +1 -1
  36. sky/dashboard/out/workspaces.html +1 -1
  37. sky/global_user_state.py +42 -34
  38. sky/jobs/server/server.py +14 -1
  39. sky/jobs/state.py +26 -1
  40. sky/provision/__init__.py +1 -0
  41. sky/provision/docker_utils.py +50 -3
  42. sky/provision/instance_setup.py +15 -1
  43. sky/provision/lambda_cloud/instance.py +12 -11
  44. sky/provision/primeintellect/__init__.py +10 -0
  45. sky/provision/primeintellect/config.py +11 -0
  46. sky/provision/primeintellect/instance.py +454 -0
  47. sky/provision/primeintellect/utils.py +398 -0
  48. sky/resources.py +9 -1
  49. sky/schemas/generated/servev1_pb2.py +58 -0
  50. sky/schemas/generated/servev1_pb2.pyi +115 -0
  51. sky/schemas/generated/servev1_pb2_grpc.py +322 -0
  52. sky/serve/serve_rpc_utils.py +179 -0
  53. sky/serve/serve_utils.py +29 -12
  54. sky/serve/server/core.py +37 -19
  55. sky/serve/server/impl.py +221 -129
  56. sky/server/common.py +13 -0
  57. sky/server/constants.py +3 -0
  58. sky/server/requests/executor.py +23 -6
  59. sky/server/server.py +10 -5
  60. sky/setup_files/dependencies.py +1 -0
  61. sky/skylet/constants.py +5 -3
  62. sky/skylet/services.py +98 -0
  63. sky/skylet/skylet.py +3 -1
  64. sky/skypilot_config.py +10 -3
  65. sky/templates/kubernetes-ray.yml.j2 +22 -12
  66. sky/templates/primeintellect-ray.yml.j2 +71 -0
  67. {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/METADATA +39 -38
  68. {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/RECORD +74 -62
  69. sky/dashboard/out/_next/static/chunks/3015-2ea98b57e318bd6e.js +0 -1
  70. sky/dashboard/out/_next/static/chunks/5339.c033b29835da0f35.js +0 -51
  71. sky/dashboard/out/_next/static/chunks/8969-0487dfbf149d9e53.js +0 -1
  72. sky/dashboard/out/_next/static/chunks/9037-f9800e64eb05dd1c.js +0 -6
  73. /sky/dashboard/out/_next/static/chunks/pages/{workspaces-7598c33a746cdc91.js → workspaces-7528cc0ef8c522c5.js} +0 -0
  74. /sky/dashboard/out/_next/static/{dG6B0i0HO4jIoKb4ZFYJ_ → k1mo5xWZrV9djgjd0moOT}/_ssgManifest.js +0 -0
  75. {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/WHEEL +0 -0
  76. {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/entry_points.txt +0 -0
  77. {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/licenses/LICENSE +0 -0
  78. {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/top_level.txt +0 -0
sky/serve/server/impl.py CHANGED
@@ -5,6 +5,7 @@ import shlex
5
5
  import signal
6
6
  import tempfile
7
7
  import threading
8
+ import typing
8
9
  from typing import Any, Dict, List, Optional, Set, Tuple, Union
9
10
  import uuid
10
11
 
@@ -17,10 +18,12 @@ from sky import execution
17
18
  from sky import sky_logging
18
19
  from sky import skypilot_config
19
20
  from sky import task as task_lib
21
+ from sky.adaptors import common as adaptors_common
20
22
  from sky.backends import backend_utils
21
23
  from sky.catalog import common as service_catalog_common
22
24
  from sky.data import storage as storage_lib
23
25
  from sky.serve import constants as serve_constants
26
+ from sky.serve import serve_rpc_utils
24
27
  from sky.serve import serve_state
25
28
  from sky.serve import serve_utils
26
29
  from sky.skylet import constants
@@ -36,6 +39,11 @@ from sky.utils import subprocess_utils
36
39
  from sky.utils import ux_utils
37
40
  from sky.utils import yaml_utils
38
41
 
42
+ if typing.TYPE_CHECKING:
43
+ import grpc
44
+ else:
45
+ grpc = adaptors_common.LazyImport('grpc')
46
+
39
47
  logger = sky_logging.init_logger(__name__)
40
48
 
41
49
 
@@ -78,24 +86,35 @@ def _get_service_record(
78
86
  """Get the service record."""
79
87
  noun = 'pool' if pool else 'service'
80
88
 
81
- code = serve_utils.ServeCodeGen.get_service_status([service_name],
82
- pool=pool)
83
- returncode, serve_status_payload, stderr = backend.run_on_head(
84
- handle,
85
- code,
86
- require_outputs=True,
87
- stream_logs=False,
88
- separate_stderr=True)
89
- try:
90
- subprocess_utils.handle_returncode(returncode,
91
- code,
92
- f'Failed to get {noun} status',
93
- stderr,
94
- stream_logs=True)
95
- except exceptions.CommandError as e:
96
- raise RuntimeError(e.error_msg) from e
89
+ assert isinstance(handle, backends.CloudVmRayResourceHandle)
90
+ use_legacy = not handle.is_grpc_enabled_with_flag
97
91
 
98
- service_statuses = serve_utils.load_service_status(serve_status_payload)
92
+ if handle.is_grpc_enabled_with_flag:
93
+ try:
94
+ service_statuses = serve_rpc_utils.RpcRunner.get_service_status(
95
+ handle, [service_name], pool)
96
+ except exceptions.SkyletMethodNotImplementedError:
97
+ use_legacy = True
98
+
99
+ if use_legacy:
100
+ code = serve_utils.ServeCodeGen.get_service_status([service_name],
101
+ pool=pool)
102
+ returncode, serve_status_payload, stderr = backend.run_on_head(
103
+ handle,
104
+ code,
105
+ require_outputs=True,
106
+ stream_logs=False,
107
+ separate_stderr=True)
108
+ try:
109
+ subprocess_utils.handle_returncode(returncode,
110
+ code,
111
+ f'Failed to get {noun} status',
112
+ stderr,
113
+ stream_logs=True)
114
+ except exceptions.CommandError as e:
115
+ raise RuntimeError(e.error_msg) from e
116
+
117
+ service_statuses = serve_utils.load_service_status(serve_status_payload)
99
118
 
100
119
  assert len(service_statuses) <= 1, service_statuses
101
120
  if not service_statuses:
@@ -287,30 +306,44 @@ def up(
287
306
  fore = colorama.Fore
288
307
 
289
308
  assert controller_job_id is not None and controller_handle is not None
309
+ assert isinstance(controller_handle, backends.CloudVmRayResourceHandle)
310
+ backend = backend_utils.get_backend_from_handle(controller_handle)
311
+ assert isinstance(backend, backends.CloudVmRayBackend)
290
312
  # TODO(tian): Cache endpoint locally to speedup. Endpoint won't
291
313
  # change after the first time, so there is no consistency issue.
292
- with rich_utils.safe_status(
293
- ux_utils.spinner_message(
294
- f'Waiting for the {noun} to register')):
295
- # This function will check the controller job id in the database
296
- # and return the endpoint if the job id matches. Otherwise it will
297
- # return None.
298
- code = serve_utils.ServeCodeGen.wait_service_registration(
299
- service_name, controller_job_id, pool)
300
- backend = backend_utils.get_backend_from_handle(controller_handle)
301
- assert isinstance(backend, backends.CloudVmRayBackend)
302
- assert isinstance(controller_handle,
303
- backends.CloudVmRayResourceHandle)
304
- returncode, lb_port_payload, _ = backend.run_on_head(
305
- controller_handle,
306
- code,
307
- require_outputs=True,
308
- stream_logs=False)
309
314
  try:
310
- subprocess_utils.handle_returncode(
311
- returncode, code, f'Failed to wait for {noun} initialization',
312
- lb_port_payload)
313
- except exceptions.CommandError:
315
+ with rich_utils.safe_status(
316
+ ux_utils.spinner_message(
317
+ f'Waiting for the {noun} to register')):
318
+ # This function will check the controller job id in the database
319
+ # and return the endpoint if the job id matches. Otherwise it
320
+ # will return None.
321
+ use_legacy = not controller_handle.is_grpc_enabled_with_flag
322
+
323
+ if controller_handle.is_grpc_enabled_with_flag:
324
+ try:
325
+ lb_port = serve_rpc_utils.RpcRunner.wait_service_registration( # pylint: disable=line-too-long
326
+ controller_handle, service_name, controller_job_id,
327
+ pool)
328
+ except exceptions.SkyletMethodNotImplementedError:
329
+ use_legacy = True
330
+
331
+ if use_legacy:
332
+ code = serve_utils.ServeCodeGen.wait_service_registration(
333
+ service_name, controller_job_id, pool)
334
+ returncode, lb_port_payload, _ = backend.run_on_head(
335
+ controller_handle,
336
+ code,
337
+ require_outputs=True,
338
+ stream_logs=False)
339
+ subprocess_utils.handle_returncode(
340
+ returncode, code,
341
+ f'Failed to wait for {noun} initialization',
342
+ lb_port_payload)
343
+ lb_port = serve_utils.load_service_initialization_result(
344
+ lb_port_payload)
345
+ except (exceptions.CommandError, grpc.FutureTimeoutError,
346
+ grpc.RpcError):
314
347
  if serve_utils.is_consolidation_mode(pool):
315
348
  with ux_utils.print_exception_no_traceback():
316
349
  raise RuntimeError(
@@ -344,8 +377,6 @@ def up(
344
377
  'Failed to spin up the service. Please '
345
378
  'check the logs above for more details.') from None
346
379
  else:
347
- lb_port = serve_utils.load_service_initialization_result(
348
- lb_port_payload)
349
380
  if not serve_utils.is_consolidation_mode(pool) and not pool:
350
381
  socket_endpoint = backend_utils.get_endpoints(
351
382
  controller_handle.cluster_name,
@@ -461,6 +492,7 @@ def update(
461
492
  f'use {ux_utils.BOLD}sky serve up{ux_utils.RESET_BOLD}',
462
493
  )
463
494
 
495
+ assert isinstance(handle, backends.CloudVmRayResourceHandle)
464
496
  backend = backend_utils.get_backend_from_handle(handle)
465
497
  assert isinstance(backend, backends.CloudVmRayBackend)
466
498
 
@@ -503,29 +535,39 @@ def update(
503
535
  controller_utils.maybe_translate_local_file_mounts_and_sync_up(
504
536
  task, task_type='serve')
505
537
 
506
- code = serve_utils.ServeCodeGen.add_version(service_name)
507
- returncode, version_string_payload, stderr = backend.run_on_head(
508
- handle,
509
- code,
510
- require_outputs=True,
511
- stream_logs=False,
512
- separate_stderr=True)
513
- try:
514
- subprocess_utils.handle_returncode(returncode,
515
- code,
516
- 'Failed to add version',
517
- stderr,
518
- stream_logs=True)
519
- except exceptions.CommandError as e:
520
- raise RuntimeError(e.error_msg) from e
538
+ use_legacy = not handle.is_grpc_enabled_with_flag
521
539
 
522
- version_string = serve_utils.load_version_string(version_string_payload)
523
- try:
524
- current_version = int(version_string)
525
- except ValueError as e:
526
- with ux_utils.print_exception_no_traceback():
527
- raise ValueError(f'Failed to parse version: {version_string}; '
528
- f'Returncode: {returncode}') from e
540
+ if handle.is_grpc_enabled_with_flag:
541
+ try:
542
+ current_version = serve_rpc_utils.RpcRunner.add_version(
543
+ handle, service_name)
544
+ except exceptions.SkyletMethodNotImplementedError:
545
+ use_legacy = True
546
+
547
+ if use_legacy:
548
+ code = serve_utils.ServeCodeGen.add_version(service_name)
549
+ returncode, version_string_payload, stderr = backend.run_on_head(
550
+ handle,
551
+ code,
552
+ require_outputs=True,
553
+ stream_logs=False,
554
+ separate_stderr=True)
555
+ try:
556
+ subprocess_utils.handle_returncode(returncode,
557
+ code,
558
+ 'Failed to add version',
559
+ stderr,
560
+ stream_logs=True)
561
+ except exceptions.CommandError as e:
562
+ raise RuntimeError(e.error_msg) from e
563
+
564
+ version_string = serve_utils.load_version_string(version_string_payload)
565
+ try:
566
+ current_version = int(version_string)
567
+ except ValueError as e:
568
+ with ux_utils.print_exception_no_traceback():
569
+ raise ValueError(f'Failed to parse version: {version_string}; '
570
+ f'Returncode: {returncode}') from e
529
571
 
530
572
  with tempfile.NamedTemporaryFile(
531
573
  prefix=f'{service_name}-v{current_version}',
@@ -540,23 +582,33 @@ def update(
540
582
  {remote_task_yaml_path: service_file.name},
541
583
  storage_mounts=None)
542
584
 
543
- code = serve_utils.ServeCodeGen.update_service(service_name,
544
- current_version,
545
- mode=mode.value,
546
- pool=pool)
547
- returncode, _, stderr = backend.run_on_head(handle,
548
- code,
549
- require_outputs=True,
550
- stream_logs=False,
551
- separate_stderr=True)
552
- try:
553
- subprocess_utils.handle_returncode(returncode,
554
- code,
555
- f'Failed to update {noun}s',
556
- stderr,
557
- stream_logs=True)
558
- except exceptions.CommandError as e:
559
- raise RuntimeError(e.error_msg) from e
585
+ use_legacy = not handle.is_grpc_enabled_with_flag
586
+
587
+ if handle.is_grpc_enabled_with_flag:
588
+ try:
589
+ serve_rpc_utils.RpcRunner.update_service(
590
+ handle, service_name, current_version, mode, pool)
591
+ except exceptions.SkyletMethodNotImplementedError:
592
+ use_legacy = True
593
+
594
+ if use_legacy:
595
+ code = serve_utils.ServeCodeGen.update_service(service_name,
596
+ current_version,
597
+ mode=mode.value,
598
+ pool=pool)
599
+ returncode, _, stderr = backend.run_on_head(handle,
600
+ code,
601
+ require_outputs=True,
602
+ stream_logs=False,
603
+ separate_stderr=True)
604
+ try:
605
+ subprocess_utils.handle_returncode(returncode,
606
+ code,
607
+ f'Failed to update {noun}s',
608
+ stderr,
609
+ stream_logs=True)
610
+ except exceptions.CommandError as e:
611
+ raise RuntimeError(e.error_msg) from e
560
612
 
561
613
  cmd = 'sky jobs pool status' if pool else 'sky serve status'
562
614
  logger.info(
@@ -619,29 +671,44 @@ def down(
619
671
  raise ValueError(f'Can only specify one of {noun}_names or all. '
620
672
  f'Provided {argument_str!r}.')
621
673
 
622
- backend = backend_utils.get_backend_from_handle(handle)
623
- assert isinstance(backend, backends.CloudVmRayBackend)
624
674
  service_names = None if all else service_names
625
- code = serve_utils.ServeCodeGen.terminate_services(service_names, purge,
626
- pool)
627
675
 
628
676
  try:
629
- returncode, stdout, _ = backend.run_on_head(handle,
630
- code,
631
- require_outputs=True,
632
- stream_logs=False)
677
+ assert isinstance(handle, backends.CloudVmRayResourceHandle)
678
+ use_legacy = not handle.is_grpc_enabled_with_flag
679
+
680
+ if handle.is_grpc_enabled_with_flag:
681
+ try:
682
+ stdout = serve_rpc_utils.RpcRunner.terminate_services(
683
+ handle, service_names, purge, pool)
684
+ except exceptions.SkyletMethodNotImplementedError:
685
+ use_legacy = True
686
+
687
+ if use_legacy:
688
+ backend = backend_utils.get_backend_from_handle(handle)
689
+ assert isinstance(backend, backends.CloudVmRayBackend)
690
+ code = serve_utils.ServeCodeGen.terminate_services(
691
+ service_names, purge, pool)
692
+
693
+ returncode, stdout, _ = backend.run_on_head(handle,
694
+ code,
695
+ require_outputs=True,
696
+ stream_logs=False)
697
+
698
+ subprocess_utils.handle_returncode(returncode, code,
699
+ f'Failed to terminate {noun}',
700
+ stdout)
633
701
  except exceptions.FetchClusterInfoError as e:
634
702
  raise RuntimeError(
635
703
  'Failed to fetch controller IP. Please refresh controller status '
636
- f'by `sky status -r {controller_type.value.cluster_name}` '
637
- 'and try again.') from e
638
-
639
- try:
640
- subprocess_utils.handle_returncode(returncode, code,
641
- f'Failed to terminate {noun}',
642
- stdout)
704
+ f'by `sky status -r {controller_type.value.cluster_name}` and try '
705
+ 'again.') from e
643
706
  except exceptions.CommandError as e:
644
707
  raise RuntimeError(e.error_msg) from e
708
+ except grpc.RpcError as e:
709
+ raise RuntimeError(f'{e.details()} ({e.code()})') from e
710
+ except grpc.FutureTimeoutError as e:
711
+ raise RuntimeError('gRPC timed out') from e
645
712
 
646
713
  logger.info(stdout)
647
714
 
@@ -669,27 +736,40 @@ def status(
669
736
  stopped_message=controller_type.value.default_hint_if_non_existent.
670
737
  replace('service', noun))
671
738
 
672
- backend = backend_utils.get_backend_from_handle(handle)
673
- assert isinstance(backend, backends.CloudVmRayBackend)
739
+ assert isinstance(handle, backends.CloudVmRayResourceHandle)
740
+ use_legacy = not handle.is_grpc_enabled_with_flag
674
741
 
675
- code = serve_utils.ServeCodeGen.get_service_status(service_names, pool=pool)
676
- returncode, serve_status_payload, stderr = backend.run_on_head(
677
- handle,
678
- code,
679
- require_outputs=True,
680
- stream_logs=False,
681
- separate_stderr=True)
742
+ if handle.is_grpc_enabled_with_flag:
743
+ try:
744
+ service_records = serve_rpc_utils.RpcRunner.get_service_status(
745
+ handle, service_names, pool)
746
+ except exceptions.SkyletMethodNotImplementedError:
747
+ use_legacy = True
748
+
749
+ if use_legacy:
750
+ backend = backend_utils.get_backend_from_handle(handle)
751
+ assert isinstance(backend, backends.CloudVmRayBackend)
752
+
753
+ code = serve_utils.ServeCodeGen.get_service_status(service_names,
754
+ pool=pool)
755
+ returncode, serve_status_payload, stderr = backend.run_on_head(
756
+ handle,
757
+ code,
758
+ require_outputs=True,
759
+ stream_logs=False,
760
+ separate_stderr=True)
682
761
 
683
- try:
684
- subprocess_utils.handle_returncode(returncode,
685
- code,
686
- f'Failed to fetch {noun}s',
687
- stderr,
688
- stream_logs=True)
689
- except exceptions.CommandError as e:
690
- raise RuntimeError(e.error_msg) from e
762
+ try:
763
+ subprocess_utils.handle_returncode(returncode,
764
+ code,
765
+ f'Failed to fetch {noun}s',
766
+ stderr,
767
+ stream_logs=True)
768
+ except exceptions.CommandError as e:
769
+ raise RuntimeError(e.error_msg) from e
770
+
771
+ service_records = serve_utils.load_service_status(serve_status_payload)
691
772
 
692
- service_records = serve_utils.load_service_status(serve_status_payload)
693
773
  # Get the endpoint for each service
694
774
  for service_record in service_records:
695
775
  service_record['endpoint'] = None
@@ -792,25 +872,37 @@ def _get_all_replica_targets(
792
872
  handle: backends.CloudVmRayResourceHandle,
793
873
  pool: bool) -> Set[serve_utils.ServiceComponentTarget]:
794
874
  """Helper function to get targets for all live replicas."""
795
- code = serve_utils.ServeCodeGen.get_service_status([service_name],
796
- pool=pool)
797
- returncode, serve_status_payload, stderr = backend.run_on_head(
798
- handle,
799
- code,
800
- require_outputs=True,
801
- stream_logs=False,
802
- separate_stderr=True)
875
+ assert isinstance(handle, backends.CloudVmRayResourceHandle)
876
+ use_legacy = not handle.is_grpc_enabled_with_flag
803
877
 
804
- try:
805
- subprocess_utils.handle_returncode(returncode,
806
- code,
807
- 'Failed to fetch services',
808
- stderr,
809
- stream_logs=True)
810
- except exceptions.CommandError as e:
811
- raise RuntimeError(e.error_msg) from e
878
+ if handle.is_grpc_enabled_with_flag:
879
+ try:
880
+ service_records = serve_rpc_utils.RpcRunner.get_service_status(
881
+ handle, [service_name], pool)
882
+ except exceptions.SkyletMethodNotImplementedError:
883
+ use_legacy = True
884
+
885
+ if use_legacy:
886
+ code = serve_utils.ServeCodeGen.get_service_status([service_name],
887
+ pool=pool)
888
+ returncode, serve_status_payload, stderr = backend.run_on_head(
889
+ handle,
890
+ code,
891
+ require_outputs=True,
892
+ stream_logs=False,
893
+ separate_stderr=True)
894
+
895
+ try:
896
+ subprocess_utils.handle_returncode(returncode,
897
+ code,
898
+ 'Failed to fetch services',
899
+ stderr,
900
+ stream_logs=True)
901
+ except exceptions.CommandError as e:
902
+ raise RuntimeError(e.error_msg) from e
903
+
904
+ service_records = serve_utils.load_service_status(serve_status_payload)
812
905
 
813
- service_records = serve_utils.load_service_status(serve_status_payload)
814
906
  if not service_records:
815
907
  raise ValueError(f'Service {service_name!r} not found.')
816
908
  assert len(service_records) == 1
sky/server/common.py CHANGED
@@ -515,6 +515,19 @@ def get_request_id(response: 'requests.Response') -> RequestId[T]:
515
515
  return RequestId[T](request_id)
516
516
 
517
517
 
518
+ def get_stream_request_id(
519
+ response: 'requests.Response') -> Optional[RequestId[T]]:
520
+ """This is same as the above function, but just for `sdk.stream_and_get.
521
+ We do this because `/api/stream` may choose the latest request id, and
522
+ we need to keep track of that information. Request id in this case can
523
+ be None."""
524
+ handle_request_error(response)
525
+ request_id = response.headers.get(server_constants.STREAM_REQUEST_HEADER)
526
+ if request_id is not None:
527
+ return RequestId[T](request_id)
528
+ return None
529
+
530
+
518
531
  def _start_api_server(deploy: bool = False,
519
532
  host: str = '127.0.0.1',
520
533
  foreground: bool = False,
sky/server/constants.py CHANGED
@@ -61,3 +61,6 @@ DASHBOARD_DIR = os.path.join(os.path.dirname(__file__), '..', 'dashboard',
61
61
 
62
62
  # The interval (seconds) for the event to be restarted in the background.
63
63
  DAEMON_RESTART_INTERVAL_SECONDS = 20
64
+
65
+ # Cookie header for stream request id.
66
+ STREAM_REQUEST_HEADER = 'X-SkyPilot-Stream-Request-ID'
@@ -282,8 +282,8 @@ def _get_queue(schedule_type: api_requests.ScheduleType) -> RequestQueue:
282
282
 
283
283
  @contextlib.contextmanager
284
284
  def override_request_env_and_config(
285
- request_body: payloads.RequestBody,
286
- request_id: str) -> Generator[None, None, None]:
285
+ request_body: payloads.RequestBody, request_id: str,
286
+ request_name: str) -> Generator[None, None, None]:
287
287
  """Override the environment and SkyPilot config for a request."""
288
288
  original_env = os.environ.copy()
289
289
  try:
@@ -319,9 +319,22 @@ def override_request_env_and_config(
319
319
  with skypilot_config.override_skypilot_config(
320
320
  request_body.override_skypilot_config,
321
321
  request_body.override_skypilot_config_path):
322
- # Rejecting requests to workspaces that the user does not have
323
- # permission to access.
324
- workspaces_core.reject_request_for_unauthorized_workspace(user)
322
+ # Skip permission check for sky.workspaces.get request
323
+ # as it is used to determine which workspaces the user
324
+ # has access to.
325
+ if request_name != 'sky.workspaces.get':
326
+ try:
327
+ # Reject requests that the user does not have permission
328
+ # to access.
329
+ workspaces_core.reject_request_for_unauthorized_workspace(
330
+ user)
331
+ except exceptions.PermissionDeniedError as e:
332
+ logger.debug(
333
+ f'{request_id} permission denied to workspace: '
334
+ f'{skypilot_config.get_active_workspace()}: {e}')
335
+ raise e
336
+ logger.debug(
337
+ f'{request_id} permission granted to {request_name} request')
325
338
  yield
326
339
  finally:
327
340
  # We need to call the save_timeline() since atexit will not be
@@ -402,7 +415,8 @@ def _request_execution_wrapper(request_id: str,
402
415
  # captured in the log file.
403
416
  try:
404
417
  with sky_logging.add_debug_log_handler(request_id), \
405
- override_request_env_and_config(request_body, request_id), \
418
+ override_request_env_and_config(
419
+ request_body, request_id, request_name), \
406
420
  tempstore.tempdir():
407
421
  if sky_logging.logging_enabled(logger, sky_logging.DEBUG):
408
422
  config = skypilot_config.to_dict()
@@ -451,6 +465,9 @@ def _request_execution_wrapper(request_id: str,
451
465
  # Capture the peak RSS before GC.
452
466
  peak_rss = max(proc.memory_info().rss,
453
467
  metrics_lib.peak_rss_bytes)
468
+ # Clear request level cache to release all memory used by
469
+ # the request.
470
+ annotations.clear_request_level_cache()
454
471
  with metrics_lib.time_it(name='release_memory',
455
472
  group='internal'):
456
473
  common_utils.release_memory()
sky/server/server.py CHANGED
@@ -1571,6 +1571,15 @@ async def stream(
1571
1571
  detail=f'Log path {log_path!r} does not exist')
1572
1572
 
1573
1573
  log_path_to_stream = resolved_log_path
1574
+
1575
+ headers = {
1576
+ 'Cache-Control': 'no-cache, no-transform',
1577
+ 'X-Accel-Buffering': 'no',
1578
+ 'Transfer-Encoding': 'chunked'
1579
+ }
1580
+ if request_id is not None:
1581
+ headers[server_constants.STREAM_REQUEST_HEADER] = request_id
1582
+
1574
1583
  return fastapi.responses.StreamingResponse(
1575
1584
  content=stream_utils.log_streamer(request_id,
1576
1585
  log_path_to_stream,
@@ -1578,11 +1587,7 @@ async def stream(
1578
1587
  tail=tail,
1579
1588
  follow=follow),
1580
1589
  media_type='text/plain',
1581
- headers={
1582
- 'Cache-Control': 'no-cache, no-transform',
1583
- 'X-Accel-Buffering': 'no',
1584
- 'Transfer-Encoding': 'chunked'
1585
- },
1590
+ headers=headers,
1586
1591
  )
1587
1592
 
1588
1593
 
@@ -189,6 +189,7 @@ extras_require: Dict[str, List[str]] = {
189
189
  'fluidstack': [], # No dependencies needed for fluidstack
190
190
  'cudo': ['cudo-compute>=0.1.10'],
191
191
  'paperspace': [], # No dependencies needed for paperspace
192
+ 'primeintellect': [], # No dependencies needed for primeintellect
192
193
  'do': ['pydo>=0.3.0', 'azure-core>=1.24.0', 'azure-common'],
193
194
  'vast': ['vastai-sdk>=0.1.12'],
194
195
  'vsphere': [
sky/skylet/constants.py CHANGED
@@ -62,7 +62,8 @@ SKY_UV_INSTALL_CMD = (f'{SKY_UV_CMD} -V >/dev/null 2>&1 || '
62
62
  'curl -LsSf https://astral.sh/uv/install.sh '
63
63
  f'| UV_INSTALL_DIR={SKY_UV_INSTALL_DIR} sh')
64
64
  SKY_UV_PIP_CMD: str = (f'VIRTUAL_ENV={SKY_REMOTE_PYTHON_ENV} {SKY_UV_CMD} pip')
65
- SKY_UV_RUN_CMD: str = (f'VIRTUAL_ENV={SKY_REMOTE_PYTHON_ENV} {SKY_UV_CMD} run')
65
+ SKY_UV_RUN_CMD: str = (
66
+ f'VIRTUAL_ENV={SKY_REMOTE_PYTHON_ENV} {SKY_UV_CMD} run --active')
66
67
  # Deleting the SKY_REMOTE_PYTHON_ENV_NAME from the PATH and unsetting relevant
67
68
  # VIRTUAL_ENV envvars to deactivate the environment. `deactivate` command does
68
69
  # not work when conda is used.
@@ -153,7 +154,7 @@ CONDA_INSTALLATION_COMMANDS = (
153
154
  # because for some images, conda is already installed, but not initialized.
154
155
  # In this case, we need to initialize conda and set auto_activate_base to
155
156
  # true.
156
- '{ bash Miniconda3-Linux.sh -b; '
157
+ '{ bash Miniconda3-Linux.sh -b || true; '
157
158
  'eval "$(~/miniconda3/bin/conda shell.bash hook)" && conda init && '
158
159
  # Caller should replace {conda_auto_activate} with either true or false.
159
160
  'conda config --set auto_activate_base {conda_auto_activate} && '
@@ -456,7 +457,8 @@ CATALOG_SCHEMA_VERSION = 'v8'
456
457
  CATALOG_DIR = '~/.sky/catalogs'
457
458
  ALL_CLOUDS = ('aws', 'azure', 'gcp', 'ibm', 'lambda', 'scp', 'oci',
458
459
  'kubernetes', 'runpod', 'vast', 'vsphere', 'cudo', 'fluidstack',
459
- 'paperspace', 'do', 'nebius', 'ssh', 'hyperbolic', 'seeweb')
460
+ 'paperspace', 'primeintellect', 'do', 'nebius', 'ssh',
461
+ 'hyperbolic', 'seeweb')
460
462
  # END constants used for service catalog.
461
463
 
462
464
  # The user ID of the SkyPilot system.