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
@@ -0,0 +1,398 @@
1
+ """Prime Intellect library wrapper for SkyPilot."""
2
+
3
+ import json
4
+ import os
5
+ import shlex
6
+ import time
7
+ from typing import Any, Dict, List, Optional, Tuple, Union
8
+ import uuid
9
+
10
+ import requests
11
+
12
+ from sky.catalog import common as catalog_common
13
+ from sky.utils import common_utils
14
+
15
+ _df = None
16
+ _lookup_dict = None
17
+
18
+ # Base URL for Prime Intellect API (used as default if not configured).
19
+ DEFAULT_BASE_URL = 'https://api.primeintellect.ai'
20
+ CREDENTIALS_PATH = '~/.prime/config.json'
21
+ INITIAL_BACKOFF_SECONDS = 10
22
+ MAX_BACKOFF_FACTOR = 10
23
+ MAX_ATTEMPTS = 6
24
+
25
+
26
+ class PrimeintellectAPIError(Exception):
27
+ """Base exception for Prime Intellect API errors."""
28
+
29
+ def __init__(self,
30
+ message: str,
31
+ status_code: Optional[int] = None,
32
+ response_data: Optional[Dict[str, Any]] = None):
33
+ super().__init__(message)
34
+ self.status_code = status_code
35
+ self.response_data = response_data
36
+
37
+
38
+ class PrimeintellectResourcesUnavailableError(PrimeintellectAPIError):
39
+ """Exception for when resources are unavailable on Prime Intellect."""
40
+ pass
41
+
42
+
43
+ def _parse_api_error(response: Any) -> Tuple[str, bool]:
44
+ """Parse API error response to extract meaningful error messages.
45
+
46
+ Returns:
47
+ Tuple[str, bool]:
48
+ - str: A human-readable error message parsed from the API response.
49
+ - bool: True if the error indicates resource unavailability (e.g.,
50
+ capacity issues or quota/limit exceeded), otherwise False.
51
+ """
52
+ try:
53
+ if hasattr(response, 'json'):
54
+ error_data = response.json()
55
+ else:
56
+ error_data = response
57
+
58
+ if isinstance(error_data, dict):
59
+ # Try to extract error message from common error response fields
60
+ error_message = error_data.get('message', '')
61
+ if not error_message:
62
+ error_message = error_data.get('error', '')
63
+ if not error_message:
64
+ error_message = error_data.get('detail', '')
65
+
66
+ # Check if it's a resource unavailability error
67
+ if any(keyword in error_message.lower() for keyword in [
68
+ 'no capacity', 'capacity', 'unavailable', 'out of stock',
69
+ 'insufficient', 'not available', 'quota exceeded',
70
+ 'limit exceeded'
71
+ ]):
72
+ return error_message, True
73
+
74
+ return error_message, False
75
+
76
+ return str(error_data), False
77
+ except Exception: # pylint: disable=broad-except
78
+ return f'HTTP {response.status_code} {response.reason}', False
79
+
80
+
81
+ def _try_request_with_backoff(
82
+ method: str,
83
+ url: str,
84
+ headers: Dict[str, str],
85
+ data: Optional[Union[str, Dict[str, Any]]] = None) -> Dict[str, Any]:
86
+ backoff = common_utils.Backoff(initial_backoff=INITIAL_BACKOFF_SECONDS,
87
+ max_backoff_factor=MAX_BACKOFF_FACTOR)
88
+ for i in range(MAX_ATTEMPTS):
89
+ timeout = 30
90
+ if method == 'get':
91
+ response = requests.get(url,
92
+ headers=headers,
93
+ params=data,
94
+ timeout=timeout)
95
+ elif method == 'post':
96
+ response = requests.post(url,
97
+ headers=headers,
98
+ json=data,
99
+ timeout=timeout)
100
+ elif method == 'put':
101
+ response = requests.put(url,
102
+ headers=headers,
103
+ json=data,
104
+ timeout=timeout)
105
+ elif method == 'patch':
106
+ response = requests.patch(url,
107
+ headers=headers,
108
+ json=data,
109
+ timeout=timeout)
110
+ elif method == 'delete':
111
+ response = requests.delete(url, headers=headers, timeout=timeout)
112
+ else:
113
+ raise ValueError(f'Unsupported requests method: {method}')
114
+ # If rate limited, wait and try again
115
+ if response.status_code == 429 and i != MAX_ATTEMPTS - 1:
116
+ time.sleep(backoff.current_backoff())
117
+ continue
118
+ if response.ok:
119
+ return response.json()
120
+ else:
121
+ # Parse the error response for meaningful messages
122
+ err, is_resource_unavailable = _parse_api_error(response)
123
+
124
+ # Create a more informative error message
125
+ if not err:
126
+ err = (f'API request failed: {method} {url}: '
127
+ f'{response.status_code} {response.reason}')
128
+ else:
129
+ err = f'API request failed: {err}'
130
+
131
+ # Raise appropriate exception based on error type
132
+ if is_resource_unavailable:
133
+ raise PrimeintellectResourcesUnavailableError(
134
+ err,
135
+ status_code=response.status_code,
136
+ response_data=response.json()
137
+ if hasattr(response, 'json') else None)
138
+ else:
139
+ raise PrimeintellectAPIError(
140
+ err,
141
+ status_code=response.status_code,
142
+ response_data=response.json()
143
+ if hasattr(response, 'json') else None)
144
+ return {}
145
+
146
+
147
+ def get_upstream_cloud_id(instance_type: str) -> Optional[str]:
148
+ global _df, _lookup_dict
149
+ if _df is None:
150
+ _df = catalog_common.read_catalog('primeintellect/vms.csv')
151
+ _lookup_dict = (
152
+ _df.set_index('InstanceType')['UpstreamCloudId'].to_dict())
153
+ return _lookup_dict.get(instance_type)
154
+
155
+
156
+ class PrimeIntellectAPIClient:
157
+ """Client for interacting with Prime Intellect API."""
158
+
159
+ def __init__(self) -> None:
160
+ self.credentials = os.path.expanduser(CREDENTIALS_PATH)
161
+ assert os.path.exists(self.credentials), 'Credentials not found'
162
+ with open(self.credentials, 'r', encoding='utf-8') as f:
163
+ self._credentials = json.load(f)
164
+ self.api_key = self._credentials.get('api_key')
165
+ self.team_id = self._credentials.get('team_id')
166
+ self.base_url = self._credentials.get('base_url', DEFAULT_BASE_URL)
167
+ self.headers = {
168
+ 'Authorization': f'Bearer {self.api_key}',
169
+ 'Content-Type': 'application/json'
170
+ }
171
+
172
+ def list_instances(self, **search_kwargs) -> List[Dict[str, Any]]:
173
+ response = _try_request_with_backoff('get',
174
+ f'{self.base_url}/api/v1/pods',
175
+ headers=self.headers,
176
+ data=search_kwargs)
177
+ return response['data']
178
+
179
+ def get_instance_details(self, instance_id: str) -> Dict[str, Any]:
180
+ return _try_request_with_backoff(
181
+ 'get',
182
+ f'{self.base_url}/api/v1/pods/{instance_id}',
183
+ headers=self.headers)
184
+
185
+ def launch(self,
186
+ name: str,
187
+ instance_type: str,
188
+ region: str,
189
+ availability_zone: str,
190
+ disk_size: int,
191
+ vcpus: int = 0,
192
+ memory: int = 0) -> Dict[str, Any]:
193
+ """Create a pod/instance via Prime Intellect API.
194
+
195
+ Args:
196
+ name: User-visible name of the pod.
197
+ instance_type: A catalog instance type string. The expected format
198
+ is:
199
+ "<provider>__<accelerator>__<vcpus>__<memory>[_SPOT]".
200
+
201
+ - <provider>: Upstream provider tag (e.g., "primecompute").
202
+ - <accelerator>:
203
+ * GPU nodes: "<N>x<GPU_MODEL>", e.g., "8xH100_80GB".
204
+ * CPU-only nodes: the literal "CPU_NODE".
205
+ - <vcpus>: Integer string for vCPU count (e.g., "104").
206
+ - <memory>: Integer string for memory in GB (e.g., "752").
207
+ - Optional suffix "_SPOT" may be present in the full string
208
+ (ignored here; pricing/spot behavior is not controlled by
209
+ this method).
210
+
211
+ Notes:
212
+ - Parsing: only the first two components (provider,
213
+ accelerator) are needed to build the payload. The vCPU
214
+ and memory values are provided via the ``vcpus`` and
215
+ ``memory`` arguments.
216
+ - Catalog lookup: the full instance_type string is used to
217
+ map to the catalog's UpstreamCloudId.
218
+ - CPU-only: accelerator "CPU_NODE" is a sentinel for
219
+ "no GPU". We set gpuType='CPU_NODE' and gpuCount=1 to
220
+ represent CPU-only pods.
221
+ - Spot: the optional "__SPOT" suffix (if present) is ignored
222
+ here; pricing/spot behavior is handled elsewhere.
223
+
224
+ region: Country/region code used by Prime Intellect.
225
+ availability_zone: Data center ID (zone) within the region.
226
+ disk_size: Boot disk size in GB.
227
+ vcpus: Optional explicit vCPU override; if >0 it will be sent.
228
+ memory: Optional explicit memory override in GB; if >0 it will be
229
+ sent.
230
+
231
+ Returns:
232
+ The API response JSON as a dict.
233
+ """
234
+ cloud_id = get_upstream_cloud_id(instance_type)
235
+ assert cloud_id, 'cloudId cannot be None'
236
+ assert availability_zone, 'availability_zone cannot be None'
237
+
238
+ # Parse the instance_type. We only need the first two components:
239
+ # provider and accelerator info (see docstring above).
240
+ provider, gpu_parts, _, _ = instance_type.split('__', 3)
241
+ if 'CPU_NODE' in gpu_parts:
242
+ # Prime Intellect API uses the same schema for CPU-only and GPU
243
+ # pods. For CPU-only instances, we set gpuType='CPU_NODE' and
244
+ # gpuCount=1 as a sentinel to indicate "no GPU". This is how CPU
245
+ # instances are represented internally on our platform; the
246
+ # backend does not interpret this as having a physical GPU.
247
+ gpu_type = 'CPU_NODE'
248
+ gpu_count = 1
249
+ else:
250
+ parts = gpu_parts.split('x', 1)
251
+ gpu_count = int(parts[0])
252
+ gpu_type = parts[1]
253
+
254
+ payload: Dict[str, Any] = {
255
+ 'pod': {
256
+ 'name': name,
257
+ 'cloudId': cloud_id,
258
+ 'socket': 'PCIe',
259
+ 'gpuType': gpu_type,
260
+ 'gpuCount': int(gpu_count),
261
+ 'diskSize': disk_size,
262
+ # Prime Intellect API historically required maxPrice.
263
+ # Set to 0 to indicate on-demand/non-spot pricing.
264
+ 'maxPrice': 0,
265
+ },
266
+ 'provider': {
267
+ 'type': provider,
268
+ }
269
+ }
270
+
271
+ if vcpus > 0:
272
+ payload['pod']['vcpus'] = vcpus
273
+ if memory > 0:
274
+ payload['pod']['memory'] = memory
275
+
276
+ if region != 'UNSPECIFIED':
277
+ payload['pod']['country'] = region
278
+ if availability_zone != 'UNSPECIFIED':
279
+ payload['pod']['dataCenterId'] = availability_zone
280
+
281
+ if self.team_id is not None and self.team_id != '':
282
+ payload['team'] = {'teamId': self.team_id}
283
+
284
+ response = _try_request_with_backoff(
285
+ 'post',
286
+ f'{self.base_url}/api/v1/pods',
287
+ headers=self.headers,
288
+ data=payload,
289
+ )
290
+ return response
291
+
292
+ def remove(self, instance_id: str) -> Dict[str, Any]:
293
+ return _try_request_with_backoff(
294
+ 'delete',
295
+ f'{self.base_url}/api/v1/pods/{instance_id}',
296
+ headers=self.headers,
297
+ )
298
+
299
+ def list_ssh_keys(self) -> List[Dict[str, Any]]:
300
+ response = _try_request_with_backoff('get',
301
+ f'{self.base_url}/api/v1/ssh_keys',
302
+ headers=self.headers)
303
+ return response['data']
304
+
305
+ def get_or_add_ssh_key(self, ssh_pub_key: str = '') -> Dict[str, str]:
306
+ """Add ssh key if not already added."""
307
+ # Check if the public key is already added
308
+ ssh_keys = self.list_ssh_keys()
309
+ for key in ssh_keys:
310
+ if key['publicKey'].strip().split()[:2] == ssh_pub_key.strip(
311
+ ).split()[:2]:
312
+ return {'name': key['name'], 'ssh_key': ssh_pub_key}
313
+
314
+ # Add the public key to Prime Intellect account if not already added
315
+ ssh_key_name = 'skypilot-' + str(uuid.uuid4()).replace('-', '')[:8]
316
+ _try_request_with_backoff(
317
+ 'post',
318
+ f'{self.base_url}/api/v1/ssh_keys',
319
+ headers=self.headers,
320
+ data={
321
+ 'name': ssh_key_name,
322
+ 'publicKey': ssh_pub_key
323
+ },
324
+ )
325
+ return {'name': ssh_key_name, 'ssh_key': ssh_pub_key}
326
+
327
+
328
+ def parse_ssh_connection(ssh_connection: Any) -> Tuple[Optional[str], int]:
329
+ """Parse and extract SSH username and port from a connection field.
330
+
331
+ The provider may return the SSH connection in multiple shapes. This helper
332
+ robustly extracts the SSH username and port while tolerating extra flags or
333
+ various tokenizations.
334
+
335
+ Accepted formats (examples):
336
+ - String with port flag:
337
+ "ubuntu@1.2.3.4 -p 2222 [-o <flag> ...]"
338
+ - String without explicit port (defaults to 22):
339
+ "ubuntu@1.2.3.4"
340
+ - String with host:port:
341
+ "ubuntu@1.2.3.4:2222"
342
+ - List with a single target:
343
+ ["ubuntu@1.2.3.4"]
344
+ - List of tokens (e.g., split form):
345
+ ["ubuntu@1.2.3.4", "-p", "2222"]
346
+
347
+ Args:
348
+ ssh_connection: The raw field from the API; can be a string or a list
349
+ of strings.
350
+
351
+ Returns:
352
+ (ssh_user, ssh_port): username if found, else None; port if found,
353
+ else 22.
354
+ """
355
+ ssh_user: Optional[str] = None
356
+ ssh_port: int = 22
357
+
358
+ # Normalize into a list of tokens for easier processing.
359
+ tokens: List[str] = []
360
+ if isinstance(ssh_connection, str):
361
+ try:
362
+ tokens = shlex.split(ssh_connection)
363
+ except Exception: # pylint: disable=broad-except
364
+ tokens = [ssh_connection]
365
+ elif isinstance(ssh_connection, list):
366
+ for elem in ssh_connection:
367
+ if isinstance(elem, str):
368
+ try:
369
+ tokens.extend(shlex.split(elem))
370
+ except Exception: # pylint: disable=broad-except
371
+ tokens.append(elem)
372
+ else:
373
+ # Unknown type; return defaults.
374
+ return ssh_user, ssh_port
375
+
376
+ # Find the first token containing '@' as the user@host candidate.
377
+ user_host: Optional[str] = next((t for t in tokens if '@' in t), None)
378
+ if user_host:
379
+ ssh_user = user_host.split('@', 1)[0].strip()
380
+ # Try host:port format (after '@').
381
+ host_part = user_host.split('@', 1)[1]
382
+ if ':' in host_part:
383
+ _, maybe_port = host_part.rsplit(':', 1)
384
+ try:
385
+ ssh_port = int(maybe_port)
386
+ except ValueError:
387
+ pass
388
+
389
+ # Check for '-p <port>' pair anywhere in the tokens. This takes priority.
390
+ if '-p' in tokens:
391
+ idx = tokens.index('-p')
392
+ if idx + 1 < len(tokens):
393
+ try:
394
+ ssh_port = int(tokens[idx + 1])
395
+ except ValueError:
396
+ pass
397
+
398
+ return ssh_user, ssh_port
sky/resources.py CHANGED
@@ -1331,10 +1331,18 @@ class Resources:
1331
1331
  clouds.CloudImplementationFeatures.IMAGE_ID
