dstack 0.19.10__py3-none-any.whl → 0.19.11rc1__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 dstack might be problematic. Click here for more details.

@@ -39,8 +39,6 @@ class MetricsCommand(APIBaseCommand):
39
39
  run = self.api.runs.get(run_name=args.run_name)
40
40
  if run is None:
41
41
  raise CLIError(f"Run {args.run_name} not found")
42
- if run.status.is_finished():
43
- raise CLIError(f"Run {args.run_name} is finished")
44
42
  metrics = _get_run_jobs_metrics(api=self.api, run=run)
45
43
 
46
44
  if not args.watch:
@@ -55,8 +53,6 @@ class MetricsCommand(APIBaseCommand):
55
53
  run = self.api.runs.get(run_name=args.run_name)
56
54
  if run is None:
57
55
  raise CLIError(f"Run {args.run_name} not found")
58
- if run.status.is_finished():
59
- raise CLIError(f"Run {args.run_name} is finished")
60
56
  metrics = _get_run_jobs_metrics(api=self.api, run=run)
61
57
  except KeyboardInterrupt:
62
58
  pass
@@ -78,11 +74,12 @@ def _get_run_jobs_metrics(api: Client, run: Run) -> List[JobMetrics]:
78
74
  def _get_metrics_table(run: Run, metrics: List[JobMetrics]) -> Table:
79
75
  table = Table(box=None)
80
76
  table.add_column("NAME", style="bold", no_wrap=True)
77
+ table.add_column("STATUS")
81
78
  table.add_column("CPU")
82
79
  table.add_column("MEMORY")
83
80
  table.add_column("GPU")
84
81
 
85
- run_row: Dict[Union[str, int], Any] = {"NAME": run.name}
82
+ run_row: Dict[Union[str, int], Any] = {"NAME": run.name, "STATUS": run.status.value}
86
83
  if len(run._run.jobs) != 1:
87
84
  add_row_from_dict(table, run_row)
88
85
 
@@ -101,9 +98,9 @@ def _get_metrics_table(run: Run, metrics: List[JobMetrics]) -> Table:
101
98
  cpu_usage = f"{cpu_usage:.0f}%"
102
99
  memory_usage = _get_metric_value(job_metrics, "memory_working_set_bytes")
103
100
  if memory_usage is not None:
104
- memory_usage = f"{round(memory_usage / 1024 / 1024)}MB"
101
+ memory_usage = _format_memory(memory_usage, 2)
105
102
  if resources is not None:
106
- memory_usage += f"/{resources.memory_mib}MB"
103
+ memory_usage += f"/{_format_memory(resources.memory_mib * 1024 * 1024, 2)}"
107
104
  gpu_metrics = ""
108
105
  gpus_detected_num = _get_metric_value(job_metrics, "gpus_detected_num")
109
106
  if gpus_detected_num is not None:
@@ -113,13 +110,16 @@ def _get_metrics_table(run: Run, metrics: List[JobMetrics]) -> Table:
113
110
  if gpu_memory_usage is not None:
114
111
  if i != 0:
115
112
  gpu_metrics += "\n"
116
- gpu_metrics += f"#{i} {round(gpu_memory_usage / 1024 / 1024)}MB"
113
+ gpu_metrics += f"gpu={i} mem={_format_memory(gpu_memory_usage, 2)}"
117
114
  if resources is not None:
118
- gpu_metrics += f"/{resources.gpus[i].memory_mib}MB"
119
- gpu_metrics += f" {gpu_util_percent}% Util"
115
+ gpu_metrics += (
116
+ f"/{_format_memory(resources.gpus[i].memory_mib * 1024 * 1024, 2)}"
117
+ )
118
+ gpu_metrics += f" util={gpu_util_percent}%"
120
119
 
121
120
  job_row: Dict[Union[str, int], Any] = {
122
121
  "NAME": f" replica={job.job_spec.replica_num} job={job.job_spec.job_num}",
122
+ "STATUS": job.job_submissions[-1].status.value,
123
123
  "CPU": cpu_usage or "-",
124
124
  "MEMORY": memory_usage or "-",
125
125
  "GPU": gpu_metrics or "-",
@@ -136,3 +136,18 @@ def _get_metric_value(job_metrics: JobMetrics, name: str) -> Optional[Any]:
136
136
  if metric.name == name:
137
137
  return metric.values[-1]
138
138
  return None
139
+
140
+
141
+ def _format_memory(memory_bytes: int, decimal_places: int) -> str:
142
+ """See test_format_memory in tests/_internal/cli/commands/test_metrics.py for examples."""
143
+ memory_mb = memory_bytes / 1024 / 1024
144
+ if memory_mb >= 1024:
145
+ value = memory_mb / 1024
146
+ unit = "GB"
147
+ else:
148
+ value = memory_mb
149
+ unit = "MB"
150
+
151
+ if decimal_places == 0:
152
+ return f"{round(value)}{unit}"
153
+ return f"{value:.{decimal_places}f}".rstrip("0").rstrip(".") + unit
@@ -391,11 +391,8 @@ class VMImageVariant(enum.Enum):
391
391
 
392
392
 
393
393
  _SUPPORTED_VM_SERIES_PATTERNS = [
394
- # TODO: Support newer CPU series (Dsv6, Esv6).
395
- # They are NVMe-only and require marking the VM image as NVMe.
396
- r"D(\d+)s_v3", # Dsv3-series (general purpose)
397
- r"E(\d+)i?s_v4", # Esv4-series (memory optimized)
398
- r"E(\d+)-(\d+)s_v4", # Esv4-series (constrained vCPU)
394
+ r"D(\d+)s_v6", # Dsv6-series (general purpose)
395
+ r"E(\d+)i?s_v6", # Esv6-series (memory optimized)
399
396
  r"F(\d+)s_v2", # Fsv2-series (compute optimized)
400
397
  r"NC(\d+)s_v3", # NCv3-series [V100 16GB]
401
398
  r"NC(\d+)as_T4_v3", # NCasT4_v3-series [T4]
@@ -404,6 +401,11 @@ _SUPPORTED_VM_SERIES_PATTERNS = [
404
401
  r"NC(\d+)ads_A100_v4", # NC A100 v4-series [A100 80GB]
405
402
  r"ND(\d+)asr_v4", # ND A100 v4-series [8xA100 40GB]
406
403
  r"ND(\d+)amsr_A100_v4", # NDm A100 v4-series [8xA100 80GB]
404
+ # Deprecated series
405
+ # TODO: Remove after several releases
406
+ r"D(\d+)s_v3", # Dsv3-series (general purpose)
407
+ r"E(\d+)i?s_v4", # Esv4-series (memory optimized)
408
+ r"E(\d+)-(\d+)s_v4", # Esv4-series (constrained vCPU)
407
409
  ]
408
410
  _SUPPORTED_VM_SERIES_PATTERN = (
409
411
  "^Standard_(" + "|".join(f"({s})" for s in _SUPPORTED_VM_SERIES_PATTERNS) + ")$"
@@ -19,6 +19,7 @@ from dstack._internal.core.consts import (
19
19
  DSTACK_RUNNER_SSH_PORT,
20
20
  DSTACK_SHIM_HTTP_PORT,
21
21
  )
22
+ from dstack._internal.core.models.configurations import DEFAULT_REPO_DIR
22
23
  from dstack._internal.core.models.gateways import (
23
24
  GatewayComputeConfiguration,
24
25
  GatewayProvisioningData,
@@ -754,7 +755,7 @@ def get_docker_commands(
754
755
  f" --ssh-port {DSTACK_RUNNER_SSH_PORT}"
755
756
  " --temp-dir /tmp/runner"
756
757
  " --home-dir /root"
757
- " --working-dir /workflow"
758
+ f" --working-dir {DEFAULT_REPO_DIR}"
758
759
  ),
759
760
  ]
760
761
 
@@ -26,6 +26,7 @@ STRIP_PREFIX_DEFAULT = True
26
26
  RUN_PRIOTIRY_MIN = 0
27
27
  RUN_PRIOTIRY_MAX = 100
28
28
  RUN_PRIORITY_DEFAULT = 0
29
+ DEFAULT_REPO_DIR = "/workflow"
29
30
 
30
31
 
31
32
  class RunConfigurationType(str, Enum):
@@ -181,7 +182,7 @@ class BaseRunConfiguration(CoreModel):
181
182
  Field(
182
183
  description=(
183
184
  "The path to the working directory inside the container."
184
- " It's specified relative to the repository directory (`/workflow`) and should be inside it."
185
+ f" It's specified relative to the repository directory (`{DEFAULT_REPO_DIR}`) and should be inside it."
185
186
  ' Defaults to `"."` '
186
187
  )
187
188
  ),
@@ -8,6 +8,7 @@ from typing_extensions import Annotated
8
8
  from dstack._internal.core.models.backends.base import BackendType
9
9
  from dstack._internal.core.models.common import ApplyAction, CoreModel, NetworkMode, RegistryAuth
10
10
  from dstack._internal.core.models.configurations import (
11
+ DEFAULT_REPO_DIR,
11
12
  AnyRunConfiguration,
12
13
  RunConfiguration,
13
14
  )
@@ -338,7 +339,7 @@ class RunSpec(CoreModel):
338
339
  Field(
339
340
  description=(
340
341
  "The path to the working directory inside the container."
341
- " It's specified relative to the repository directory (`/workflow`) and should be inside it."
342
+ f" It's specified relative to the repository directory (`{DEFAULT_REPO_DIR}`) and should be inside it."
342
343
  ' Defaults to `"."`.'
343
344
  )
344
345
  ),
@@ -1 +1,11 @@
1
- log_format dstack_stat '$time_iso8601 $host $status $request_time';
1
+ log_format dstack_stat '$time_iso8601 $host $status $request_time $dstack_replica_hit';
2
+
3
+
4
+ # A hack to avoid this Nginx reload error when no services are registered:
5
+ # nginx: [emerg] unknown "dstack_replica_hit" variable
6
+ server {
7
+ listen unix:/tmp/dstack-dummy-nginx.sock;
8
+ server_name placeholder.local;
9
+ deny all;
10
+ set $dstack_replica_hit 0;
11
+ }
@@ -14,6 +14,7 @@ upstream {{ domain }}.upstream {
14
14
  server {
15
15
  server_name {{ domain }};
16
16
  limit_req_status 429;
17
+ set $dstack_replica_hit 0;
17
18
  access_log {{ access_log_path }} dstack_stat;
18
19
  client_max_body_size {{ client_max_body_size }};
19
20
 
@@ -23,11 +24,7 @@ server {
23
24
  auth_request /_dstack_auth;
24
25
  {% endif %}
25
26
 
26
- {% if replicas %}
27
27
  try_files /nonexistent @$http_upgrade;
28
- {% else %}
29
- return 503;
30
- {% endif %}
31
28
 
32
29
  {% if location.limit_req %}
33
30
  limit_req zone={{ location.limit_req.zone }}{% if location.limit_req.burst %} burst={{ location.limit_req.burst }} nodelay{% endif %};
@@ -35,8 +32,9 @@ server {
35
32
  }
36
33
  {% endfor %}
37
34
 
38
- {% if replicas %}
39
35
  location @websocket {
36
+ set $dstack_replica_hit 1;
37
+ {% if replicas %}
40
38
  proxy_pass http://{{ domain }}.upstream;
41
39
  proxy_set_header X-Real-IP $remote_addr;
42
40
  proxy_set_header Host $host;
@@ -44,19 +42,27 @@ server {
44
42
  proxy_set_header Upgrade $http_upgrade;
45
43
  proxy_set_header Connection "Upgrade";
46
44
  proxy_read_timeout 300s;
45
+ {% else %}
46
+ return 503;
47
+ {% endif %}
47
48
  }
48
49
  location @ {
50
+ set $dstack_replica_hit 1;
51
+ {% if replicas %}
49
52
  proxy_pass http://{{ domain }}.upstream;
50
53
  proxy_set_header X-Real-IP $remote_addr;
51
54
  proxy_set_header Host $host;
52
55
  proxy_read_timeout 300s;
56
+ {% else %}
57
+ return 503;
58
+ {% endif %}
53
59
  }
54
- {% endif %}
55
60
 
56
61
  {% if auth %}
57
62
  location = /_dstack_auth {
58
63
  internal;
59
64
  if ($remote_addr = 127.0.0.1) {
65
+ # for requests from the gateway app, e.g. from the OpenAI-compatible API
60
66
  return 200;
61
67
  }
62
68
  proxy_pass http://localhost:{{ proxy_port }}/api/auth/{{ project_name }};
@@ -11,10 +11,10 @@ from pydantic import BaseModel
11
11
 
12
12
  from dstack._internal.proxy.gateway.repo.repo import GatewayProxyRepo
13
13
  from dstack._internal.proxy.gateway.schemas.stats import PerWindowStats, ServiceStats, Stat
14
+ from dstack._internal.proxy.lib.errors import UnexpectedProxyError
14
15
  from dstack._internal.utils.common import run_async
15
16
 
16
17
  logger = logging.getLogger(__name__)
17
- IGNORE_STATUSES = {403, 404}
18
18
  WINDOWS = (30, 60, 300)
19
19
  TTL = WINDOWS[-1]
20
20
  EMPTY_STATS = {window: Stat(requests=0, request_time=0.0) for window in WINDOWS}
@@ -35,6 +35,7 @@ class LogEntry(BaseModel):
35
35
  host: str
36
36
  status: int
37
37
  request_time: float
38
+ is_replica_hit: bool
38
39
 
39
40
 
40
41
  class StatsCollector:
@@ -87,7 +88,8 @@ class StatsCollector:
87
88
  now = datetime.datetime.now(tz=datetime.timezone.utc)
88
89
 
89
90
  for entry in self._read_access_log(now - datetime.timedelta(seconds=TTL)):
90
- if entry.status in IGNORE_STATUSES:
91
+ # only include requests that hit or should hit a service replica
92
+ if not entry.is_replica_hit:
91
93
  continue
92
94
 
93
95
  frame_timestamp = int(entry.timestamp.timestamp())
@@ -119,7 +121,10 @@ class StatsCollector:
119
121
  line = self._file.readline()
120
122
  if not line:
121
123
  break
122
- timestamp_str, host, status, request_time = line.split()
124
+ cells = line.split()
125
+ if len(cells) == 4: # compatibility with pre-0.19.11 logs
126
+ cells.append("0" if cells[2] in ["403", "404"] else "1")
127
+ timestamp_str, host, status, request_time, dstack_replica_hit = cells
123
128
  timestamp = datetime.datetime.fromisoformat(timestamp_str)
124
129
  if timestamp < after:
125
130
  continue
@@ -128,6 +133,7 @@ class StatsCollector:
128
133
  host=host,
129
134
  status=int(status),
130
135
  request_time=float(request_time),
136
+ is_replica_hit=_parse_nginx_bool(dstack_replica_hit),
131
137
  )
132
138
  if os.fstat(self._file.fileno()).st_ino != st_ino:
133
139
  # file was rotated
@@ -154,3 +160,11 @@ async def get_service_stats(
154
160
  )
155
161
  for service in services
156
162
  ]
163
+
164
+
165
+ def _parse_nginx_bool(v: str) -> bool:
166
+ if v == "0":
167
+ return False
168
+ if v == "1":
169
+ return True
170
+ raise UnexpectedProxyError(f"Cannot parse boolean value: expected '0' or '1', got {v!r}")
@@ -10,6 +10,7 @@ from dstack._internal import settings
10
10
  from dstack._internal.core.errors import DockerRegistryError, ServerClientError
11
11
  from dstack._internal.core.models.common import RegistryAuth
12
12
  from dstack._internal.core.models.configurations import (
13
+ DEFAULT_REPO_DIR,
13
14
  PortMapping,
14
15
  PythonVersion,
15
16
  RunConfigurationType,
@@ -149,7 +150,8 @@ class JobConfigurator(ABC):
149
150
  commands = self.run_spec.configuration.commands
150
151
  elif shell_commands := self._shell_commands():
151
152
  entrypoint = [self._shell(), "-i", "-c"]
152
- commands = [_join_shell_commands(shell_commands)]
153
+ dstack_image_commands = self._dstack_image_commands()
154
+ commands = [_join_shell_commands(dstack_image_commands + shell_commands)]
153
155
  else: # custom docker image without commands
154
156
  image_config = await self._get_image_config()
155
157
  entrypoint = image_config.entrypoint or []
@@ -164,6 +166,18 @@ class JobConfigurator(ABC):
164
166
 
165
167
  return result
166
168
 
169
+ def _dstack_image_commands(self) -> List[str]:
170
+ if (
171
+ self.run_spec.configuration.image is not None
172
+ or self.run_spec.configuration.entrypoint is not None
173
+ ):
174
+ return []
175
+ return [
176
+ f"uv venv --prompt workflow --seed {DEFAULT_REPO_DIR}/.venv > /dev/null 2>&1",
177
+ f"echo 'source {DEFAULT_REPO_DIR}/.venv/bin/activate' >> ~/.bashrc",
178
+ f"source {DEFAULT_REPO_DIR}/.venv/bin/activate",
179
+ ]
180
+
167
181
  def _app_specs(self) -> List[AppSpec]:
168
182
  specs = []
169
183
  for i, pm in enumerate(filter_reserved_ports(self._ports())):
@@ -1,5 +1,7 @@
1
1
  from typing import List
2
2
 
3
+ from dstack._internal.core.models.configurations import DEFAULT_REPO_DIR
4
+
3
5
 
4
6
  class CursorDesktop:
5
7
  def __init__(
@@ -37,6 +39,6 @@ class CursorDesktop:
37
39
  return [
38
40
  "echo To open in Cursor, use link below:",
39
41
  "echo ''",
40
- f"echo ' cursor://vscode-remote/ssh-remote+{self.run_name}/workflow'", # TODO use $REPO_DIR
42
+ f"echo ' cursor://vscode-remote/ssh-remote+{self.run_name}{DEFAULT_REPO_DIR}'", # TODO use $REPO_DIR
41
43
  "echo ''",
42
44
  ]
@@ -1,5 +1,7 @@
1
1
  from typing import List
2
2
 
3
+ from dstack._internal.core.models.configurations import DEFAULT_REPO_DIR
4
+
3
5
 
4
6
  class VSCodeDesktop:
5
7
  def __init__(
@@ -37,6 +39,6 @@ class VSCodeDesktop:
37
39
  return [
38
40
  "echo To open in VS Code Desktop, use link below:",
39
41
  "echo ''",
40
- f"echo ' vscode://vscode-remote/ssh-remote+{self.run_name}/workflow'", # TODO use $REPO_DIR
42
+ f"echo ' vscode://vscode-remote/ssh-remote+{self.run_name}{DEFAULT_REPO_DIR}'", # TODO use $REPO_DIR
41
43
  "echo ''",
42
44
  ]
dstack/version.py CHANGED
@@ -1,3 +1,3 @@
1
- __version__ = "0.19.10"
1
+ __version__ = "0.19.11rc1"
2
2
  __is_release__ = True
3
- base_image = "0.7"
3
+ base_image = "0.8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dstack
3
- Version: 0.19.10
3
+ Version: 0.19.11rc1
4
4
  Summary: dstack is an open-source orchestration engine for running AI workloads on any cloud or on-premises.
5
5
  Project-URL: Homepage, https://dstack.ai
6
6
  Project-URL: Source, https://github.com/dstackai/dstack
@@ -1,5 +1,5 @@
1
1
  dstack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- dstack/version.py,sha256=1w-1PVkazoEpWhJboy2UsLiK2Ezuk8Le2ZyTHPXYf7E,65
2
+ dstack/version.py,sha256=GxG1ziHLEcRXoddW7khMHK2u0fShzLeWrp1qMzeZKMQ,68
3
3
  dstack/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  dstack/_internal/compat.py,sha256=bF9U9fTMfL8UVhCouedoUSTYFl7UAOiU0WXrnRoByxw,40
5
5
  dstack/_internal/settings.py,sha256=GOqfcLEONWC1hGU36IYPuOhJXP_qC3Y6d2SQge_NdpY,953
@@ -15,7 +15,7 @@ dstack/_internal/cli/commands/fleet.py,sha256=J0Yi5CAYvIQF_NC4ZBsDYGc3grTOtvaF7s
15
15
  dstack/_internal/cli/commands/gateway.py,sha256=DcD6P_MvXbSL9aXkLX9hgGYSAzARjgY6RSbrCMzdNcg,6075
16
16
  dstack/_internal/cli/commands/init.py,sha256=bLhSlViNWtjflB6xNq_PuCR2o2A06h222luh1NeUgVA,1169
17
17
  dstack/_internal/cli/commands/logs.py,sha256=o8ehPAKM12Xn9thg2jjnYdr7_wKqF-00ziVry8IVVwE,1528
18
- dstack/_internal/cli/commands/metrics.py,sha256=nxdTcyCvHNev7Mn19zGQ7vTHUBGY6hyvPtY6Z731SOU,5373
18
+ dstack/_internal/cli/commands/metrics.py,sha256=ZS_dHD4_YK135J09xKpVTY_3CXzhj8QhDo18Ail9Pas,5862
19
19
  dstack/_internal/cli/commands/offer.py,sha256=rf10T9ohEC77GmZexdqF_RBCQkLYzVSAwTzZlxukNYM,4085
20
20
  dstack/_internal/cli/commands/project.py,sha256=V8gJwQWQGvGKQJPUyce_M7Ij_B7bOxYzo2IQgkLLHFE,6151
21
21
  dstack/_internal/cli/commands/ps.py,sha256=5RU4mcL4-FT4PcXktfKb4htCOPqia7mIuVGgfK7x9lY,1894
@@ -58,14 +58,14 @@ dstack/_internal/core/backends/aws/resources.py,sha256=Wht_USG8ps9HQBhAYfxDxjaob
58
58
  dstack/_internal/core/backends/azure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  dstack/_internal/core/backends/azure/auth.py,sha256=CHp3QRNx3tIwkhyOY_l8WU-ElY4Pxhavoy9JSdwr15g,1259
60
60
  dstack/_internal/core/backends/azure/backend.py,sha256=XySTor8v_tLkZctDBryrFHrbVzQgNf_RUPkXQYplvwM,746
61
- dstack/_internal/core/backends/azure/compute.py,sha256=3CH6m1ytCG-cvj3sAQG3BPpehZQ7XQkAFE8JOyja0V8,24433
61
+ dstack/_internal/core/backends/azure/compute.py,sha256=waunprBzpiJBMtVDJMjFCxEdmtO52E7ckzcc6OcZLf4,24488
62
62
  dstack/_internal/core/backends/azure/configurator.py,sha256=cC0YhiayPtrOEEr8Lr-9nDDq6v2-sbxK-1QhixpM1YY,18228
63
63
  dstack/_internal/core/backends/azure/models.py,sha256=ap0WsYBSFdDCxY0G3W1sg2DBN2k0xknz6bp8Ypf6phs,3356
64
64
  dstack/_internal/core/backends/azure/resources.py,sha256=cJWS2Yjxdg-XtjpdBxfVDZaX_gTbuoEpmdjTxdA9uIw,3431
65
65
  dstack/_internal/core/backends/azure/utils.py,sha256=taHMJq6UHRzUXLUcO2P5VCKy3wJaye2bG-6QdkEPNdY,1741
66
66
  dstack/_internal/core/backends/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
67
  dstack/_internal/core/backends/base/backend.py,sha256=hdFMHED1RMV9GVfLSU0yGhGE-cXlbLvt1coDA885PMM,505
68
- dstack/_internal/core/backends/base/compute.py,sha256=0APW_2yo4zO-mHw6vg-5nnMnwppR4QPGrFN3GQmD-EU,28542
68
+ dstack/_internal/core/backends/base/compute.py,sha256=XblmmEz4muUjcnlIudKEwoPSaqMBVZtbOcwgGs47Xvc,28625
69
69
  dstack/_internal/core/backends/base/configurator.py,sha256=OCv8N2oxcxy3In2zS1PKiCJ0a-COZwxGjBz2FYkQnfg,3807
70
70
  dstack/_internal/core/backends/base/models.py,sha256=Ij0osOl-T-ABsKLoVg2eY81DMkwdWkevAnjXj2QnLXI,532
71
71
  dstack/_internal/core/backends/base/offers.py,sha256=AzAAx5eSTaHv8CbWuGERTHS151x4oJuQn3tr_Bz9HKQ,6282
@@ -156,7 +156,7 @@ dstack/_internal/core/backends/vultr/models.py,sha256=TkqK_lW6w5k_7wsoFiKDb6NXuT
156
156
  dstack/_internal/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
157
  dstack/_internal/core/models/common.py,sha256=XWd79dmFGMrdpTcStH5fVmNXCKE0s7FsIorPL0saQ8w,2138
158
158
  dstack/_internal/core/models/config.py,sha256=JJ7rT7dztzTWCY5TkoyxXxTvG5D4IFYhGe7EzwkLOWQ,581
159
- dstack/_internal/core/models/configurations.py,sha256=I-BRBls-oSZ2EZy5glC4_PJbdM-_KnoAxl6gm1u16tg,19027
159
+ dstack/_internal/core/models/configurations.py,sha256=yG5GaCbTK4QhSh0UMYrYpFSeFvD0f-Uhi3TT_XviGhQ,19068
160
160
  dstack/_internal/core/models/envs.py,sha256=yq84YRFBILOy4x3XnGcTgYpbZ69eFTCQPgBCr9Ndov4,4969
161
161
  dstack/_internal/core/models/fleets.py,sha256=gbP2rj1ODDuy4IfTbPNB-ae050thvzTtA8uDb5iTmdY,12059
162
162
  dstack/_internal/core/models/gateways.py,sha256=_O8EWwHWLdgNoWY4P4u71KM-uEr5DDp42LXfyv1qMDI,4054
@@ -167,7 +167,7 @@ dstack/_internal/core/models/placement.py,sha256=WJVq5ENJykyRarQzL2EeYQag_9_jV7V
167
167
  dstack/_internal/core/models/profiles.py,sha256=seeysTuMv1vVUmpHAZgrMUGcbMtH7hSMFIvfx0Qk__0,10406
168
168
  dstack/_internal/core/models/projects.py,sha256=H5ZZRiyUEKifpTFAhl45KBi5ly7ooE0WmI329myK360,643
169
169
  dstack/_internal/core/models/resources.py,sha256=rsf6hAhi5bfSb_Z9VcS3UoEG0G8Ohl6ekyrOStLOAqw,14114
170
- dstack/_internal/core/models/runs.py,sha256=Xkv1kY68JA0eJUeCVJjM9YWRkfy6P1RGXslBIMtox2E,18985
170
+ dstack/_internal/core/models/runs.py,sha256=6egFnxV0qGs-XCr22RvJc-rSpc3zsNIk2UF3cRdWlX4,19017
171
171
  dstack/_internal/core/models/secrets.py,sha256=IQyemsNpSzqOCB-VlVTuc4gyPFmXXO4mhko0Ur0ey3I,221
172
172
  dstack/_internal/core/models/server.py,sha256=Hkc1v2s3KOiwslsWVmhUOAzcSeREoG-HD1SzSX9WUGg,152
173
173
  dstack/_internal/core/models/services.py,sha256=2Hpi7j0Q1shaf_0wd0C0044AJAmuYi-D3qx3PH849oI,3076
@@ -204,9 +204,9 @@ dstack/_internal/proxy/gateway/models.py,sha256=OLarOKJj-6teeg9dvxp3ueRv2_7yDJJf
204
204
  dstack/_internal/proxy/gateway/repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
205
  dstack/_internal/proxy/gateway/repo/repo.py,sha256=0i9FaLwDLnf8hijtRjT8hBooWj7EJ6L0_WJMbFaIBmo,4629
206
206
  dstack/_internal/proxy/gateway/repo/state_v1.py,sha256=fngXqJWONuoJZEQcKHgiOGvs-ZQ3NATMzUFn67w4xxY,5943
207
- dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf,sha256=hqo9-5Ss1htl6s0dxXnnj1Mgjgs3ijJS8QmZ529CQaI,68
207
+ dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf,sha256=-nVcJRFb4qbxy-t9BOq03dvdBtZ-P-Fi81gOzS0GnPc,361
208
208
  dstack/_internal/proxy/gateway/resources/nginx/entrypoint.jinja2,sha256=umnUlm34wfoLNik3GFr1Gn2jtZMAx1-kgjBYcY3sLAU,817
209
- dstack/_internal/proxy/gateway/resources/nginx/service.jinja2,sha256=9ulU4qh1fQwJvh478srAlRcay6s9nONsEnO7NYcMa7A,2547
209
+ dstack/_internal/proxy/gateway/resources/nginx/service.jinja2,sha256=sccX4pIfdErti7VPhvN_9ObEJgbvsZc-COTJk1dUe8U,2780
210
210
  dstack/_internal/proxy/gateway/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
211
211
  dstack/_internal/proxy/gateway/routers/auth.py,sha256=PCMYEy2HLbiSZgqrtMUH90hbMAMXHp1nSZ0j13Nlrhs,253
212
212
  dstack/_internal/proxy/gateway/routers/config.py,sha256=1UKHAPSYkeG8ULl9X3Eu6nPg94Xp-fecTObRa5Yw294,908
@@ -221,7 +221,7 @@ dstack/_internal/proxy/gateway/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
221
221
  dstack/_internal/proxy/gateway/services/nginx.py,sha256=tGvs0Ci1X0aO8HjaflCgkxEXop0Z7o6euw7ADfCUOro,6149
222
222
  dstack/_internal/proxy/gateway/services/registry.py,sha256=Gqyri5PaJW79iRYufawS09XHO_q7a1Re3tx2dGjBTfQ,13580
223
223
  dstack/_internal/proxy/gateway/services/server_client.py,sha256=KSnpO8iPm5wxQPU0DcW7kqUzwliaQrb3b0K8Jmk8iA0,3630
224
- dstack/_internal/proxy/gateway/services/stats.py,sha256=i88GpWMUlB8tZTWAQHPNh420qbgSGAhnaxNgQN2zK78,5326
224
+ dstack/_internal/proxy/gateway/services/stats.py,sha256=F1LI34oXk_vF3VkWqpRnf_aO2ykECv6_WmBlZVa2jU8,5945
225
225
  dstack/_internal/proxy/gateway/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
226
226
  dstack/_internal/proxy/gateway/testing/common.py,sha256=K50IHpdxM9NpojVPrFFEaZyMwTAHvDU76VLB3qlZBn8,269
227
227
  dstack/_internal/proxy/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -402,14 +402,14 @@ dstack/_internal/server/services/gateways/connection.py,sha256=ot3lV85XdmCT45vBW
402
402
  dstack/_internal/server/services/gateways/pool.py,sha256=0LclTl1tyx-doS78LeaAKjr-SMp98zuwh5f9s06JSd0,1914
403
403
  dstack/_internal/server/services/jobs/__init__.py,sha256=GU3vMC0SZKyvL564A7t_QRoDjf83-8GsUkguDWK5x6c,25578
404
404
  dstack/_internal/server/services/jobs/configurators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
405
- dstack/_internal/server/services/jobs/configurators/base.py,sha256=kgCbEom7hGPunrUxXI0NjXGlTdNq_Q27u56lrExDnT8,11390
405
+ dstack/_internal/server/services/jobs/configurators/base.py,sha256=WLRIBM50P8mfvpotzYjK3Gtf5ScQsuijGieH_zaYqCg,11984
406
406
  dstack/_internal/server/services/jobs/configurators/dev.py,sha256=ufN6Sd8TwIsjQYNZE32fkAqJI7o2zjgoZThbrP-bd7U,2378
407
407
  dstack/_internal/server/services/jobs/configurators/service.py,sha256=FOWrLE-6YFSMuGqjOwYTLMV4FuIM5lCMDFjS0l0CoLI,929
408
408
  dstack/_internal/server/services/jobs/configurators/task.py,sha256=0-B3oO-61Eq4-mmlLmqJPliFKHhvvIV0tqc12slcQuA,1436
409
409
  dstack/_internal/server/services/jobs/configurators/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
410
410
  dstack/_internal/server/services/jobs/configurators/extensions/base.py,sha256=xJbHxaaSJ1zjn8zuuApP1Xt2uBaedPhhc-IY0NtDDJQ,418
411
- dstack/_internal/server/services/jobs/configurators/extensions/cursor.py,sha256=00HB1kC_eMlioEW0nZI7Ly78b-RSehySVNhC9pajBP8,1636
412
- dstack/_internal/server/services/jobs/configurators/extensions/vscode.py,sha256=DAj8OEVLyL1x8Jko2EXKhnAkcSnlO1sJk6o6eiiVkDI,1611
411
+ dstack/_internal/server/services/jobs/configurators/extensions/cursor.py,sha256=r6Cgdd-P5C63xXyrqC6E0yNKIeTX6KabRLO92VEpJRY,1719
412
+ dstack/_internal/server/services/jobs/configurators/extensions/vscode.py,sha256=WRg_jqi4eSqbs3XRVASMFF7OQHYRDtVBNn6NCroJY1I,1694
413
413
  dstack/_internal/server/services/logs/__init__.py,sha256=NAjO1KeYvuDznN2EkfAaJt9S6Y00fo_dl3ob3WmsdGQ,3088
414
414
  dstack/_internal/server/services/logs/aws.py,sha256=MuRVGgYwkh0TA11Y2H0upSj56-k_Bs-vT_oa2X-5yZE,13834
415
415
  dstack/_internal/server/services/logs/base.py,sha256=7eCB6SPF9iWviv4vZ_34SvfM_Bvi9DeVj1t7TxmrXKs,1273
@@ -584,8 +584,8 @@ dstack/plugins/__init__.py,sha256=buT1pcyORLgVbl89ATkRWJPhvejriVz7sNBjvuZRCRE,40
584
584
  dstack/plugins/_base.py,sha256=-etiB-EozaJCg2wtmONfj8ic-K03qXvXyl_TIDp-kNE,2662
585
585
  dstack/plugins/_models.py,sha256=1Gw--mDQ1_0FFr9Zur9LE8UbMoWESUpTdHHt12AyIZo,341
586
586
  dstack/plugins/_utils.py,sha256=FqeWYb7zOrgZkO9Bd8caL5I81_TUEsysIzvxsULrmzk,392
587
- dstack-0.19.10.dist-info/METADATA,sha256=kOxSPHWY8taNRczMVwanWtP_p-0KmFJbOSE7vCKQsKk,20509
588
- dstack-0.19.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
589
- dstack-0.19.10.dist-info/entry_points.txt,sha256=GnLrMS8hx3rWAySQjA7tPNhtixV6a-brRkmal1PKoHc,58
590
- dstack-0.19.10.dist-info/licenses/LICENSE.md,sha256=qDABaRGjSKVOib1U8viw2P_96sIK7Puo426784oD9f8,15976
591
- dstack-0.19.10.dist-info/RECORD,,
587
+ dstack-0.19.11rc1.dist-info/METADATA,sha256=ZU6h89CiVMvwc_lXF_Cv4LI2DPdA6_zvPr7rZF1iTJY,20512
588
+ dstack-0.19.11rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
589
+ dstack-0.19.11rc1.dist-info/entry_points.txt,sha256=GnLrMS8hx3rWAySQjA7tPNhtixV6a-brRkmal1PKoHc,58
590
+ dstack-0.19.11rc1.dist-info/licenses/LICENSE.md,sha256=qDABaRGjSKVOib1U8viw2P_96sIK7Puo426784oD9f8,15976
591
+ dstack-0.19.11rc1.dist-info/RECORD,,