1332
1332
  })
1333
1333
  except exceptions.NotSupportedError as e:
1334
+ # Provide a more helpful error message for Lambda cloud
1335
+ if self.cloud.is_same_cloud(clouds.Lambda()):
1336
+ with ux_utils.print_exception_no_traceback():
1337
+ raise ValueError(
1338
+ 'Lambda cloud only supports Docker images. '
1339
+ 'Please prefix your image with "docker:" '
1340
+ '(e.g., image_id: docker:your-image-name).') from e
1334
1341
  with ux_utils.print_exception_no_traceback():
1335
1342
  raise ValueError(
1336
1343
  'image_id is only supported for AWS/GCP/Azure/IBM/OCI/'
1337
- 'Kubernetes, please explicitly specify the cloud.') from e
1344
+ 'Kubernetes. For Lambda cloud, use "docker:" prefix for '
1345
+ 'Docker images.') from e
1338
1346
 
1339
1347
  if self._region is not None:
1340
1348
  # If the image_id has None as key (region-agnostic),
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: sky/schemas/generated/servev1.proto
4
+ # Protobuf Python Version: 5.26.1
5
+ """Generated protocol buffer code."""
6
+ from google.protobuf import descriptor as _descriptor
7
+ from google.protobuf import descriptor_pool as _descriptor_pool
8
+ from google.protobuf import symbol_database as _symbol_database
9
+ from google.protobuf.internal import builder as _builder
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#sky/schemas/generated/servev1.proto\x12\x08serve.v1\"\x1d\n\x0cServiceNames\x12\r\n\x05names\x18\x01 \x03(\t\"s\n\rServiceStatus\x12\x33\n\x06status\x18\x01 \x03(\x0b\x32#.serve.v1.ServiceStatus.StatusEntry\x1a-\n\x0bStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"m\n\x17GetServiceStatusRequest\x12\x32\n\rservice_names\x18\x01 \x01(\x0b\x32\x16.serve.v1.ServiceNamesH\x00\x88\x01\x01\x12\x0c\n\x04pool\x18\x02 \x01(\x08\x42\x10\n\x0e_service_names\"E\n\x18GetServiceStatusResponse\x12)\n\x08statuses\x18\x01 \x03(\x0b\x32\x17.serve.v1.ServiceStatus\")\n\x11\x41\x64\x64VersionRequest\x12\x14\n\x0cservice_name\x18\x01 \x01(\t\"%\n\x12\x41\x64\x64VersionResponse\x12\x0f\n\x07version\x18\x01 \x01(\x03\"}\n\x18TerminateServicesRequest\x12\x32\n\rservice_names\x18\x01 \x01(\x0b\x32\x16.serve.v1.ServiceNamesH\x00\x88\x01\x01\x12\r\n\x05purge\x18\x02 \x01(\x08\x12\x0c\n\x04pool\x18\x03 \x01(\x08\x42\x10\n\x0e_service_names\",\n\x19TerminateServicesResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"R\n\x17TerminateReplicaRequest\x12\x14\n\x0cservice_name\x18\x01 \x01(\t\x12\x12\n\nreplica_id\x18\x02 \x01(\x03\x12\r\n\x05purge\x18\x03 \x01(\x08\"+\n\x18TerminateReplicaResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"T\n\x1eWaitServiceRegistrationRequest\x12\x14\n\x0cservice_name\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\x03\x12\x0c\n\x04pool\x18\x03 \x01(\x08\"2\n\x1fWaitServiceRegistrationResponse\x12\x0f\n\x07lb_port\x18\x01 \x01(\x03\"Y\n\x14UpdateServiceRequest\x12\x14\n\x0cservice_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\x03\x12\x0c\n\x04mode\x18\x03 \x01(\t\x12\x0c\n\x04pool\x18\x04 \x01(\x08\"\x17\n\x15UpdateServiceResponse2\xad\x04\n\x0cServeService\x12Y\n\x10GetServiceStatus\x12!.serve.v1.GetServiceStatusRequest\x1a\".serve.v1.GetServiceStatusResponse\x12G\n\nAddVersion\x12\x1b.serve.v1.AddVersionRequest\x1a\x1c.serve.v1.AddVersionResponse\x12\\\n\x11TerminateServices\x12\".serve.v1.TerminateServicesRequest\x1a#.serve.v1.TerminateServicesResponse\x12Y\n\x10TerminateReplica\x12!.serve.v1.TerminateReplicaRequest\x1a\".serve.v1.TerminateReplicaResponse\x12n\n\x17WaitServiceRegistration\x12(.serve.v1.WaitServiceRegistrationRequest\x1a).serve.v1.WaitServiceRegistrationResponse\x12P\n\rUpdateService\x12\x1e.serve.v1.UpdateServiceRequest\x1a\x1f.serve.v1.UpdateServiceResponseb\x06proto3')
18
+
19
+ _globals = globals()
20
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'sky.schemas.generated.servev1_pb2', _globals)
22
+ if not _descriptor._USE_C_DESCRIPTORS:
23
+ DESCRIPTOR._loaded_options = None
24
+ _globals['_SERVICESTATUS_STATUSENTRY']._loaded_options = None
25
+ _globals['_SERVICESTATUS_STATUSENTRY']._serialized_options = b'8\001'
26
+ _globals['_SERVICENAMES']._serialized_start=49
27
+ _globals['_SERVICENAMES']._serialized_end=78
28
+ _globals['_SERVICESTATUS']._serialized_start=80
29
+ _globals['_SERVICESTATUS']._serialized_end=195
30
+ _globals['_SERVICESTATUS_STATUSENTRY']._serialized_start=150
31
+ _globals['_SERVICESTATUS_STATUSENTRY']._serialized_end=195
32
+ _globals['_GETSERVICESTATUSREQUEST']._serialized_start=197
33
+ _globals['_GETSERVICESTATUSREQUEST']._serialized_end=306
34
+ _globals['_GETSERVICESTATUSRESPONSE']._serialized_start=308
35
+ _globals['_GETSERVICESTATUSRESPONSE']._serialized_end=377
36
+ _globals['_ADDVERSIONREQUEST']._serialized_start=379
37
+ _globals['_ADDVERSIONREQUEST']._serialized_end=420
38
+ _globals['_ADDVERSIONRESPONSE']._serialized_start=422
39
+ _globals['_ADDVERSIONRESPONSE']._serialized_end=459
40
+ _globals['_TERMINATESERVICESREQUEST']._serialized_start=461
41
+ _globals['_TERMINATESERVICESREQUEST']._serialized_end=586
42
+ _globals['_TERMINATESERVICESRESPONSE']._serialized_start=588
43
+ _globals['_TERMINATESERVICESRESPONSE']._serialized_end=632
44
+ _globals['_TERMINATEREPLICAREQUEST']._serialized_start=634
45
+ _globals['_TERMINATEREPLICAREQUEST']._serialized_end=716
46
+ _globals['_TERMINATEREPLICARESPONSE']._serialized_start=718
47
+ _globals['_TERMINATEREPLICARESPONSE']._serialized_end=761
48
+ _globals['_WAITSERVICEREGISTRATIONREQUEST']._serialized_start=763
49
+ _globals['_WAITSERVICEREGISTRATIONREQUEST']._serialized_end=847
50
+ _globals['_WAITSERVICEREGISTRATIONRESPONSE']._serialized_start=849
51
+ _globals['_WAITSERVICEREGISTRATIONRESPONSE']._serialized_end=899
52
+ _globals['_UPDATESERVICEREQUEST']._serialized_start=901
53
+ _globals['_UPDATESERVICEREQUEST']._serialized_end=990
54
+ _globals['_UPDATESERVICERESPONSE']._serialized_start=992
55
+ _globals['_UPDATESERVICERESPONSE']._serialized_end=1015
56
+ _globals['_SERVESERVICE']._serialized_start=1018
57
+ _globals['_SERVESERVICE']._serialized_end=1575
58
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,115 @@
1
+ from google.protobuf.internal import containers as _containers
2
+ from google.protobuf import descriptor as _descriptor
3
+ from google.protobuf import message as _message
4
+ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
5
+
6
+ DESCRIPTOR: _descriptor.FileDescriptor
7
+
8
+ class ServiceNames(_message.Message):
9
+ __slots__ = ("names",)
10
+ NAMES_FIELD_NUMBER: _ClassVar[int]
11
+ names: _containers.RepeatedScalarFieldContainer[str]
12
+ def __init__(self, names: _Optional[_Iterable[str]] = ...) -> None: ...
13
+
14
+ class ServiceStatus(_message.Message):
15
+ __slots__ = ("status",)
16
+ class StatusEntry(_message.Message):
17
+ __slots__ = ("key", "value")
18
+ KEY_FIELD_NUMBER: _ClassVar[int]
19
+ VALUE_FIELD_NUMBER: _ClassVar[int]
20
+ key: str
21
+ value: str
22
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
23
+ STATUS_FIELD_NUMBER: _ClassVar[int]
24
+ status: _containers.ScalarMap[str, str]
25
+ def __init__(self, status: _Optional[_Mapping[str, str]] = ...) -> None: ...
26
+
27
+ class GetServiceStatusRequest(_message.Message):
28
+ __slots__ = ("service_names", "pool")
29
+ SERVICE_NAMES_FIELD_NUMBER: _ClassVar[int]
30
+ POOL_FIELD_NUMBER: _ClassVar[int]
31
+ service_names: ServiceNames
32
+ pool: bool
33
+ def __init__(self, service_names: _Optional[_Union[ServiceNames, _Mapping]] = ..., pool: bool = ...) -> None: ...
34
+
35
+ class GetServiceStatusResponse(_message.Message):
36
+ __slots__ = ("statuses",)
37
+ STATUSES_FIELD_NUMBER: _ClassVar[int]
38
+ statuses: _containers.RepeatedCompositeFieldContainer[ServiceStatus]
39
+ def __init__(self, statuses: _Optional[_Iterable[_Union[ServiceStatus, _Mapping]]] = ...) -> None: ...
40
+
41
+ class AddVersionRequest(_message.Message):
42
+ __slots__ = ("service_name",)
43
+ SERVICE_NAME_FIELD_NUMBER: _ClassVar[int]
44
+ service_name: str
45
+ def __init__(self, service_name: _Optional[str] = ...) -> None: ...
46
+
47
+ class AddVersionResponse(_message.Message):
48
+ __slots__ = ("version",)
49
+ VERSION_FIELD_NUMBER: _ClassVar[int]
50
+ version: int
51
+ def __init__(self, version: _Optional[int] = ...) -> None: ...
52
+
53
+ class TerminateServicesRequest(_message.Message):
54
+ __slots__ = ("service_names", "purge", "pool")
55
+ SERVICE_NAMES_FIELD_NUMBER: _ClassVar[int]
56
+ PURGE_FIELD_NUMBER: _ClassVar[int]
57
+ POOL_FIELD_NUMBER: _ClassVar[int]
58
+ service_names: ServiceNames
59
+ purge: bool
60
+ pool: bool
61
+ def __init__(self, service_names: _Optional[_Union[ServiceNames, _Mapping]] = ..., purge: bool = ..., pool: bool = ...) -> None: ...
62
+
63
+ class TerminateServicesResponse(_message.Message):
64
+ __slots__ = ("message",)
65
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
66
+ message: str
67
+ def __init__(self, message: _Optional[str] = ...) -> None: ...
68
+
69
+ class TerminateReplicaRequest(_message.Message):
70
+ __slots__ = ("service_name", "replica_id", "purge")
71
+ SERVICE_NAME_FIELD_NUMBER: _ClassVar[int]
72
+ REPLICA_ID_FIELD_NUMBER: _ClassVar[int]
73
+ PURGE_FIELD_NUMBER: _ClassVar[int]
74
+ service_name: str
75
+ replica_id: int
76
+ purge: bool
77
+ def __init__(self, service_name: _Optional[str] = ..., replica_id: _Optional[int] = ..., purge: bool = ...) -> None: ...
78
+
79
+ class TerminateReplicaResponse(_message.Message):
80
+ __slots__ = ("message",)
81
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
82
+ message: str
83
+ def __init__(self, message: _Optional[str] = ...) -> None: ...
84
+
85
+ class WaitServiceRegistrationRequest(_message.Message):
86
+ __slots__ = ("service_name", "job_id", "pool")
87
+ SERVICE_NAME_FIELD_NUMBER: _ClassVar[int]
88
+ JOB_ID_FIELD_NUMBER: _ClassVar[int]
89
+ POOL_FIELD_NUMBER: _ClassVar[int]
90
+ service_name: str
91
+ job_id: int
92
+ pool: bool
93
+ def __init__(self, service_name: _Optional[str] = ..., job_id: _Optional[int] = ..., pool: bool = ...) -> None: ...
94
+
95
+ class WaitServiceRegistrationResponse(_message.Message):
96
+ __slots__ = ("lb_port",)
97
+ LB_PORT_FIELD_NUMBER: _ClassVar[int]
98
+ lb_port: int
99
+ def __init__(self, lb_port: _Optional[int] = ...) -> None: ...
100
+
101
+ class UpdateServiceRequest(_message.Message):
102
+ __slots__ = ("service_name", "version", "mode", "pool")
103
+ SERVICE_NAME_FIELD_NUMBER: _ClassVar[int]
104
+ VERSION_FIELD_NUMBER: _ClassVar[int]
105
+ MODE_FIELD_NUMBER: _ClassVar[int]
106
+ POOL_FIELD_NUMBER: _ClassVar[int]
107
+ service_name: str
108
+ version: int
109
+ mode: str
110
+ pool: bool
111
+ def __init__(self, service_name: _Optional[str] = ..., version: _Optional[int] = ..., mode: _Optional[str] = ..., pool: bool = ...) -> None: ...
112
+
113
+ class UpdateServiceResponse(_message.Message):
114
+ __slots__ = ()
115
+ def __init__(self) -> None: ...