├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── config.yml │ └── feature_request.yaml └── workflows │ ├── build.yml │ ├── close-inactive-issues.yml │ ├── docker-amd-smi.yml │ ├── docker-dind.yml │ ├── docker-efa.yml │ ├── docker.yml │ ├── docs.yaml │ ├── gcp-a3mega-image.yml │ └── release.yml ├── .gitignore ├── .justfile ├── .pre-commit-config.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── contributing ├── ARCHITECTURE.md ├── AUTOSCALING.md ├── BACKENDS.md ├── DEVELOPMENT.md ├── FRONTEND.md ├── GPUHUNT.md ├── LOCKING.md ├── MIGRATIONS.md ├── PROXY.md ├── RUNNER-AND-SHIM.md └── RUNS-AND-JOBS.md ├── docker ├── amd-smi │ ├── Dockerfile │ └── README.md ├── base │ ├── Dockerfile │ └── README.md ├── dind │ ├── Dockerfile │ ├── README.md │ └── start-dockerd ├── efa │ ├── Dockerfile │ └── README.md └── server │ ├── README.md │ ├── entrypoint.sh │ ├── release │ └── Dockerfile │ └── stgn │ └── Dockerfile ├── docs ├── CNAME ├── assets │ ├── images │ │ ├── aws-logo.svg │ │ ├── azure-logo.svg │ │ ├── cats-in-hats.png │ │ ├── chevron-down.svg │ │ ├── cudo-logo.svg │ │ ├── datacrunch-logo.svg │ │ ├── discord-logo.svg │ │ ├── dstack-cli.png │ │ ├── dstack-code-dark.png │ │ ├── dstack-dev-environments-code.png │ │ ├── dstack-dolly-code.png │ │ ├── dstack-dolly.png │ │ ├── dstack-fav-32.ico │ │ ├── dstack-fine-tuning-diagram.png │ │ ├── dstack-finetuning-hf.png │ │ ├── dstack-finetuning-wandb.png │ │ ├── dstack-google-colab.png │ │ ├── dstack-gradio-falcon.png │ │ ├── dstack-hub-create-aws-project.png │ │ ├── dstack-hub-create-azure-project.png │ │ ├── dstack-hub-create-gcp-project.png │ │ ├── dstack-hub-create-lambda-project.png │ │ ├── dstack-hub-create-project.png │ │ ├── dstack-hub-edit-gateway.png │ │ ├── dstack-hub-view-project-empty.png │ │ ├── dstack-hub-view-project.png │ │ ├── dstack-huggingface-space.png │ │ ├── dstack-jupyterlab.png │ │ ├── dstack-lambda-api-key.png │ │ ├── dstack-llmchat-discord-chat.png │ │ ├── dstack-llmchat-gallery.png │ │ ├── dstack-logo-dark.svg │ │ ├── dstack-logo-notext.png │ │ ├── dstack-logo-notext.svg │ │ ├── dstack-logo.svg │ │ ├── dstack-mixtral-chat-ui.png │ │ ├── dstack-playground-github-actions-ui.png │ │ ├── dstack-run-artifacts.png │ │ ├── dstack-runpod-dev-environment.png │ │ ├── dstack-server-output-2.png │ │ ├── dstack-stable-diffusion-code.png │ │ ├── dstack-stable-diffusion.png │ │ ├── dstack-tensorboard.png │ │ ├── dstack-train-artifacts.png │ │ ├── dstack-v010-vscode-desktop.png │ │ ├── dstack-vscode-jupyter.png │ │ ├── dstack-vscode.png │ │ ├── gcp-logo.svg │ │ ├── github-logo.svg │ │ ├── hero_code_background.png │ │ ├── hotaisle-logo.svg │ │ ├── jb-toolbox-logo.svg │ │ ├── jupyter-logo.svg │ │ ├── kapa.svg │ │ ├── kubernetes-logo.svg │ │ ├── lambda-logo.svg │ │ ├── logo.svg │ │ ├── minus.svg │ │ ├── nebius-logo.svg │ │ ├── oci-logo.svg │ │ ├── plus.svg │ │ ├── runpod-logo.svg │ │ ├── ssh-logo.svg │ │ ├── tensordock-logo.svg │ │ ├── tensorwave-logo.svg │ │ ├── vastai-logo.svg │ │ ├── vscode-logo.svg │ │ └── vultr-logo.svg │ ├── javascripts │ │ ├── extra.js │ │ ├── pricing.js │ │ └── termynal.js │ └── stylesheets │ │ ├── extra.css │ │ ├── landing.css │ │ ├── pricing.css │ │ └── termynal.css ├── blog │ ├── archive │ │ └── ambassador-program.md │ ├── index.md │ └── posts │ │ ├── amd-mi300x-inference-benchmark.md │ │ ├── amd-on-runpod.md │ │ ├── amd-on-tensorwave.md │ │ ├── beyond-kubernetes-2024-recap-and-whats-ahead.md │ │ ├── cursor.md │ │ ├── docker-inside-containers.md │ │ ├── dstack-metrics.md │ │ ├── dstack-sky-own-cloud-accounts.md │ │ ├── dstack-sky.md │ │ ├── ea-gtc25.md │ │ ├── efa.md │ │ ├── gh200-on-lambda.md │ │ ├── gpu-blocks-and-proxy-jump.md │ │ ├── h100-mi300x-inference-benchmark.md │ │ ├── h200-mi300x-deepskeek-benchmark.md │ │ ├── images │ │ ├── dstack-diagram-stack-3.png │ │ ├── dstack-research-banner-2.png │ │ └── dstack-sky-banner-4.png │ │ ├── inactivity-duration.md │ │ ├── instance-volumes.md │ │ ├── intel-gaudi.md │ │ ├── metrics-ui.md │ │ ├── mpi.md │ │ ├── nebius.md │ │ ├── nvidia-and-amd-on-vultr.md │ │ ├── prometheus.md │ │ ├── tpu-on-gcp.md │ │ └── volumes-on-runpod.md ├── docs │ ├── concepts │ │ ├── backends.md │ │ ├── dev-environments.md │ │ ├── fleets.md │ │ ├── gateways.md │ │ ├── projects.md │ │ ├── repos.md │ │ ├── services.md │ │ ├── snippets │ │ │ ├── manage-fleets.ext │ │ │ └── manage-runs.ext │ │ ├── tasks.md │ │ └── volumes.md │ ├── guides │ │ ├── clusters.md │ │ ├── dstack-sky.md │ │ ├── metrics.md │ │ ├── plugins.md │ │ ├── protips.md │ │ ├── server-deployment.md │ │ └── troubleshooting.md │ ├── index.md │ ├── installation │ │ └── index.md │ ├── quickstart.md │ └── reference │ │ ├── api │ │ ├── python │ │ │ └── index.md │ │ └── rest │ │ │ └── index.md │ │ ├── cli │ │ └── dstack │ │ │ ├── apply.md │ │ │ ├── attach.md │ │ │ ├── config.md │ │ │ ├── delete.md │ │ │ ├── fleet.md │ │ │ ├── gateway.md │ │ │ ├── init.md │ │ │ ├── logs.md │ │ │ ├── metrics.md │ │ │ ├── offer.md │ │ │ ├── project.md │ │ │ ├── ps.md │ │ │ ├── server.md │ │ │ ├── stop.md │ │ │ └── volume.md │ │ ├── dstack.yml.md │ │ ├── dstack.yml │ │ ├── dev-environment.md │ │ ├── fleet.md │ │ ├── gateway.md │ │ ├── service.md │ │ ├── task.md │ │ └── volume.md │ │ ├── environment-variables.md │ │ ├── plugins │ │ └── rest_plugin │ │ │ └── index.md │ │ ├── profiles.yml.md │ │ └── server │ │ └── config.yml.md ├── examples.md ├── examples │ ├── accelerators │ │ ├── amd │ │ │ └── index.md │ │ ├── intel │ │ │ └── index.md │ │ ├── tenstorrent │ │ │ └── index.md │ │ └── tpu │ │ │ └── index.md │ ├── clusters │ │ ├── a3high │ │ │ └── index.md │ │ ├── a3mega │ │ │ └── index.md │ │ ├── nccl-tests │ │ │ └── index.md │ │ └── rccl-tests │ │ │ └── index.md │ ├── distributed-training │ │ ├── axolotl │ │ │ └── index.md │ │ ├── ray-ragen │ │ │ └── index.md │ │ └── trl │ │ │ └── index.md │ ├── inference │ │ ├── nim │ │ │ └── index.md │ │ ├── sglang │ │ │ └── index.md │ │ ├── tgi │ │ │ └── index.md │ │ ├── trtllm │ │ │ └── index.md │ │ └── vllm │ │ │ └── index.md │ ├── llms │ │ ├── deepseek │ │ │ └── index.md │ │ └── llama │ │ │ └── index.md │ ├── misc │ │ └── docker-compose │ │ │ └── index.md │ └── single-node-training │ │ ├── axolotl │ │ └── index.md │ │ └── trl │ │ └── index.md ├── index.md ├── layouts │ └── custom.yml ├── overrides │ ├── .icons │ │ └── custom │ │ │ ├── colored │ │ │ ├── discord.svg │ │ │ ├── github.svg │ │ │ └── twitter.svg │ │ │ └── github.svg │ ├── assets │ │ └── images │ │ │ ├── github-logo.png │ │ │ ├── hero.svg │ │ │ ├── new.svg │ │ │ ├── quotes │ │ │ ├── alvarobartt.jpg │ │ │ ├── chansung.jpg │ │ │ ├── cudopete.png │ │ │ ├── eckart.png │ │ │ ├── movchan.jpg │ │ │ └── spott.jpg │ │ │ ├── slack.png │ │ │ └── twitter.png │ ├── header-2.html │ ├── header.html │ ├── home.html │ ├── landing.html │ ├── main.html │ ├── partials │ │ └── post.html │ ├── path.html │ ├── pricing.html │ ├── privacy.html │ ├── toc-item.html │ └── toc.html ├── partners.md ├── privacy.md └── terms.md ├── examples ├── .dstack.yml ├── __init__.py ├── accelerators │ ├── amd │ │ └── README.md │ ├── intel │ │ └── README.md │ ├── tenstorrent │ │ ├── .dstack.yml │ │ ├── README.md │ │ ├── tt-inference-server.dstack.yml │ │ └── tt-smi.dstack.yml │ └── tpu │ │ └── README.md ├── clusters │ ├── a3high │ │ ├── README.md │ │ ├── fleet.dstack.yml │ │ └── nccl-tests.dstack.yml │ ├── a3mega │ │ ├── README.md │ │ ├── fleet.dstack.yml │ │ └── nccl-tests.dstack.yml │ ├── nccl-tests │ │ ├── .dstack.yml │ │ └── README.md │ └── rccl-tests │ │ ├── .dstack.yml │ │ └── README.md ├── distributed-training │ ├── axolotl │ │ ├── .dstack.yml │ │ └── README.md │ ├── ray-ragen │ │ ├── .dstack.yml │ │ └── README.md │ ├── torchrun │ │ └── .dstack.yml │ └── trl │ │ ├── README.md │ │ ├── deepspeed.dstack.yml │ │ └── fsdp.dstack.yml ├── inference │ ├── nim │ │ ├── .dstack.yml │ │ └── README.md │ ├── sglang │ │ └── README.md │ ├── tgi │ │ ├── .dstack.yml │ │ ├── README.md │ │ ├── amd │ │ │ └── .dstack.yml │ │ └── tpu │ │ │ └── .dstack.yml │ ├── trtllm │ │ ├── README.md │ │ ├── build-image.dstack.yml │ │ ├── build-model.dstack.yml │ │ ├── convert-model.dstack.yml │ │ ├── serve-distill.dstack.yml │ │ └── serve-r1.dstack.yml │ └── vllm │ │ ├── .dstack.yml │ │ ├── README.md │ │ ├── amd │ │ ├── .dstack.yml │ │ └── build-vllm.dstack.yml │ │ └── tpu │ │ └── .dstack.yml ├── llms │ ├── deepseek │ │ ├── README.md │ │ ├── sglang │ │ │ ├── amd │ │ │ │ ├── .dstack.yml │ │ │ │ └── deepseek_v2_lite.dstack.yml │ │ │ └── nvidia │ │ │ │ ├── .dstack.yml │ │ │ │ └── deepseek_v2_lite.dstack.yml │ │ ├── tgi │ │ │ └── intel │ │ │ │ └── .dstack.yml │ │ ├── trl │ │ │ ├── amd │ │ │ │ ├── .dstack.yml │ │ │ │ ├── deepseek_v2.dstack.yml │ │ │ │ ├── grpo.dstack.yml │ │ │ │ └── grpo_train.py │ │ │ ├── intel │ │ │ │ ├── .dstack.yml │ │ │ │ └── deepseek_v2.dstack.yml │ │ │ └── nvidia │ │ │ │ ├── .dstack.yml │ │ │ │ └── deepseek_v2.dstack.yml │ │ └── vllm │ │ │ ├── amd │ │ │ ├── .dstack.yml │ │ │ └── deepseek_v2_lite.dstack.yml │ │ │ ├── intel │ │ │ └── .dstack.yml │ │ │ └── nvidia │ │ │ ├── .dstack.yml │ │ │ └── deepseek_v2_lite.dstack.yml │ ├── llama │ │ ├── README.md │ │ ├── sglang │ │ │ └── nvidia │ │ │ │ └── .dstack.yml │ │ └── vllm │ │ │ ├── amd │ │ │ └── .dstack.yml │ │ │ └── nvidia │ │ │ └── .dstack.yml │ ├── llama31 │ │ └── README.md │ └── llama32 │ │ ├── README.md │ │ └── vllm │ │ └── .dstack.yml ├── misc │ ├── airflow │ │ ├── README.md │ │ └── dags │ │ │ ├── dstack-repo │ │ │ └── task.dstack.yml │ │ │ └── dstack_tasks.py │ ├── docker-compose │ │ ├── .dstack.yml │ │ ├── README.md │ │ ├── compose.yaml │ │ ├── service.dstack.yml │ │ ├── task.dstack.yml │ │ └── volume.dstack.yml │ ├── http.server │ │ ├── .dstack.yml │ │ ├── README.md │ │ └── task.dstack.yml │ ├── jupyterlab │ │ └── .dstack.yml │ ├── ray │ │ ├── README.md │ │ ├── cluster.dstack.yaml │ │ ├── fleet.dstack.yaml │ │ └── tasks │ │ │ ├── pytorch-mnist.py │ │ │ └── quicksort.py │ ├── spark │ │ ├── README.md │ │ ├── cluster.dstack.yaml │ │ ├── fleet.dstack.yaml │ │ ├── task.dstack.yaml │ │ └── tasks │ │ │ └── words.py │ └── streamlit │ │ ├── .dstack.yml │ │ ├── README.md │ │ └── task.dstack.yml ├── plugins │ ├── __init__.py │ ├── example_plugin │ │ ├── .python-version │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── enterprise.Dockerfile │ │ ├── pyproject.toml │ │ └── src │ │ │ └── example_plugin │ │ │ ├── __init__.py │ │ │ └── py.typed │ └── example_plugin_server │ │ ├── .python-version │ │ ├── README.md │ │ ├── __init__.py │ │ ├── pyproject.toml │ │ └── src │ │ └── example_plugin_server │ │ ├── __init__.py │ │ ├── main.py │ │ └── utils.py ├── server-deployment │ └── cloudformation │ │ ├── README.md │ │ └── template.yaml └── single-node-training │ ├── axolotl │ ├── .dstack.yml │ ├── README.md │ ├── amd │ │ ├── .dstack.yml │ │ ├── build-flash-attention.yml │ │ └── build-xformers.dstack.yml │ └── config.yaml │ ├── optimum-tpu │ └── llama31 │ │ ├── .dstack.yml │ │ ├── config.yaml │ │ └── train.py │ ├── qlora │ ├── .dstack.yml │ ├── README.md │ ├── requirements.txt │ └── train.py │ └── trl │ ├── README.md │ ├── amd │ ├── .dstack.yml │ └── train.py │ └── train.dstack.yml ├── frontend ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── jest.config.ts ├── openapi-config.ts ├── package-lock.json ├── package.json ├── public │ ├── index.html │ ├── manifest.json │ └── robots.txt ├── setupEnzyme.ts ├── src │ ├── App │ │ ├── AuthErrorMessage │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ ├── Loading │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ ├── Login │ │ │ ├── EnterpriseLogin │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── EntraID │ │ │ │ ├── LoginByEntraID │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ └── LoginByEntraIDCallback │ │ │ │ │ └── index.tsx │ │ │ ├── LoginByGithub │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── LoginByGithubCallback │ │ │ │ └── index.tsx │ │ │ ├── LoginByOkta │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── LoginByOktaCallback │ │ │ │ └── index.tsx │ │ │ ├── LoginByTokenForm │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ └── TokenLogin │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ ├── Logout │ │ │ └── index.tsx │ │ ├── constants.ts │ │ ├── helpers.ts │ │ ├── index.tsx │ │ ├── slice.ts │ │ └── types.ts │ ├── api.ts │ ├── assets │ │ ├── css │ │ │ ├── index.css │ │ │ ├── mixins.css │ │ │ └── variables.css │ │ ├── icons │ │ │ ├── .gitkeep │ │ │ ├── entraID.svg │ │ │ ├── github.svg │ │ │ ├── okta.svg │ │ │ └── theme.svg │ │ └── images │ │ │ ├── .gitkeep │ │ │ ├── favicon.png │ │ │ └── logo.svg │ ├── components │ │ ├── Button │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ ├── ButtonWithConfirmation │ │ │ ├── index.tsx │ │ │ └── types.ts │ │ ├── Code │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ ├── ConfirmationDialog │ │ │ ├── index.tsx │ │ │ ├── styles.module.scss │ │ │ └── types.ts │ │ ├── DetailsHeader │ │ │ ├── index.tsx │ │ │ └── types.ts │ │ ├── FileUploader │ │ │ ├── FileEntry │ │ │ │ └── index.tsx │ │ │ ├── Token │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ └── index.tsx │ │ ├── Hotspot │ │ │ └── index.tsx │ │ ├── InfoLink │ │ │ ├── index.tsx │ │ │ └── types.ts │ │ ├── ListEmptyMessage │ │ │ ├── index.tsx │ │ │ └── types.ts │ │ ├── Loader │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ ├── NavigateLink │ │ │ └── index.tsx │ │ ├── Notifications │ │ │ ├── index.tsx │ │ │ ├── slice.ts │ │ │ └── types.ts │ │ ├── PermissionGuard │ │ │ ├── index.tsx │ │ │ └── types.ts │ │ ├── Tabs │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ ├── form │ │ │ ├── Checkbox │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── CodeEditor │ │ │ │ ├── constants.ts │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── Input │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── Multiselect │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── RadioButtons │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── S3BucketSelector │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.module.scss │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ ├── Select │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── Textarea │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ └── Tiles │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ └── index.ts │ ├── consts.ts │ ├── consts │ │ └── index.ts │ ├── hooks │ │ ├── index.ts │ │ ├── useAppDispatch.ts │ │ ├── useAppSelector.ts │ │ ├── useBreadcrumbs.ts │ │ ├── useHelpPanel.ts │ │ ├── useInfiniteScroll.ts │ │ ├── useIsMounted.ts │ │ ├── useLocalStorageState.ts │ │ ├── useNotifications.ts │ │ ├── useOnClickOutside.ts │ │ ├── usePermissionGuard.ts │ │ ├── usePrevious.ts │ │ └── useProjectFilter.ts │ ├── index.tsx │ ├── layouts │ │ ├── AppLayout │ │ │ ├── AnnotationContext │ │ │ │ └── index.tsx │ │ │ ├── Tally │ │ │ │ └── index.tsx │ │ │ ├── TutorialPanel │ │ │ │ ├── constants.tsx │ │ │ │ ├── hooks.ts │ │ │ │ └── index.tsx │ │ │ ├── hooks.ts │ │ │ ├── index.module.scss │ │ │ ├── index.tsx │ │ │ └── themeIcons.tsx │ │ └── UnauthorizedLayout │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ ├── libs │ │ ├── fetchBaseQueryHeaders.ts │ │ ├── fleet.ts │ │ ├── form.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── run.ts │ │ ├── serverErrors.ts │ │ ├── types.ts │ │ └── volumes.ts │ ├── locale │ │ ├── en.json │ │ └── index.ts │ ├── pages │ │ ├── Fleets │ │ │ ├── Details │ │ │ │ └── index.tsx │ │ │ ├── List │ │ │ │ ├── hooks.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.module.scss │ │ │ │ └── useDeleteFleet.ts │ │ │ └── index.ts │ │ ├── Instances │ │ │ ├── List │ │ │ │ ├── hooks │ │ │ │ │ ├── useActions.ts │ │ │ │ │ ├── useColumnDefinitions.tsx │ │ │ │ │ ├── useEmptyMessage.tsx │ │ │ │ │ └── useFilters.ts │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ └── index.ts │ │ ├── Models │ │ │ ├── Details │ │ │ │ ├── helpers.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.module.scss │ │ │ │ └── types.ts │ │ │ ├── List │ │ │ │ ├── Preferences │ │ │ │ │ ├── consts.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useModelListPreferences.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── hooks.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.module.scss │ │ │ │ └── types.ts │ │ │ ├── helpers.ts │ │ │ └── index.ts │ │ ├── Project │ │ │ ├── Add │ │ │ │ └── index.tsx │ │ │ ├── Backends │ │ │ │ ├── Add │ │ │ │ │ └── index.tsx │ │ │ │ ├── Edit │ │ │ │ │ └── index.tsx │ │ │ │ ├── Table │ │ │ │ │ ├── constants.tsx │ │ │ │ │ ├── hooks │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── useColumnsDefinitions.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ └── types.ts │ │ │ │ ├── YAMLForm │ │ │ │ │ ├── constants.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useBackendsTable.ts │ │ │ │ └── index.tsx │ │ │ ├── Details │ │ │ │ ├── Settings │ │ │ │ │ ├── constants.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ └── index.tsx │ │ │ ├── Form │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── Gateways │ │ │ │ ├── Add │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ ├── Edit │ │ │ │ │ ├── constants.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ ├── Table │ │ │ │ │ ├── constants.tsx │ │ │ │ │ ├── hooks │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── useColumnsDefinitions.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ └── types.ts │ │ │ │ ├── hooks │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useGatewaysTable.ts │ │ │ │ └── index.tsx │ │ │ ├── List │ │ │ │ ├── hooks │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useColumnsDefinitions.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── Members │ │ │ │ ├── UsersAutosuggest │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.module.scss │ │ │ │ └── types.ts │ │ │ ├── hooks │ │ │ │ ├── useCheckAvailableProjectPermission.ts │ │ │ │ ├── useConfigProjectCliComand.ts │ │ │ │ └── useDeleteProject.ts │ │ │ ├── index.tsx │ │ │ └── utils.ts │ │ ├── Runs │ │ │ ├── Details │ │ │ │ ├── Artifacts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ └── types.ts │ │ │ │ ├── Jobs │ │ │ │ │ ├── Details │ │ │ │ │ │ ├── JobDetails │ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ │ └── styles.module.scss │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── styles.module.scss │ │ │ │ │ ├── List │ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ │ ├── hooks.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── Metrics │ │ │ │ │ │ ├── consts.ts │ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── useMetricsData.ts │ │ │ │ ├── Logs │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ └── types.ts │ │ │ │ ├── RunDetails │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── List │ │ │ │ ├── Preferences │ │ │ │ │ ├── consts.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useRunListPreferences.ts │ │ │ │ ├── helpers.ts │ │ │ │ ├── hooks │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── useColumnsDefinitions.tsx │ │ │ │ │ ├── useDeleteRuns.ts │ │ │ │ │ ├── useDisabledStatesForButtons.ts │ │ │ │ │ ├── useEmptyMessages.tsx │ │ │ │ │ ├── useFilters.ts │ │ │ │ │ └── useStopRuns.ts │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ └── utils.ts │ │ ├── User │ │ │ ├── Add │ │ │ │ └── index.tsx │ │ │ ├── Details │ │ │ │ ├── Billing │ │ │ │ │ ├── PayForm │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── types.ts │ │ │ │ │ ├── components │ │ │ │ │ │ └── AmountField │ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ │ └── styles.module.scss │ │ │ │ │ └── index.tsx │ │ │ │ ├── CreditsHistory │ │ │ │ │ ├── Add │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── types.ts │ │ │ │ │ ├── constants.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── types.ts │ │ │ │ ├── Payments │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── types.ts │ │ │ │ ├── Projects │ │ │ │ │ └── index.tsx │ │ │ │ ├── Settings │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── Edit │ │ │ │ └── index.tsx │ │ │ ├── Form │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── List │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ └── Volumes │ │ │ ├── List │ │ │ ├── hooks.tsx │ │ │ ├── index.tsx │ │ │ └── styles.module.scss │ │ │ └── index.ts │ ├── router.tsx │ ├── routes.ts │ ├── services │ │ ├── artifact.ts │ │ ├── auth.ts │ │ ├── backend.ts │ │ ├── fleet.ts │ │ ├── gateway.ts │ │ ├── instance.ts │ │ ├── mainApi.ts │ │ ├── project.ts │ │ ├── run.ts │ │ ├── server.ts │ │ ├── user.ts │ │ └── volume.ts │ ├── setupTests.ts │ ├── store.ts │ └── types │ │ ├── artifact.d.ts │ │ ├── aws-backend.d.ts │ │ ├── azure-backend.d.ts │ │ ├── backend.d.ts │ │ ├── bread-crums.d.ts │ │ ├── fleet.d.ts │ │ ├── gateway.d.ts │ │ ├── gcp-backend.d.ts │ │ ├── global.d.ts │ │ ├── i18next.d.ts │ │ ├── index.ts │ │ ├── instance.d.ts │ │ ├── labmda-backend.d.ts │ │ ├── log.d.ts │ │ ├── payment.d.ts │ │ ├── project.d.ts │ │ ├── repo.d.ts │ │ ├── run.d.ts │ │ ├── user.d.ts │ │ └── volume.d.ts ├── staticServer.js ├── tests │ ├── __mocks__ │ │ ├── MockStore.tsx │ │ ├── fileMock.ts │ │ ├── shim.ts │ │ └── svgrMock.ts │ └── setupEnzyme.ts ├── tsconfig.json ├── webpack.config.js └── webpack │ ├── base.js │ ├── dev.js │ ├── env.js │ ├── getStyleLoaders.js │ └── prod.js ├── gateway ├── README.md ├── pyproject.toml └── src │ ├── dstack │ ├── __init__.py │ └── gateway │ │ ├── __init__.py │ │ ├── main.py │ │ ├── resources │ │ └── systemd │ │ │ ├── dstack.gateway.service │ │ │ ├── start.sh │ │ │ └── update.sh │ │ ├── systemd │ │ ├── __init__.py │ │ └── __main__.py │ │ └── version.py │ └── tests │ └── __init__.py ├── mkdocs.yml ├── pyproject.toml ├── pytest.ini ├── ruff.toml ├── runner ├── .golangci.yml ├── .justfile ├── README.md ├── cmd │ ├── runner │ │ ├── cmd.go │ │ └── main.go │ └── shim │ │ └── main.go ├── consts │ └── consts.go ├── docs │ └── shim.openapi.yaml ├── go.mod ├── go.sum └── internal │ ├── api │ └── common.go │ ├── common │ ├── gpu.go │ ├── interpolator.go │ ├── interpolator_test.go │ └── string.go │ ├── connections │ ├── connections.go │ └── connections_test.go │ ├── executor │ ├── base.go │ ├── env.go │ ├── env_test.go │ ├── exec.go │ ├── exec_test.go │ ├── executor.go │ ├── executor_test.go │ ├── lock.go │ ├── logs.go │ ├── query.go │ ├── repo.go │ ├── states.go │ ├── timestamp.go │ └── timestamp_test.go │ ├── gerrors │ └── stacktrace.go │ ├── log │ └── log.go │ ├── metrics │ ├── metrics.go │ └── metrics_test.go │ ├── repo │ ├── diff.go │ ├── diff_test.go │ └── manager.go │ ├── runner │ └── api │ │ ├── http.go │ │ ├── server.go │ │ └── ws.go │ ├── schemas │ └── schemas.go │ ├── shim │ ├── api │ │ ├── api_test.go │ │ ├── handlers.go │ │ ├── handlers_test.go │ │ ├── schemas.go │ │ └── server.go │ ├── authorized_keys.go │ ├── authorized_keys_test.go │ ├── backends │ │ ├── aws.go │ │ ├── base.go │ │ └── gcp.go │ ├── dcgm │ │ ├── exporter.go │ │ ├── metrics.go │ │ └── metrics_test.go │ ├── docker.go │ ├── docker_test.go │ ├── errs.go │ ├── host │ │ ├── gpu.go │ │ └── host.go │ ├── host_info.go │ ├── models.go │ ├── resources.go │ ├── resources_test.go │ ├── runner.go │ ├── task.go │ └── task_test.go │ └── types │ └── types.go ├── scripts ├── add_backend.py ├── build_frontend.sh ├── docs │ ├── gen_cli_reference.py │ ├── gen_examples.py │ ├── gen_openapi_reference.py │ ├── gen_rest_plugin_spec_reference.py │ └── gen_schema_reference.py ├── oci_image_tools.py ├── packer │ ├── README.md │ ├── aws-image-cuda.json │ ├── aws-image.json │ ├── aws-vars-prod.json │ ├── azure-image-cuda.json │ ├── azure-image-grid.json │ ├── azure-image.json │ ├── build-cuda-image.pkr.hcl │ ├── build-image.pkr.hcl │ ├── config.pkr.hcl │ ├── gcp-a3mega-image.json │ ├── gcp-image-cuda.json │ ├── gcp-image.json │ ├── locals.pkr.hcl │ ├── oci-image-cuda.json │ ├── oci-image.json │ ├── provisioners │ │ ├── cuda.sh │ │ ├── install-docker.sh │ │ ├── install-nvidia-container-toolkit.sh │ │ ├── install-nvidia-grid-driver-for-azure.sh │ │ ├── kernel │ │ │ ├── apt-daily.sh │ │ │ ├── apt-packages.sh │ │ │ ├── apt-upgrade.sh │ │ │ └── kernel-tuning.sh │ │ ├── pull-docker-images.sh │ │ ├── run-docker │ │ └── wait-for-dpkg-lock.sh │ ├── variables.pkr.hcl │ └── versions.json ├── publish_azure_image.sh └── sqlite_to_psql.load └── src ├── dstack ├── __init__.py ├── _internal │ ├── __init__.py │ ├── cli │ │ ├── __init__.py │ │ ├── commands │ │ │ ├── __init__.py │ │ │ ├── apply.py │ │ │ ├── attach.py │ │ │ ├── completion.py │ │ │ ├── config.py │ │ │ ├── delete.py │ │ │ ├── fleet.py │ │ │ ├── gateway.py │ │ │ ├── init.py │ │ │ ├── logs.py │ │ │ ├── metrics.py │ │ │ ├── offer.py │ │ │ ├── project.py │ │ │ ├── ps.py │ │ │ ├── server.py │ │ │ ├── stats.py │ │ │ ├── stop.py │ │ │ └── volume.py │ │ ├── main.py │ │ ├── services │ │ │ ├── __init__.py │ │ │ ├── args.py │ │ │ ├── completion.py │ │ │ ├── configurators │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ ├── fleet.py │ │ │ │ ├── gateway.py │ │ │ │ ├── run.py │ │ │ │ └── volume.py │ │ │ ├── profile.py │ │ │ └── repos.py │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ ├── fleet.py │ │ │ ├── gateway.py │ │ │ ├── rich.py │ │ │ ├── run.py │ │ │ ├── updates.py │ │ │ └── volume.py │ ├── compat.py │ ├── core │ │ ├── __init__.py │ │ ├── backends │ │ │ ├── __init__.py │ │ │ ├── aws │ │ │ │ ├── __init__.py │ │ │ │ ├── auth.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── models.py │ │ │ │ └── resources.py │ │ │ ├── azure │ │ │ │ ├── __init__.py │ │ │ │ ├── auth.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── models.py │ │ │ │ ├── resources.py │ │ │ │ └── utils.py │ │ │ ├── base │ │ │ │ ├── __init__.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── models.py │ │ │ │ └── offers.py │ │ │ ├── configurators.py │ │ │ ├── cudo │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ │ ├── datacrunch │ │ │ │ ├── __init__.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ │ ├── dstack │ │ │ │ ├── __init__.py │ │ │ │ └── models.py │ │ │ ├── gcp │ │ │ │ ├── __init__.py │ │ │ │ ├── auth.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── features │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── tcpx.py │ │ │ │ ├── models.py │ │ │ │ └── resources.py │ │ │ ├── kubernetes │ │ │ │ ├── __init__.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── models.py │ │ │ │ └── utils.py │ │ │ ├── lambdalabs │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ │ ├── local │ │ │ │ ├── __init__.py │ │ │ │ ├── backend.py │ │ │ │ └── compute.py │ │ │ ├── models.py │ │ │ ├── nebius │ │ │ │ ├── __init__.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── fabrics.py │ │ │ │ ├── models.py │ │ │ │ └── resources.py │ │ │ ├── oci │ │ │ │ ├── __init__.py │ │ │ │ ├── auth.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── models.py │ │ │ │ ├── region.py │ │ │ │ └── resources.py │ │ │ ├── remote │ │ │ │ ├── __init__.py │ │ │ │ └── provisioning.py │ │ │ ├── runpod │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ │ ├── template │ │ │ │ ├── __init__.py │ │ │ │ ├── backend.py.jinja │ │ │ │ ├── compute.py.jinja │ │ │ │ ├── configurator.py.jinja │ │ │ │ └── models.py.jinja │ │ │ ├── tensordock │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ │ ├── vastai │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ │ └── vultr │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── backend.py │ │ │ │ ├── compute.py │ │ │ │ ├── configurator.py │ │ │ │ └── models.py │ │ ├── consts.py │ │ ├── errors.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── backends │ │ │ │ ├── __init__.py │ │ │ │ └── base.py │ │ │ ├── common.py │ │ │ ├── config.py │ │ │ ├── configurations.py │ │ │ ├── envs.py │ │ │ ├── fleets.py │ │ │ ├── gateways.py │ │ │ ├── instances.py │ │ │ ├── logs.py │ │ │ ├── metrics.py │ │ │ ├── placement.py │ │ │ ├── profiles.py │ │ │ ├── projects.py │ │ │ ├── repos │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ ├── local.py │ │ │ │ ├── remote.py │ │ │ │ └── virtual.py │ │ │ ├── resources.py │ │ │ ├── runs.py │ │ │ ├── secrets.py │ │ │ ├── server.py │ │ │ ├── services.py │ │ │ ├── unix.py │ │ │ ├── users.py │ │ │ └── volumes.py │ │ └── services │ │ │ ├── __init__.py │ │ │ ├── api_client.py │ │ │ ├── configs │ │ │ └── __init__.py │ │ │ ├── diff.py │ │ │ ├── logs.py │ │ │ ├── profiles.py │ │ │ ├── repos.py │ │ │ └── ssh │ │ │ ├── __init__.py │ │ │ ├── attach.py │ │ │ ├── client.py │ │ │ ├── ports.py │ │ │ └── tunnel.py │ ├── proxy │ │ ├── __init__.py │ │ ├── gateway │ │ │ ├── __init__.py │ │ │ ├── app.py │ │ │ ├── auth.py │ │ │ ├── const.py │ │ │ ├── deps.py │ │ │ ├── main.py │ │ │ ├── models.py │ │ │ ├── repo │ │ │ │ ├── __init__.py │ │ │ │ ├── repo.py │ │ │ │ └── state_v1.py │ │ │ ├── resources │ │ │ │ └── nginx │ │ │ │ │ ├── 00-log-format.conf │ │ │ │ │ ├── entrypoint.jinja2 │ │ │ │ │ └── service.jinja2 │ │ │ ├── routers │ │ │ │ ├── __init__.py │ │ │ │ ├── auth.py │ │ │ │ ├── config.py │ │ │ │ ├── registry.py │ │ │ │ └── stats.py │ │ │ ├── schemas │ │ │ │ ├── __init__.py │ │ │ │ ├── common.py │ │ │ │ ├── config.py │ │ │ │ ├── registry.py │ │ │ │ └── stats.py │ │ │ ├── services │ │ │ │ ├── __init__.py │ │ │ │ ├── nginx.py │ │ │ │ ├── registry.py │ │ │ │ ├── server_client.py │ │ │ │ └── stats.py │ │ │ └── testing │ │ │ │ ├── __init__.py │ │ │ │ └── common.py │ │ └── lib │ │ │ ├── __init__.py │ │ │ ├── auth.py │ │ │ ├── deps.py │ │ │ ├── errors.py │ │ │ ├── models.py │ │ │ ├── repo.py │ │ │ ├── routers │ │ │ ├── __init__.py │ │ │ └── model_proxy.py │ │ │ ├── schemas │ │ │ ├── __init__.py │ │ │ └── model_proxy.py │ │ │ ├── services │ │ │ ├── __init__.py │ │ │ ├── model_proxy │ │ │ │ ├── __init__.py │ │ │ │ ├── clients │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base.py │ │ │ │ │ ├── openai.py │ │ │ │ │ └── tgi.py │ │ │ │ └── model_proxy.py │ │ │ └── service_connection.py │ │ │ └── testing │ │ │ ├── __init__.py │ │ │ ├── auth.py │ │ │ └── common.py │ ├── server │ │ ├── __init__.py │ │ ├── alembic.ini │ │ ├── app.py │ │ ├── background │ │ │ ├── __init__.py │ │ │ └── tasks │ │ │ │ ├── __init__.py │ │ │ │ ├── common.py │ │ │ │ ├── process_fleets.py │ │ │ │ ├── process_gateways.py │ │ │ │ ├── process_instances.py │ │ │ │ ├── process_metrics.py │ │ │ │ ├── process_placement_groups.py │ │ │ │ ├── process_prometheus_metrics.py │ │ │ │ ├── process_running_jobs.py │ │ │ │ ├── process_runs.py │ │ │ │ ├── process_submitted_jobs.py │ │ │ │ ├── process_terminating_jobs.py │ │ │ │ └── process_volumes.py │ │ ├── db.py │ │ ├── deps.py │ │ ├── main.py │ │ ├── migrations │ │ │ ├── __init__.py │ │ │ ├── env.py │ │ │ ├── script.py.mako │ │ │ └── versions │ │ │ │ ├── 065588ec72b8_add_vultr_to_backendtype_enum.py │ │ │ │ ├── 0e33559e16ed_update_instancestatus.py │ │ │ │ ├── 112753bc17dd_remove_nullable_fields.py │ │ │ │ ├── 1338b788b612_reverse_job_instance_relationship.py │ │ │ │ ├── 14f2cb002fc2_add_jobmodel_removed_flag.py │ │ │ │ ├── 1a48dfe44a40_rework_termination_handling.py │ │ │ │ ├── 1e3fb39ef74b_add_remote_connection_details.py │ │ │ │ ├── 1e76fb0dde87_add_jobmodel_inactivity_secs.py │ │ │ │ ├── 20166748b60c_add_jobmodel_disconnected_at.py │ │ │ │ ├── 23e01c56279a_make_blob_nullable.py │ │ │ │ ├── 252d3743b641_.py │ │ │ │ ├── 27d3e55759fa_add_pools.py │ │ │ │ ├── 29826f417010_remove_instancemodel_retry_policy.py │ │ │ │ ├── 29c08c6a8cb3_.py │ │ │ │ ├── 3cf77fb8bcf1_store_repo_clone_url.py │ │ │ │ ├── 3dbdce90d0e0_fix_code_uq_constraint.py │ │ │ │ ├── 48ad3ecbaea2_do_not_delete_projects_and_runs.py │ │ │ │ ├── 4ae1a5b0e7f1_add_run_list_index.py │ │ │ │ ├── 4b4319398164_introduce_runs_processing.py │ │ │ │ ├── 51d45659d574_add_instancemodel_blocks_fields.py │ │ │ │ ├── 54a77e19c64c_add_manager_project_role.py │ │ │ │ ├── 555138b1f77f_change_instancemodel_for_asynchronous_.py │ │ │ │ ├── 58aa5162dcc3_add_gatewaymodel_configuration.py │ │ │ │ ├── 5ad8debc8fe6_fixes_for_psql.py │ │ │ │ ├── 5ec538b70e71_replace_instansestatus.py │ │ │ │ ├── 60e444118b6d_add_jobprometheusmetrics.py │ │ │ │ ├── 63c3f19cb184_add_jobterminationreason_inactivity_.py │ │ │ │ ├── 686fb8341ea5_add_user_emails.py │ │ │ │ ├── 6c1a9d6530ee_add_jobmodel_exit_status.py │ │ │ │ ├── 710e5b3fac8f_add_encryption.py │ │ │ │ ├── 7b24b1c8eba7_add_instancemodel_last_processed_at.py │ │ │ │ ├── 7ba3b59d7ca6_add_runmodel_resubmission_attempt.py │ │ │ │ ├── 7bc2586e8b9e_make_instancemodel_pool_id_optional.py │ │ │ │ ├── 803c7e9ed85d_add_jobmodel_job_runtime_data.py │ │ │ │ ├── 82b32a135ea2_.py │ │ │ │ ├── 866ec1d67184_replace_retrypolicy_limit_with_.py │ │ │ │ ├── 91a12fff6c76_add_repocredsmodel.py │ │ │ │ ├── 91ac5e543037_extend_repos_creds_column.py │ │ │ │ ├── 98cd9c8b5927_add_volumemodel.py │ │ │ │ ├── 98d1b92988bc_add_jobterminationreason_terminated_due_.py │ │ │ │ ├── 99b4c8c954ea_add_termination_reason_message.py │ │ │ │ ├── 9eea6af28e10_added_fail_reason_for_instancemodel.py │ │ │ │ ├── __init__.py │ │ │ │ ├── a060e2440936_.py │ │ │ │ ├── a751ef183f27_move_attachment_data_to_volumes_.py │ │ │ │ ├── a7b46c073fa1_add_placementgroupmodel.py │ │ │ │ ├── afbc600ff2b2_add_created_at_to_usermodel_and_.py │ │ │ │ ├── b4d6ad60db08_add_instancemodel_unreachable.py │ │ │ │ ├── b88d55c2a07d_replace_instancestatus_ready.py │ │ │ │ ├── bc8ca4a505c6_store_backendtype_as_string.py │ │ │ │ ├── bca2fdf130bf_add_runmodel_priority.py │ │ │ │ ├── bfba43f6def2_.py │ │ │ │ ├── c00090eaef21_support_fleets.py │ │ │ │ ├── c154eece89da_add_fields_for_async_gateway_creation.py │ │ │ │ ├── c20626d03cfb_add_jobmetricspoint.py │ │ │ │ ├── c48df7985d57_add_instance_termination_retries.py │ │ │ │ ├── c83d45f9a971_replace_string_with_text.py │ │ │ │ ├── d0bb68e48b9f_add_project_owners_and_quotas.py │ │ │ │ ├── d3e8af4786fa_gateway_compute_flag_deleted.py │ │ │ │ ├── d6b11105f659_add_usermodel_active.py │ │ │ │ ├── da574e93fee0_add_jobmodel_volumes_detached_at.py │ │ │ │ ├── dfffd6a1165c_add_fields_for_gateways_behind_alb.py │ │ │ │ ├── e3b7db07727f_add_gatewaycomputemodel_app_updated_at.py │ │ │ │ ├── e6391ca6a264_separate_gateways_from_compute.py │ │ │ │ ├── ea60480f82bb_add_membermodel_member_num.py │ │ │ │ ├── ed0ca30e13bb_migrate_instancestatus_provisioning.py │ │ │ │ ├── fe72c4de8376_add_gateways.py │ │ │ │ └── ffa99edd1988_add_jobterminationreason_max_duration_.py │ │ ├── models.py │ │ ├── routers │ │ │ ├── __init__.py │ │ │ ├── backends.py │ │ │ ├── fleets.py │ │ │ ├── gateways.py │ │ │ ├── instances.py │ │ │ ├── logs.py │ │ │ ├── metrics.py │ │ │ ├── projects.py │ │ │ ├── prometheus.py │ │ │ ├── repos.py │ │ │ ├── runs.py │ │ │ ├── secrets.py │ │ │ ├── server.py │ │ │ ├── users.py │ │ │ └── volumes.py │ │ ├── schemas │ │ │ ├── __init__.py │ │ │ ├── backends.py │ │ │ ├── common.py │ │ │ ├── fleets.py │ │ │ ├── gateways.py │ │ │ ├── instances.py │ │ │ ├── logs.py │ │ │ ├── projects.py │ │ │ ├── repos.py │ │ │ ├── runner.py │ │ │ ├── runs.py │ │ │ ├── secrets.py │ │ │ ├── users.py │ │ │ └── volumes.py │ │ ├── security │ │ │ ├── __init__.py │ │ │ └── permissions.py │ │ ├── services │ │ │ ├── __init__.py │ │ │ ├── backends │ │ │ │ ├── __init__.py │ │ │ │ └── handlers.py │ │ │ ├── config.py │ │ │ ├── docker.py │ │ │ ├── encryption │ │ │ │ ├── __init__.py │ │ │ │ └── keys │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── aes.py │ │ │ │ │ ├── base.py │ │ │ │ │ └── identity.py │ │ │ ├── fleets.py │ │ │ ├── gateways │ │ │ │ ├── __init__.py │ │ │ │ ├── client.py │ │ │ │ ├── connection.py │ │ │ │ └── pool.py │ │ │ ├── instances.py │ │ │ ├── jobs │ │ │ │ ├── __init__.py │ │ │ │ └── configurators │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base.py │ │ │ │ │ ├── dev.py │ │ │ │ │ ├── extensions │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base.py │ │ │ │ │ ├── cursor.py │ │ │ │ │ └── vscode.py │ │ │ │ │ ├── service.py │ │ │ │ │ └── task.py │ │ │ ├── locking.py │ │ │ ├── logging.py │ │ │ ├── logs │ │ │ │ ├── __init__.py │ │ │ │ ├── aws.py │ │ │ │ ├── base.py │ │ │ │ ├── filelog.py │ │ │ │ └── gcp.py │ │ │ ├── metrics.py │ │ │ ├── offers.py │ │ │ ├── permissions.py │ │ │ ├── placement.py │ │ │ ├── plugins.py │ │ │ ├── projects.py │ │ │ ├── prometheus.py │ │ │ ├── proxy │ │ │ │ ├── __init__.py │ │ │ │ ├── auth.py │ │ │ │ ├── deps.py │ │ │ │ ├── repo.py │ │ │ │ ├── routers │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── service_proxy.py │ │ │ │ └── services │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── service_proxy.py │ │ │ ├── repos.py │ │ │ ├── resources.py │ │ │ ├── runner │ │ │ │ ├── __init__.py │ │ │ │ ├── client.py │ │ │ │ └── ssh.py │ │ │ ├── runs.py │ │ │ ├── services │ │ │ │ ├── __init__.py │ │ │ │ ├── autoscalers.py │ │ │ │ └── options.py │ │ │ ├── storage │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ ├── gcs.py │ │ │ │ └── s3.py │ │ │ ├── users.py │ │ │ └── volumes.py │ │ ├── settings.py │ │ ├── testing │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ └── conf.py │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ ├── logging.py │ │ │ └── routers.py │ ├── settings.py │ └── utils │ │ ├── __init__.py │ │ ├── common.py │ │ ├── crypto.py │ │ ├── dxf.py │ │ ├── env.py │ │ ├── event_loop.py │ │ ├── gpu.py │ │ ├── hash.py │ │ ├── interpolator.py │ │ ├── json_schema.py │ │ ├── logging.py │ │ ├── network.py │ │ ├── path.py │ │ ├── random_names.py │ │ ├── ssh.py │ │ └── tags.py ├── api │ ├── __init__.py │ ├── _public │ │ ├── __init__.py │ │ ├── backends.py │ │ ├── repos.py │ │ └── runs.py │ ├── huggingface │ │ └── __init__.py │ ├── server │ │ ├── __init__.py │ │ ├── _backends.py │ │ ├── _fleets.py │ │ ├── _gateways.py │ │ ├── _group.py │ │ ├── _logs.py │ │ ├── _metrics.py │ │ ├── _projects.py │ │ ├── _repos.py │ │ ├── _runs.py │ │ ├── _secrets.py │ │ ├── _users.py │ │ ├── _volumes.py │ │ └── utils.py │ └── utils.py ├── core │ └── __init__.py ├── plugins │ ├── __init__.py │ ├── _base.py │ ├── _models.py │ ├── _utils.py │ └── builtin │ │ ├── __init__.py │ │ └── rest_plugin │ │ ├── __init__.py │ │ ├── _models.py │ │ └── _plugin.py └── version.py └── tests ├── __init__.py ├── _internal ├── __init__.py ├── cli │ ├── __init__.py │ ├── commands │ │ ├── __init__.py │ │ ├── test_config.py │ │ ├── test_dstack.py │ │ └── test_metrics.py │ ├── common.py │ ├── services │ │ ├── __init__.py │ │ └── configurators │ │ │ ├── __init__.py │ │ │ ├── test_fleet.py │ │ │ ├── test_profile.py │ │ │ └── test_run.py │ └── utils │ │ └── test_updates.py ├── core │ ├── __init__.py │ ├── backends │ │ ├── __init__.py │ │ ├── aws │ │ │ ├── __init__.py │ │ │ ├── test_configurator.py │ │ │ └── test_resources.py │ │ ├── azure │ │ │ ├── __init__.py │ │ │ ├── test_compute.py │ │ │ ├── test_configurator.py │ │ │ └── test_resources.py │ │ ├── base │ │ │ ├── __init__.py │ │ │ └── test_compute.py │ │ ├── cudo │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ │ ├── datacrunch │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ │ ├── gcp │ │ │ ├── __init__.py │ │ │ ├── test_configurator.py │ │ │ └── test_resources.py │ │ ├── kubernetes │ │ │ ├── __init__.py │ │ │ ├── test_compute.py │ │ │ └── test_configurator.py │ │ ├── lambdalabs │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ │ ├── oci │ │ │ ├── __init__.py │ │ │ ├── test_configurator.py │ │ │ └── test_resources.py │ │ ├── runpod │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ │ ├── tensordock │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ │ ├── vastai │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ │ └── vultr │ │ │ ├── __init__.py │ │ │ └── test_configurator.py │ ├── models │ │ ├── __init__.py │ │ ├── repos │ │ │ ├── __init__.py │ │ │ ├── test_local.py │ │ │ └── test_remote.py │ │ ├── test_configurations.py │ │ ├── test_instances.py │ │ ├── test_resources.py │ │ ├── test_runs.py │ │ ├── test_unix.py │ │ └── test_volumes.py │ └── services │ │ ├── __init__.py │ │ ├── ssh │ │ ├── __init__.py │ │ ├── test_client.py │ │ └── test_tunnel.py │ │ └── test_logs.py ├── proxy │ ├── __init__.py │ ├── gateway │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── repo │ │ │ ├── __init__.py │ │ │ ├── test_repo.py │ │ │ └── test_state_v1.py │ │ ├── routers │ │ │ ├── __init__.py │ │ │ ├── test_registry.py │ │ │ └── test_stats.py │ │ ├── services │ │ │ ├── __init__.py │ │ │ └── test_stats.py │ │ └── test_app.py │ └── lib │ │ ├── __init__.py │ │ └── routers │ │ ├── __init__.py │ │ └── test_model_proxy.py ├── server │ ├── __init__.py │ ├── background │ │ ├── __init__.py │ │ └── tasks │ │ │ ├── __init__.py │ │ │ ├── test_process_fleets.py │ │ │ ├── test_process_gateways.py │ │ │ ├── test_process_instances.py │ │ │ ├── test_process_metrics.py │ │ │ ├── test_process_placement_groups.py │ │ │ ├── test_process_prometheus_metrics.py │ │ │ ├── test_process_running_jobs.py │ │ │ ├── test_process_runs.py │ │ │ ├── test_process_submitted_jobs.py │ │ │ ├── test_process_submitted_volumes.py │ │ │ └── test_process_terminating_jobs.py │ ├── conftest.py │ ├── routers │ │ ├── __init__.py │ │ ├── test_backends.py │ │ ├── test_fleets.py │ │ ├── test_gateways.py │ │ ├── test_instances.py │ │ ├── test_logs.py │ │ ├── test_metrics.py │ │ ├── test_projects.py │ │ ├── test_prometheus.py │ │ ├── test_repos.py │ │ ├── test_runs.py │ │ ├── test_server.py │ │ ├── test_users.py │ │ └── test_volumes.py │ ├── services │ │ ├── __init__.py │ │ ├── backends │ │ │ └── __init__.py │ │ ├── encryption │ │ │ ├── __init__.py │ │ │ ├── keys │ │ │ │ ├── __init__.py │ │ │ │ └── test_aes.py │ │ │ └── test_encryption.py │ │ ├── jobs │ │ │ ├── __init__.py │ │ │ └── configurators │ │ │ │ ├── __init__.py │ │ │ │ ├── test_base.py │ │ │ │ └── test_task.py │ │ ├── proxy │ │ │ ├── __init__.py │ │ │ └── routers │ │ │ │ ├── __init__.py │ │ │ │ └── test_service_proxy.py │ │ ├── runner │ │ │ ├── __init__.py │ │ │ └── test_client.py │ │ ├── services │ │ │ ├── __init__.py │ │ │ └── test_autoscalers.py │ │ ├── test_config.py │ │ ├── test_docker.py │ │ ├── test_fleets.py │ │ ├── test_instances.py │ │ ├── test_logs.py │ │ ├── test_metrics.py │ │ ├── test_offers.py │ │ ├── test_plugins.py │ │ ├── test_repos.py │ │ ├── test_runs.py │ │ ├── test_users.py │ │ └── test_volumes.py │ ├── test_app.py │ ├── test_migrations.py │ └── utils │ │ ├── __init__.py │ │ ├── test_common.py │ │ └── test_routers.py └── utils │ ├── __init__.py │ ├── test_common.py │ ├── test_env.py │ ├── test_event_loop.py │ ├── test_gpu.py │ ├── test_interpolator.py │ ├── test_network.py │ ├── test_path.py │ ├── test_ssh.py │ └── test_tags.py ├── api ├── __init__.py └── test_utils.py ├── conftest.py └── plugins ├── __init__.py └── test_rest_plugin.py /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Need help or have a question? 4 | url: https://discord.gg/u8SmfwPpMd 5 | about: Join our Discord server 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__/ 2 | *.py[co] 3 | *.egg-info 4 | 5 | dist/ 6 | venv/ 7 | /site/ 8 | /.cache/ 9 | .pytest_cache/ 10 | .coverage 11 | 12 | .idea/ 13 | 14 | /runner/cmd/shim/shim 15 | /runner/cmd/runner/runner 16 | 17 | /src/dstack/_internal/server/statics 18 | 19 | build/ 20 | .DS_Store 21 | .fleet 22 | .env 23 | .envrc 24 | .vscode 25 | .aider* 26 | uv.lock 27 | .local/ 28 | -------------------------------------------------------------------------------- /.justfile: -------------------------------------------------------------------------------- 1 | # Root justfile 2 | # 3 | # This justfile serves as the main entry point to recipes from different components. 4 | # 5 | # Run `just` to see all available commands. 6 | # 7 | # Components: 8 | # * runner/justfile – Building and uploading dstack runner and shim 9 | 10 | default: 11 | @just --list 12 | 13 | set allow-duplicate-recipes 14 | 15 | import "runner/.justfile" 16 | 17 | # TODO: Add frontend/justfile for managing frontend development tasks 18 | -------------------------------------------------------------------------------- /docker/amd-smi/README.md: -------------------------------------------------------------------------------- 1 | # dstack AMD SMI 2 | 3 | An Ubuntu-based image with [AMD SMI](https://rocm.docs.amd.com/projects/amdsmi/en/latest/) preinstalled. Suitable for AMD GPU detection. 4 | 5 | ## Usage 6 | 7 | ```shell 8 | docker run --rm --device /dev/kfd --device /dev/dri dstackai/amd-smi static 9 | ``` 10 | -------------------------------------------------------------------------------- /docker/base/README.md: -------------------------------------------------------------------------------- 1 | Image for `dstack` runner instances. 2 | -------------------------------------------------------------------------------- /docker/efa/README.md: -------------------------------------------------------------------------------- 1 | # dstack AWS EFA 2 | 3 | This image has the following installed: 4 | 5 | * CUDA 12.1 6 | * AWS EFA Installer 1.38.1 (Libfabric + Open MPI 4 + Open MPI 5) 7 | * NCCL 2.26.2-1 8 | * AWS OFI NCCL 1.14.0 9 | * NCCL Tests 10 | -------------------------------------------------------------------------------- /docker/server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ -n "${GOOGLE_APPLICATION_CREDENTIALS_JSON}" ]; then 5 | GOOGLE_APPLICATION_CREDENTIALS_DIR="${HOME}/.config/gcloud/" 6 | mkdir -p "${GOOGLE_APPLICATION_CREDENTIALS_DIR}" 7 | echo "${GOOGLE_APPLICATION_CREDENTIALS_JSON}" > "${GOOGLE_APPLICATION_CREDENTIALS_DIR}/application_default_credentials.json" 8 | fi 9 | 10 | if [[ -z "${LITESTREAM_REPLICA_URL}" ]]; then 11 | dstack server --host 0.0.0.0 12 | else 13 | litestream restore -if-replica-exists -o ${HOME}/.dstack/server/data/sqlite.db ${LITESTREAM_REPLICA_URL} 14 | litestream replicate -exec "dstack server --host 0.0.0.0" ${HOME}/.dstack/server/data/sqlite.db ${LITESTREAM_REPLICA_URL} 15 | fi 16 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | dstack.ai 2 | -------------------------------------------------------------------------------- /docs/assets/images/cats-in-hats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/cats-in-hats.png -------------------------------------------------------------------------------- /docs/assets/images/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/assets/images/dstack-cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-cli.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-code-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-code-dark.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-dev-environments-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-dev-environments-code.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-dolly-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-dolly-code.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-dolly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-dolly.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-fav-32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-fav-32.ico -------------------------------------------------------------------------------- /docs/assets/images/dstack-fine-tuning-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-fine-tuning-diagram.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-finetuning-hf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-finetuning-hf.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-finetuning-wandb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-finetuning-wandb.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-google-colab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-google-colab.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-gradio-falcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-gradio-falcon.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-create-aws-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-create-aws-project.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-create-azure-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-create-azure-project.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-create-gcp-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-create-gcp-project.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-create-lambda-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-create-lambda-project.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-create-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-create-project.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-edit-gateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-edit-gateway.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-view-project-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-view-project-empty.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-hub-view-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-hub-view-project.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-huggingface-space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-huggingface-space.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-jupyterlab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-jupyterlab.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-lambda-api-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-lambda-api-key.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-llmchat-discord-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-llmchat-discord-chat.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-llmchat-gallery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-llmchat-gallery.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-logo-notext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-logo-notext.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-mixtral-chat-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-mixtral-chat-ui.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-playground-github-actions-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-playground-github-actions-ui.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-run-artifacts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-run-artifacts.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-runpod-dev-environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-runpod-dev-environment.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-server-output-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-server-output-2.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-stable-diffusion-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-stable-diffusion-code.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-stable-diffusion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-stable-diffusion.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-tensorboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-tensorboard.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-train-artifacts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-train-artifacts.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-v010-vscode-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-v010-vscode-desktop.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-vscode-jupyter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-vscode-jupyter.png -------------------------------------------------------------------------------- /docs/assets/images/dstack-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/dstack-vscode.png -------------------------------------------------------------------------------- /docs/assets/images/hero_code_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/assets/images/hero_code_background.png -------------------------------------------------------------------------------- /docs/assets/images/jb-toolbox-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/assets/images/kapa.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/assets/images/lambda-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/assets/images/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/assets/images/oci-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/assets/images/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/assets/images/ssh-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/assets/images/tensorwave-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /docs/assets/images/vastai-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /docs/blog/index.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Blog 8 | -------------------------------------------------------------------------------- /docs/blog/posts/images/dstack-diagram-stack-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/blog/posts/images/dstack-diagram-stack-3.png -------------------------------------------------------------------------------- /docs/blog/posts/images/dstack-research-banner-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/blog/posts/images/dstack-research-banner-2.png -------------------------------------------------------------------------------- /docs/blog/posts/images/dstack-sky-banner-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/blog/posts/images/dstack-sky-banner-4.png -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/apply.md: -------------------------------------------------------------------------------- 1 | # dstack apply 2 | 3 | This command applies a given configuration. If a resource does not exist, `dstack apply` creates the resource. 4 | If a resource exists, `dstack apply` updates the resource in-place or re-creates the resource if the update is not possible. 5 | 6 | When applying run configurations, `dstack apply` requires that you run `dstack init` first, 7 | or specify a repo to work with via `-P` (or `--repo`), or specify `--no-repo` if you don't need any repo for the run. 8 | 9 | ## Usage 10 | 11 |
12 | 13 | ```shell 14 | $ dstack apply --help 15 | #GENERATE# 16 | ``` 17 | 18 |
19 | 20 | [//]: # (TODO: Provide examples) 21 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/attach.md: -------------------------------------------------------------------------------- 1 | # dstack attach 2 | 3 | This command attaches to a given run. It establishes the SSH tunnel, forwards ports, and shows real-time run logs. 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack attach --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/delete.md: -------------------------------------------------------------------------------- 1 | # dstack delete 2 | 3 | This command deletes the resources defined by a given configuration. 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack delete --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/fleet.md: -------------------------------------------------------------------------------- 1 | # dstack fleet 2 | 3 | Fleets enable efficient provisioning and management of clusters and instances. 4 | 5 | ## dstack fleet list 6 | 7 | The `dstack fleet list` command displays fleets and instances. 8 | 9 |
10 | 11 | ```shell 12 | $ dstack fleet list --help 13 | #GENERATE# 14 | ``` 15 | 16 |
17 | 18 | ## dstack fleet delete 19 | 20 | The `dstack fleet delete` deletes fleets and instances. 21 | Cloud instances are terminated upon deletion. 22 | 23 |
24 | 25 | ```shell 26 | $ dstack fleet delete --help 27 | #GENERATE# 28 | ``` 29 | 30 |
31 | 32 | [//]: # (TODO: Provide examples) 33 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/logs.md: -------------------------------------------------------------------------------- 1 | # dstack logs 2 | 3 | This command shows the output of a given run. 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack logs --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/metrics.md: -------------------------------------------------------------------------------- 1 | # dstack metrics 2 | 3 | This command shows run hardware metrics such as CPU, memory, and GPU utilization. 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack metrics --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/ps.md: -------------------------------------------------------------------------------- 1 | # dstack ps 2 | 3 | This command shows the status of runs. 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack ps --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples, incl. `-a`) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/server.md: -------------------------------------------------------------------------------- 1 | # dstack server 2 | 3 | This command starts the `dstack` server. 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack server --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples; mention Docker; reference the deployment guide) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/stop.md: -------------------------------------------------------------------------------- 1 | # dstack stop 2 | 3 | This command stops run(s). 4 | 5 | ## Usage 6 | 7 |
8 | 9 | ```shell 10 | $ dstack stop --help 11 | #GENERATE# 12 | ``` 13 | 14 |
15 | 16 | [//]: # (TODO: Provide examples, incl. `-x`) 17 | -------------------------------------------------------------------------------- /docs/docs/reference/cli/dstack/volume.md: -------------------------------------------------------------------------------- 1 | # dstack volume 2 | 3 | The volumes commands. 4 | 5 | ## dstack volume list 6 | 7 | The `dstack volume list` command lists volumes. 8 | 9 | ##### Usage 10 | 11 |
12 | 13 | ```shell 14 | $ dstack volume list --help 15 | #GENERATE# 16 | ``` 17 | 18 |
19 | 20 | ## dstack volume delete 21 | 22 | The `dstack volume delete` command deletes volumes. 23 | 24 | ##### Usage 25 | 26 |
27 | 28 | ```shell 29 | $ dstack volume delete --help 30 | #GENERATE# 31 | ``` 32 | 33 |
34 | 35 | [//]: # (TODO: Provide examples) 36 | -------------------------------------------------------------------------------- /docs/docs/reference/dstack.yml.md: -------------------------------------------------------------------------------- 1 | # .dstack.yml 2 | 3 | - [`dev-environment`](dstack.yml/dev-environment.md) 4 | - [`task`](dstack.yml/task.md) 5 | - [`service`](dstack.yml/service.md) 6 | -------------------------------------------------------------------------------- /docs/docs/reference/dstack.yml/volume.md: -------------------------------------------------------------------------------- 1 | # `volume` 2 | 3 | The `volume` configuration type allows creating, registering, and updating [volumes](../../concepts/volumes.md). 4 | 5 | ## Root reference 6 | 7 | #SCHEMA# dstack._internal.core.models.volumes.VolumeConfiguration 8 | overrides: 9 | show_root_heading: false 10 | type: 11 | required: true 12 | -------------------------------------------------------------------------------- /docs/examples/accelerators/amd/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/accelerators/amd/index.md -------------------------------------------------------------------------------- /docs/examples/accelerators/intel/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/accelerators/intel/index.md -------------------------------------------------------------------------------- /docs/examples/accelerators/tenstorrent/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/accelerators/tenstorrent/index.md -------------------------------------------------------------------------------- /docs/examples/accelerators/tpu/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/accelerators/tpu/index.md -------------------------------------------------------------------------------- /docs/examples/clusters/a3high/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/clusters/a3high/index.md -------------------------------------------------------------------------------- /docs/examples/clusters/a3mega/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/clusters/a3mega/index.md -------------------------------------------------------------------------------- /docs/examples/clusters/nccl-tests/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/clusters/nccl-tests/index.md -------------------------------------------------------------------------------- /docs/examples/clusters/rccl-tests/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/clusters/rccl-tests/index.md -------------------------------------------------------------------------------- /docs/examples/distributed-training/axolotl/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/distributed-training/axolotl/index.md -------------------------------------------------------------------------------- /docs/examples/distributed-training/ray-ragen/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/distributed-training/ray-ragen/index.md -------------------------------------------------------------------------------- /docs/examples/distributed-training/trl/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/distributed-training/trl/index.md -------------------------------------------------------------------------------- /docs/examples/inference/nim/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/inference/nim/index.md -------------------------------------------------------------------------------- /docs/examples/inference/sglang/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/inference/sglang/index.md -------------------------------------------------------------------------------- /docs/examples/inference/tgi/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/inference/tgi/index.md -------------------------------------------------------------------------------- /docs/examples/inference/trtllm/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/inference/trtllm/index.md -------------------------------------------------------------------------------- /docs/examples/inference/vllm/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/inference/vllm/index.md -------------------------------------------------------------------------------- /docs/examples/llms/deepseek/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/llms/deepseek/index.md -------------------------------------------------------------------------------- /docs/examples/llms/llama/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/llms/llama/index.md -------------------------------------------------------------------------------- /docs/examples/misc/docker-compose/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/misc/docker-compose/index.md -------------------------------------------------------------------------------- /docs/examples/single-node-training/axolotl/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/single-node-training/axolotl/index.md -------------------------------------------------------------------------------- /docs/examples/single-node-training/trl/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/examples/single-node-training/trl/index.md -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | template: home.html 3 | title: AI container orchestration for AI teams 4 | hide: 5 | - navigation 6 | - toc 7 | - footer 8 | --- 9 | -------------------------------------------------------------------------------- /docs/overrides/.icons/custom/colored/github.svg: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /docs/overrides/.icons/custom/colored/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/overrides/.icons/custom/github.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/overrides/assets/images/github-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/github-logo.png -------------------------------------------------------------------------------- /docs/overrides/assets/images/quotes/alvarobartt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/quotes/alvarobartt.jpg -------------------------------------------------------------------------------- /docs/overrides/assets/images/quotes/chansung.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/quotes/chansung.jpg -------------------------------------------------------------------------------- /docs/overrides/assets/images/quotes/cudopete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/quotes/cudopete.png -------------------------------------------------------------------------------- /docs/overrides/assets/images/quotes/eckart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/quotes/eckart.png -------------------------------------------------------------------------------- /docs/overrides/assets/images/quotes/movchan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/quotes/movchan.jpg -------------------------------------------------------------------------------- /docs/overrides/assets/images/quotes/spott.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/quotes/spott.jpg -------------------------------------------------------------------------------- /docs/overrides/assets/images/slack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/slack.png -------------------------------------------------------------------------------- /docs/overrides/assets/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/docs/overrides/assets/images/twitter.png -------------------------------------------------------------------------------- /docs/overrides/landing.html: -------------------------------------------------------------------------------- 1 | {% extends "main.html" %} 2 | 3 | {% block header %} 4 | {% include "header-2.html" %} 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /docs/privacy.md: -------------------------------------------------------------------------------- 1 | --- 2 | template: privacy.html 3 | title: Privacy policy 4 | hide: 5 | - navigation 6 | - toc 7 | - footer 8 | --- 9 | -------------------------------------------------------------------------------- /examples/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: dev-environment 2 | # The name is optional, if not specified, generated randomly 3 | name: vscode 4 | 5 | #python: "3.11" 6 | 7 | image: un1def/dstack-base:py3.12-dev-cuda-12.1 8 | 9 | ide: vscode 10 | 11 | # Use either spot or on-demand instances 12 | #spot_policy: auto 13 | 14 | resources: 15 | cpu: x86:8..32 16 | gpu: 24GB..:1 17 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/examples/__init__.py -------------------------------------------------------------------------------- /examples/accelerators/tenstorrent/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: dev-environment 2 | name: cursor 3 | 4 | image: dstackai/tt-smi:latest 5 | 6 | ide: cursor 7 | 8 | resources: 9 | gpu: n150:1 10 | -------------------------------------------------------------------------------- /examples/accelerators/tenstorrent/tt-smi.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | name: tt-smi 3 | 4 | image: dstackai/tt-smi:latest 5 | 6 | commands: 7 | - tt-smi -s 8 | 9 | resources: 10 | gpu: n150:1 11 | -------------------------------------------------------------------------------- /examples/clusters/a3high/fleet.dstack.yml: -------------------------------------------------------------------------------- 1 | type: fleet 2 | name: a3high-cluster 3 | nodes: 2 4 | placement: cluster 5 | instance_types: 6 | - a3-highgpu-8g 7 | spot_policy: auto 8 | -------------------------------------------------------------------------------- /examples/clusters/a3mega/fleet.dstack.yml: -------------------------------------------------------------------------------- 1 | type: fleet 2 | name: a3mega-cluster 3 | nodes: 2 4 | placement: cluster 5 | instance_types: 6 | - a3-megagpu-8g 7 | spot_policy: auto 8 | -------------------------------------------------------------------------------- /examples/inference/nim/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: serve-distill-deepseek 3 | 4 | image: nvcr.io/nim/deepseek-ai/deepseek-r1-distill-llama-8b 5 | env: 6 | - NGC_API_KEY 7 | - NIM_MAX_MODEL_LEN=4096 8 | registry_auth: 9 | username: $oauthtoken 10 | password: ${{ env.NGC_API_KEY }} 11 | port: 8000 12 | # Register the model 13 | model: deepseek-ai/deepseek-r1-distill-llama-8b 14 | 15 | # Uncomment to leverage spot instances 16 | #spot_policy: auto 17 | 18 | # Cache downloaded models 19 | volumes: 20 | - instance_path: /root/.cache/nim 21 | path: /opt/nim/.cache 22 | optional: true 23 | 24 | resources: 25 | gpu: A100:40GB 26 | # Uncomment if using multiple GPUs 27 | #shm_size: 16GB 28 | -------------------------------------------------------------------------------- /examples/inference/tgi/amd/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: amd-service-tgi 3 | 4 | image: ghcr.io/huggingface/text-generation-inference:sha-a379d55-rocm 5 | env: 6 | - HF_TOKEN 7 | - ROCM_USE_FLASH_ATTN_V2_TRITON=true 8 | - TRUST_REMOTE_CODE=true 9 | - MODEL_ID=meta-llama/Meta-Llama-3.1-70B-Instruct 10 | commands: 11 | - text-generation-launcher --port 8000 12 | port: 8000 13 | # Register the model 14 | model: meta-llama/Meta-Llama-3.1-70B-Instruct 15 | 16 | # Uncomment to leverage spot instances 17 | #spot_policy: auto 18 | 19 | resources: 20 | gpu: MI300X 21 | disk: 150GB 22 | -------------------------------------------------------------------------------- /examples/inference/vllm/tpu/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | # The name is optional, if not specified, generated randomly 3 | name: llama31-service-vllm-tpu 4 | image: vllm/vllm-tpu:nightly 5 | env: 6 | - HF_TOKEN 7 | - MODEL_ID=meta-llama/Meta-Llama-3.1-8B-Instruct 8 | - MAX_MODEL_LEN=4096 9 | commands: 10 | - vllm serve $MODEL_ID 11 | --tensor-parallel-size 4 12 | --max-model-len $MAX_MODEL_LEN 13 | --port 8000 14 | # Expose the vllm server port 15 | port: 8000 16 | # Register the model 17 | model: meta-llama/Meta-Llama-3.1-8B-Instruct 18 | 19 | # Uncomment to leverage spot instances 20 | #spot_policy: auto 21 | 22 | resources: 23 | gpu: v5litepod-4 24 | -------------------------------------------------------------------------------- /examples/llms/deepseek/sglang/amd/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-r1-amd 3 | 4 | image: lmsysorg/sglang:v0.4.1.post4-rocm620 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-70B 7 | commands: 8 | - python3 -m sglang.launch_server 9 | --model-path $MODEL_ID 10 | --port 8000 11 | --trust-remote-code 12 | 13 | port: 8000 14 | model: deepseek-ai/DeepSeek-R1-Distill-Llama-70B 15 | 16 | resources: 17 | gpu: mi300x 18 | disk: 300Gb 19 | -------------------------------------------------------------------------------- /examples/llms/deepseek/sglang/amd/deepseek_v2_lite.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-v2-lite-amd 3 | 4 | image: lmsysorg/sglang:v0.4.1.post4-rocm620 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-V2-Lite 7 | commands: 8 | - python3 -m sglang.launch_server 9 | --model-path $MODEL_ID 10 | --port 8000 11 | --trust-remote-code 12 | 13 | port: 8000 14 | model: deepseek-ai/DeepSeek-V2-Lite 15 | 16 | resources: 17 | gpu: mi300x 18 | disk: 150Gb 19 | -------------------------------------------------------------------------------- /examples/llms/deepseek/sglang/nvidia/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-r1-nvidia 3 | 4 | image: lmsysorg/sglang:latest 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-8B 7 | commands: 8 | - python3 -m sglang.launch_server 9 | --model-path $MODEL_ID 10 | --port 8000 11 | --trust-remote-code 12 | 13 | port: 8000 14 | 15 | model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B 16 | 17 | resources: 18 | gpu: 24GB 19 | -------------------------------------------------------------------------------- /examples/llms/deepseek/sglang/nvidia/deepseek_v2_lite.dstack.yml: -------------------------------------------------------------------------------- 1 | # Not Working https://github.com/sgl-project/sglang/issues/3451 2 | type: service 3 | name: deepseek-v2-lite-nvidia 4 | 5 | image: lmsysorg/sglang:latest 6 | env: 7 | - MODEL_ID=deepseek-ai/DeepSeek-V2-Lite 8 | commands: 9 | - python3 -m sglang.launch_server 10 | --model-path $MODEL_ID 11 | --port 8000 12 | --trust-remote-code 13 | 14 | port: 8000 15 | 16 | model: deepseek-ai/DeepSeek-V2-Lite 17 | 18 | resources: 19 | gpu: 80GB 20 | -------------------------------------------------------------------------------- /examples/llms/deepseek/vllm/amd/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-r1-amd 3 | 4 | image: rocm/vllm:rocm6.2_mi300_ubuntu20.04_py3.9_vllm_0.6.4 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-70B 7 | - MAX_MODEL_LEN=126432 8 | commands: 9 | - vllm serve $MODEL_ID 10 | --max-model-len $MAX_MODEL_LEN 11 | --trust-remote-code 12 | port: 8000 13 | 14 | model: deepseek-ai/DeepSeek-R1-Distill-Llama-70B 15 | 16 | 17 | resources: 18 | gpu: mi300x 19 | disk: 300Gb 20 | -------------------------------------------------------------------------------- /examples/llms/deepseek/vllm/amd/deepseek_v2_lite.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-v2-lite-amd 3 | 4 | image: rocm/vllm:rocm6.2_mi300_ubuntu20.04_py3.9_vllm_0.6.4 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-V2-Lite 7 | commands: 8 | - vllm serve $MODEL_ID 9 | --trust-remote-code 10 | 11 | port: 8000 12 | 13 | model: deepseek-ai/DeepSeek-V2-Lite 14 | 15 | 16 | resources: 17 | gpu: mi300x 18 | disk: 150Gb 19 | -------------------------------------------------------------------------------- /examples/llms/deepseek/vllm/nvidia/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-r1-nvidia 3 | 4 | image: vllm/vllm-openai:latest 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Llama-8B 7 | - MAX_MODEL_LEN=4096 8 | commands: 9 | - vllm serve $MODEL_ID 10 | --max-model-len $MAX_MODEL_LEN 11 | 12 | port: 8000 13 | 14 | model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B 15 | 16 | resources: 17 | gpu: 24GB 18 | -------------------------------------------------------------------------------- /examples/llms/deepseek/vllm/nvidia/deepseek_v2_lite.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: deepseek-v2-lite-nvidia 3 | 4 | image: vllm/vllm-openai:latest 5 | env: 6 | - MODEL_ID=deepseek-ai/DeepSeek-V2-Lite 7 | - MAX_MODEL_LEN=4096 8 | commands: 9 | - vllm serve $MODEL_ID 10 | --max-model-len $MAX_MODEL_LEN 11 | --tensor-parallel-size $DSTACK_GPUS_NUM 12 | --trust-remote-code 13 | 14 | port: 8000 15 | 16 | model: deepseek-ai/DeepSeek-V2-Lite 17 | 18 | resources: 19 | gpu: 48GB 20 | -------------------------------------------------------------------------------- /examples/llms/llama/sglang/nvidia/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: llama4-scout 3 | 4 | image: lmsysorg/sglang 5 | env: 6 | - HF_TOKEN 7 | - MODEL_ID=meta-llama/Llama-4-Scout-17B-16E-Instruct 8 | - CONTEXT_LEN=256000 9 | commands: 10 | - python3 -m sglang.launch_server 11 | --model-path $MODEL_ID 12 | --tp $DSTACK_GPUS_NUM 13 | --context-length $CONTEXT_LEN 14 | --port 8000 15 | --kv-cache-dtype fp8_e5m2 16 | 17 | port: 8000 18 | ## Register the model 19 | model: meta-llama/Llama-4-Scout-17B-16E-Instruct 20 | 21 | resources: 22 | gpu: H200:2 23 | disk: 500GB.. 24 | -------------------------------------------------------------------------------- /examples/llms/llama/vllm/nvidia/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: llama4-scout 3 | 4 | image: vllm/vllm-openai 5 | env: 6 | - HF_TOKEN 7 | - MODEL_ID=meta-llama/Llama-4-Scout-17B-16E-Instruct 8 | - VLLM_DISABLE_COMPILE_CACHE=1 9 | - MAX_MODEL_LEN=256000 10 | commands: 11 | - | 12 | vllm serve $MODEL_ID \ 13 | --tensor-parallel-size $DSTACK_GPUS_NUM \ 14 | --max-model-len $MAX_MODEL_LEN \ 15 | --kv-cache-dtype fp8 \ 16 | --override-generation-config='{"attn_temperature_tuning": true}' 17 | 18 | port: 8000 19 | # Register the model 20 | model: meta-llama/Llama-4-Scout-17B-16E-Instruct 21 | 22 | resources: 23 | gpu: H200:2 24 | disk: 500GB.. 25 | -------------------------------------------------------------------------------- /examples/misc/airflow/dags/dstack-repo/task.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | commands: 3 | - echo "Running dstack task via Airflow" 4 | - sleep 10 5 | - echo "Finished" 6 | -------------------------------------------------------------------------------- /examples/misc/docker-compose/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: dev-environment 2 | name: vscode-dind 3 | 4 | privileged: true 5 | image: dstackai/dind 6 | env: 7 | - MODEL_ID=meta-llama/Llama-3.2-3B-Instruct 8 | - HF_TOKEN 9 | ide: vscode 10 | init: 11 | - start-dockerd 12 | 13 | # Uncomment to leverage spot instances 14 | #spot_policy: auto 15 | 16 | resources: 17 | gpu: 24GB 18 | -------------------------------------------------------------------------------- /examples/misc/docker-compose/service.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | name: chat-ui-service 3 | 4 | privileged: true 5 | image: dstackai/dind 6 | env: 7 | - MODEL_ID=meta-llama/Llama-3.2-3B-Instruct 8 | - HF_TOKEN 9 | working_dir: examples/misc/docker-compose 10 | commands: 11 | - start-dockerd 12 | - docker compose up 13 | port: 9000 14 | auth: false 15 | 16 | # Uncomment to leverage spot instances 17 | #spot_policy: auto 18 | 19 | resources: 20 | # Required resources 21 | gpu: "nvidia:24GB" 22 | 23 | # Uncomment to persist data 24 | #volumes: 25 | # - name: my-dind-volume 26 | # path: /var/lib/docker 27 | -------------------------------------------------------------------------------- /examples/misc/docker-compose/task.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | name: chat-ui-task 3 | 4 | privileged: true 5 | image: dstackai/dind 6 | env: 7 | - MODEL_ID=meta-llama/Llama-3.2-3B-Instruct 8 | - HF_TOKEN 9 | working_dir: examples/misc/docker-compose 10 | commands: 11 | - start-dockerd 12 | - docker compose up 13 | ports: 14 | - 9000 15 | 16 | # Use either spot or on-demand instances 17 | spot_policy: auto 18 | 19 | resources: 20 | # Required resources 21 | gpu: "nvidia:24GB" 22 | 23 | # Uncomment to persist data 24 | #volumes: 25 | # - name: my-dind-volume 26 | # path: /var/lib/docker 27 | -------------------------------------------------------------------------------- /examples/misc/docker-compose/volume.dstack.yml: -------------------------------------------------------------------------------- 1 | type: volume 2 | name: my-dind-volume 3 | 4 | backend: aws 5 | region: eu-west-1 6 | 7 | # Required size 8 | size: 100GB 9 | -------------------------------------------------------------------------------- /examples/misc/http.server/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | # This service deploys a simple HTTP server 3 | 4 | python: "3.11" 5 | commands: 6 | - python3 -m http.server 7 | port: 8000 8 | 9 | # Disable authentication 10 | auth: false 11 | -------------------------------------------------------------------------------- /examples/misc/http.server/README.md: -------------------------------------------------------------------------------- 1 | # Streamlit 2 | 3 | ## Service 4 | 5 | The following command runs `http.server` as a service: 6 | 7 | ```shell 8 | dstack apply -f examples/misc/http.server/.dstack.yml 9 | ``` 10 | 11 | See the configuration at [.dstack.yml](.dstack.yml). 12 | 13 | ## Task 14 | 15 | The following command runs `http.server` as a task: 16 | 17 | ```shell 18 | dstack apply -f examples/misc/http.server/task.dstack.yml 19 | ``` 20 | 21 | See the configuration at [task.dstack.yml](task.dstack.yml). 22 | 23 | For more details, refer to [services](https://dstack.ai/docs/services) or [tasks](https://dstack.ai/docs/tasks). 24 | -------------------------------------------------------------------------------- /examples/misc/http.server/task.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | # This task runs a simple HTTP server 3 | 4 | python: "3.11" 5 | 6 | commands: 7 | - python3 -m http.server 8 | 9 | ports: 10 | - 8000 11 | -------------------------------------------------------------------------------- /examples/misc/jupyterlab/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | # This task runs a JupyterLab instance 3 | 4 | ports: 5 | - 8888 6 | 7 | commands: 8 | - pip install jupyterlab 9 | - jupyter lab --allow-root 10 | -------------------------------------------------------------------------------- /examples/misc/ray/cluster.dstack.yaml: -------------------------------------------------------------------------------- 1 | type: task 2 | name: ray-cluster 3 | nodes: 4 4 | commands: 5 | - pip install -U "ray[default]" 6 | - > 7 | if [ $DSTACK_NODE_RANK = 0 ]; then 8 | ray start --head --port=6379; 9 | else 10 | ray start --address=$DSTACK_MASTER_NODE_IP:6379 11 | fi 12 | ports: 13 | - 8265 # ray dashboard port 14 | resources: 15 | shm_size: 8GB 16 | -------------------------------------------------------------------------------- /examples/misc/ray/fleet.dstack.yaml: -------------------------------------------------------------------------------- 1 | type: fleet 2 | name: ray-fleet 3 | nodes: 4 4 | placement: cluster 5 | backends: [gcp] 6 | resources: 7 | cpu: 8.. 8 | memory: 32GB.. 9 | gpu: 1 10 | -------------------------------------------------------------------------------- /examples/misc/spark/cluster.dstack.yaml: -------------------------------------------------------------------------------- 1 | type: task 2 | name: spark-cluster 3 | image: spark 4 | nodes: 2 5 | commands: 6 | - export SPARK_MASTER_HOST=$DSTACK_MASTER_NODE_IP 7 | - export SPARK_NO_DAEMONIZE=true 8 | - if [ $DSTACK_NODE_RANK = 0 ]; then /opt/spark/sbin/start-master.sh; else /opt/spark/sbin/start-worker.sh spark://$DSTACK_MASTER_NODE_IP:7077; fi 9 | ports: 10 | - 7077 11 | - 8080 12 | -------------------------------------------------------------------------------- /examples/misc/spark/fleet.dstack.yaml: -------------------------------------------------------------------------------- 1 | type: fleet 2 | name: spark-fleet 3 | nodes: 3 4 | placement: cluster 5 | backends: [gcp] 6 | -------------------------------------------------------------------------------- /examples/misc/spark/task.dstack.yaml: -------------------------------------------------------------------------------- 1 | type: task 2 | name: spark-task 3 | image: spark 4 | env: 5 | - SPARK_CLUSTER_IP 6 | commands: 7 | - pip install pyspark 8 | - python3 tasks/words.py 9 | -------------------------------------------------------------------------------- /examples/misc/streamlit/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: service 2 | # This service deploys a "Hello world" Streamlit app 3 | 4 | image: python:3.11 5 | commands: 6 | - pip3 install streamlit 7 | - streamlit hello 8 | port: 8501 9 | 10 | # Disable authentication 11 | auth: false 12 | -------------------------------------------------------------------------------- /examples/misc/streamlit/README.md: -------------------------------------------------------------------------------- 1 | # Streamlit 2 | 3 | ## Service (no auth) 4 | 5 | The following command runs `streamlit hello` as a service with disabled authentication: 6 | 7 | ```shell 8 | dstack apply -f examples/misc/streamlit/.dstack.yml 9 | ``` 10 | 11 | See the configuration at [.dstack.yml](.dstack.yml). 12 | 13 | ## Task 14 | 15 | The following command runs `streamlit hello` as a task: 16 | 17 | ```shell 18 | dstack apply -f examples/misc/streamlit/task.dstack.yml 19 | ``` 20 | 21 | See the configuration at [task.dstack.yml](task.dstack.yml). 22 | 23 | For more details, refer to [services](https://dstack.ai/docs/services) or [tasks](https://dstack.ai/docs/tasks). 24 | -------------------------------------------------------------------------------- /examples/misc/streamlit/task.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | # This task runs a "Hello world" Streamlit app 3 | 4 | image: python:3.11 5 | commands: 6 | - pip3 install streamlit 7 | - streamlit hello 8 | ports: 9 | - 8501 10 | -------------------------------------------------------------------------------- /examples/plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/examples/plugins/__init__.py -------------------------------------------------------------------------------- /examples/plugins/example_plugin/.python-version: -------------------------------------------------------------------------------- 1 | 3.11 2 | -------------------------------------------------------------------------------- /examples/plugins/example_plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | # Example of including plugins into the dstack server Docker image 2 | FROM dstackai/dstack:latest 3 | 4 | # Installing plugin from Docker context 5 | COPY . plugins/example_plugin 6 | RUN uv tool install "dstack[all]" --with plugins/example_plugin 7 | 8 | # Installing some other plugins from pypi/git 9 | # RUN uv tool install "dstack[all]" --with plugin1 --with plugin2 10 | -------------------------------------------------------------------------------- /examples/plugins/example_plugin/enterprise.Dockerfile: -------------------------------------------------------------------------------- 1 | # Example of including plugins into the dstack Enterprise Docker image 2 | FROM ghcr.io/dstackai/dstack-enterprise:latest 3 | 4 | # Installing plugin from Docker context 5 | COPY . plugins/example_plugin 6 | RUN uv pip install plugins/example_plugin 7 | 8 | # Installing some other plugins from pypi/git 9 | # RUN uv pip install plugin-name 10 | -------------------------------------------------------------------------------- /examples/plugins/example_plugin/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "example-plugin" 3 | version = "0.1.0" 4 | description = "A dstack plugin example" 5 | readme = "README.md" 6 | authors = [ 7 | { name = "Victor Skvortsov", email = "victor@dstack.ai" } 8 | ] 9 | requires-python = ">=3.9" 10 | dependencies = [] 11 | 12 | [build-system] 13 | requires = ["hatchling"] 14 | build-backend = "hatchling.build" 15 | 16 | [project.entry-points."dstack.plugins"] 17 | example_plugin = "example_plugin:ExamplePlugin" 18 | -------------------------------------------------------------------------------- /examples/plugins/example_plugin/src/example_plugin/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/examples/plugins/example_plugin/src/example_plugin/py.typed -------------------------------------------------------------------------------- /examples/plugins/example_plugin_server/.python-version: -------------------------------------------------------------------------------- 1 | 3.11 2 | -------------------------------------------------------------------------------- /examples/plugins/example_plugin_server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/examples/plugins/example_plugin_server/__init__.py -------------------------------------------------------------------------------- /examples/plugins/example_plugin_server/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "dstack-plugin-server" 3 | version = "0.1.0" 4 | description = "Example plugin server" 5 | readme = "README.md" 6 | requires-python = ">=3.11" 7 | dependencies = [ 8 | "fastapi[standard]>=0.115.12", 9 | "dstack", 10 | ] 11 | 12 | [build-system] 13 | requires = ["hatchling"] 14 | build-backend = "hatchling.build" 15 | 16 | [tool.hatch.build.targets.wheel] 17 | packages = ["src/example_plugin_server"] 18 | -------------------------------------------------------------------------------- /examples/plugins/example_plugin_server/src/example_plugin_server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/examples/plugins/example_plugin_server/src/example_plugin_server/__init__.py -------------------------------------------------------------------------------- /examples/plugins/example_plugin_server/src/example_plugin_server/utils.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | 5 | def configure_logging(): 6 | log_level = os.getenv("LOG_LEVEL", "INFO").upper() 7 | logging.basicConfig(level=log_level) 8 | -------------------------------------------------------------------------------- /examples/single-node-training/optimum-tpu/llama31/config.yaml: -------------------------------------------------------------------------------- 1 | per_device_train_batch_size: 24 2 | per_device_eval_batch_size: 8 3 | num_train_epochs: 1 4 | max_steps: -1 5 | output_dir: "./finetuned_models/llama3_fine_tuned" 6 | optim: "adafactor" 7 | dataset_name: "Abirate/english_quotes" 8 | model_name: "meta-llama/Meta-Llama-3.1-8B" 9 | lora_r: 4 10 | push_to_hub: True 11 | -------------------------------------------------------------------------------- /examples/single-node-training/qlora/.dstack.yml: -------------------------------------------------------------------------------- 1 | type: task 2 | 3 | python: "3.11" 4 | 5 | env: 6 | - HF_TOKEN 7 | - HF_HUB_ENABLE_HF_TRANSFER=1 8 | 9 | commands: 10 | - pip install -r examples/single-node-training/qlora/requirements.txt 11 | - tensorboard --logdir results/runs & 12 | - python examples/single-node-training/qlora/train.py --merge_and_push ${{ run.args }} 13 | ports: 14 | - 6006 15 | 16 | resources: 17 | gpu: 16GB..24GB 18 | -------------------------------------------------------------------------------- /examples/single-node-training/qlora/README.md: -------------------------------------------------------------------------------- 1 | # QLoRA 2 | 3 | The following command runs the task to fine-tune an LLM using QLoRA: 4 | 5 | ```shell 6 | dstack apply -f examples/single-node-training/qlora/.dstack.yml 7 | ``` 8 | 9 | See the configuration at [.dstack.yml](.dstack.yml). 10 | 11 | For more details, refer to [tasks](https://dstack.ai/docs/tasks). 12 | -------------------------------------------------------------------------------- /examples/single-node-training/qlora/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/examples/single-node-training/qlora/requirements.txt -------------------------------------------------------------------------------- /frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | server.js 4 | src/locale 5 | src/types 6 | src/setupProxy.js 7 | webpack/** 8 | webpack/env.js 9 | webpack/prod.js 10 | public 11 | staticServer.js 12 | webpack.config.js 13 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /.idea/ 3 | build 4 | -------------------------------------------------------------------------------- /frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 128, 6 | "tabWidth": 4 7 | } 8 | -------------------------------------------------------------------------------- /frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "dstack", 3 | "name": "dstack", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff", 15 | "permissions": ["clipboardWrite", "clipboardRead"] 16 | } 17 | -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/setupEnzyme.ts: -------------------------------------------------------------------------------- 1 | import { configure } from 'enzyme'; 2 | import Adapter from '@cfaester/enzyme-adapter-react-18'; 3 | 4 | configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /frontend/src/App/AuthErrorMessage/styles.module.scss: -------------------------------------------------------------------------------- 1 | .content { 2 | margin-top: 20px; 3 | } 4 | -------------------------------------------------------------------------------- /frontend/src/App/Loading/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { AppLayout, Spinner } from 'components'; 4 | 5 | import styles from './styles.module.scss'; 6 | 7 | export const Loading: React.FC = () => { 8 | return ( 9 | 15 | 16 | 17 | } 18 | /> 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /frontend/src/App/Loading/styles.module.scss: -------------------------------------------------------------------------------- 1 | .spinner { 2 | height: 100%; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/App/Login/EnterpriseLogin/styles.module.scss: -------------------------------------------------------------------------------- 1 | .form { 2 | max-width: 440px; 3 | width: 100%; 4 | margin-left: auto; 5 | margin-right: auto; 6 | padding-top: 120px; 7 | } 8 | .token { 9 | 10 | } 11 | .okta { 12 | margin-top: 20px; 13 | } 14 | .entra { 15 | margin-top: 20px; 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/App/Login/EntraID/LoginByEntraID/styles.module.scss: -------------------------------------------------------------------------------- 1 | @use '@cloudscape-design/design-tokens/index' as awsui; 2 | 3 | .entraSignIn { 4 | display: flex; 5 | justify-content: center; 6 | 7 | button { 8 | .loginButtonInner { 9 | display: inline-flex; 10 | align-items: center; 11 | justify-content: center; 12 | gap: 8px; 13 | } 14 | 15 | .loginButtonLabel { 16 | height: 20px; 17 | line-height: 21px; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/App/Login/LoginByOkta/styles.module.scss: -------------------------------------------------------------------------------- 1 | @use '@cloudscape-design/design-tokens/index' as awsui; 2 | 3 | .signIn { 4 | display: flex; 5 | justify-content: center; 6 | 7 | button { 8 | .loginButtonInner { 9 | display: inline-flex; 10 | align-items: center; 11 | justify-content: center; 12 | gap: 8px; 13 | } 14 | 15 | .loginButtonLabel { 16 | height: 20px; 17 | line-height: 21px; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/App/Login/LoginByTokenForm/styles.module.scss: -------------------------------------------------------------------------------- 1 | .form { 2 | max-width: 440px; 3 | margin-left: auto; 4 | margin-right: auto; 5 | } 6 | .token { 7 | display: flex; 8 | align-items: flex-start; 9 | gap: 12px; 10 | } 11 | .fieldWrap { 12 | flex-grow: 1; 13 | min-width: 0; 14 | } 15 | .buttonWrap { 16 | display: flex; 17 | flex-shrink: 0; 18 | width: 104px; 19 | margin-right: -20px; 20 | 21 | button { 22 | white-space: nowrap !important; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/src/App/Login/TokenLogin/styles.module.scss: -------------------------------------------------------------------------------- 1 | .form { 2 | max-width: 440px; 3 | width: 100%; 4 | margin-left: auto; 5 | margin-right: auto; 6 | padding-top: 120px; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/App/Logout/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { Navigate } from 'react-router-dom'; 3 | 4 | import { useAppDispatch } from 'hooks'; 5 | import { ROUTES } from 'routes'; 6 | import { projectApi } from 'services/project'; 7 | import { userApi } from 'services/user'; 8 | 9 | import { removeAuthData } from '../slice'; 10 | 11 | export const Logout: React.FC = () => { 12 | const dispatch = useAppDispatch(); 13 | 14 | useEffect(() => { 15 | dispatch(removeAuthData()); 16 | 17 | dispatch(userApi.util.resetApiState()); 18 | dispatch(projectApi.util.resetApiState()); 19 | }, []); 20 | 21 | return ; 22 | }; 23 | -------------------------------------------------------------------------------- /frontend/src/App/constants.ts: -------------------------------------------------------------------------------- 1 | export const AUTH_DATA_STORAGE_KEY = 'authData'; 2 | export const MODE_STORAGE_KEY = 'mode'; 3 | -------------------------------------------------------------------------------- /frontend/src/App/helpers.ts: -------------------------------------------------------------------------------- 1 | import { Mode } from '@cloudscape-design/global-styles'; 2 | 3 | export const getThemeMode = (): Mode => (window?.matchMedia('(prefers-color-scheme: dark)').matches ? Mode.Dark : Mode.Light); 4 | 5 | export function getBaseUrl(): string { 6 | const { protocol, hostname, port } = window.location; 7 | return `${protocol}//${hostname}${port ? `:${port}` : ''}`; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | .b-page-header { 2 | position: relative; 3 | z-index: 1002; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/assets/css/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/frontend/src/assets/css/mixins.css -------------------------------------------------------------------------------- /frontend/src/assets/css/variables.css: -------------------------------------------------------------------------------- 1 | @custom-media --mobile (width <= 640px); 2 | @custom-media --no-mobile (width > 640px); 3 | @custom-media --no-desktop (width < 980px); 4 | @custom-media --desktop (width >= 980px); 5 | 6 | :root { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/frontend/src/assets/icons/.gitkeep -------------------------------------------------------------------------------- /frontend/src/assets/icons/okta.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/theme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/frontend/src/assets/images/.gitkeep -------------------------------------------------------------------------------- /frontend/src/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/frontend/src/assets/images/favicon.png -------------------------------------------------------------------------------- /frontend/src/components/Button/styles.module.scss: -------------------------------------------------------------------------------- 1 | @use '@cloudscape-design/design-tokens/index' as awsui; 2 | 3 | .button { 4 | &.danger-normal { 5 | &:not([disabled]) { 6 | color: awsui.$color-charts-red-600 !important; 7 | border-color: awsui.$color-charts-red-600 !important; 8 | 9 | &:hover { 10 | color: awsui.$color-charts-red-500 !important; 11 | border-color: awsui.$color-charts-red-500 !important; 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/components/ButtonWithConfirmation/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import type { IProps as ButtonProps } from '../Button'; 4 | 5 | export interface IProps extends Omit { 6 | confirmTitle?: string; 7 | confirmContent?: ReactNode; 8 | onClick?: () => void; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/components/Code/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classNames from 'classnames'; 3 | import Box from '@cloudscape-design/components/box'; 4 | 5 | import styles from './styles.module.scss'; 6 | 7 | export interface Props extends React.PropsWithChildren { 8 | className?: string; 9 | } 10 | 11 | export const Code: React.FC = ({ children, className }) => { 12 | return ( 13 |
14 | 15 | {children} 16 | 17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /frontend/src/components/Code/styles.module.scss: -------------------------------------------------------------------------------- 1 | @use '@cloudscape-design/design-tokens/index' as awsui; 2 | 3 | .code { 4 | padding: 8px; 5 | background-color: awsui.$color-background-input-disabled; 6 | border-radius: 8px; 7 | white-space: pre-wrap; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/components/ConfirmationDialog/styles.module.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/frontend/src/components/ConfirmationDialog/styles.module.scss -------------------------------------------------------------------------------- /frontend/src/components/ConfirmationDialog/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { ButtonProps } from 'components'; 4 | 5 | export interface IProps { 6 | title?: string; 7 | content?: ReactNode; 8 | visible?: boolean; 9 | onDiscard: ButtonProps['onClick']; 10 | onConfirm: ButtonProps['onClick']; 11 | 12 | cancelButtonLabel?: string; 13 | confirmButtonLabel?: string; 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/components/DetailsHeader/types.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export interface IProps { 4 | title: React.ReactNode; 5 | editAction?: () => void; 6 | deleteAction?: () => void; 7 | editDisabled?: boolean; 8 | deleteDisabled?: boolean; 9 | actionButtons?: React.ReactNode; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/components/FileUploader/Token/styles.module.scss: -------------------------------------------------------------------------------- 1 | .tokenPanel { 2 | background-color: var(--color-background-item-selected-ebt4bi); 3 | display: flex; 4 | border: 0.2em solid var(--color-border-item-selected-ppkssz); 5 | padding: 1em; 6 | margin: 1em; 7 | border-radius: var(--border-radius-token-wohc9e); 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/components/Hotspot/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import HotspotGeneral, { HotspotProps } from '@cloudscape-design/components/hotspot'; 3 | 4 | export interface IProps extends HotspotProps { 5 | renderHotspot?: boolean; 6 | } 7 | 8 | export const Hotspot: React.FC = ({ renderHotspot = true, children, ...props }) => { 9 | if (!renderHotspot) { 10 | return children; 11 | } 12 | 13 | return {children}; 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/components/InfoLink/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useTranslation } from 'react-i18next'; 3 | import Link from '@cloudscape-design/components/link'; 4 | 5 | import { IProps } from './types'; 6 | 7 | export const InfoLink: React.FC = (props) => { 8 | const { t } = useTranslation(); 9 | 10 | return ( 11 | 12 | {t('common.info')} 13 | 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /frontend/src/components/InfoLink/types.ts: -------------------------------------------------------------------------------- 1 | import { LinkProps } from '@cloudscape-design/components/link'; 2 | 3 | export interface IProps { 4 | id?: string; 5 | ariaLabel?: string; 6 | onFollow: LinkProps['onFollow']; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/components/ListEmptyMessage/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Box from '@cloudscape-design/components/box'; 3 | 4 | import { IProps } from './types'; 5 | 6 | export const ListEmptyMessage: React.FC = ({ title, message, children }) => { 7 | return ( 8 | 9 | {title && {title}} 10 | 11 | {message} 12 | 13 | {children} 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /frontend/src/components/ListEmptyMessage/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | export interface IProps { 4 | title?: string; 5 | message?: string; 6 | children?: ReactNode; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/components/Loader/styles.module.scss: -------------------------------------------------------------------------------- 1 | .loader { 2 | display: flex; 3 | justify-content: center; 4 | transition: opacity .2s ease; 5 | 6 | &:not(.show) { 7 | opacity: 0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/components/NavigateLink/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useNavigate } from 'react-router-dom'; 3 | import Link, { LinkProps } from '@cloudscape-design/components/link'; 4 | export const NavigateLink: React.FC = ({ onFollow, ...props }) => { 5 | const navigate = useNavigate(); 6 | const onFollowHandler: LinkProps['onFollow'] = (event) => { 7 | event.preventDefault(); 8 | 9 | if (onFollow) onFollow(event); 10 | if (event.detail.href) navigate(event.detail.href); 11 | }; 12 | 13 | return ; 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/components/Notifications/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Flashbar from '@cloudscape-design/components/flashbar'; 3 | 4 | import { useAppSelector } from 'hooks'; 5 | 6 | import { selectNotifications } from './slice'; 7 | 8 | export const Notifications: React.FC = () => { 9 | const notifications = useAppSelector(selectNotifications); 10 | 11 | return ; 12 | }; 13 | -------------------------------------------------------------------------------- /frontend/src/components/Notifications/types.ts: -------------------------------------------------------------------------------- 1 | import { FlashbarProps } from '@cloudscape-design/components/flashbar'; 2 | 3 | export type Notification = FlashbarProps.MessageDefinition; 4 | -------------------------------------------------------------------------------- /frontend/src/components/PermissionGuard/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { usePermissionGuard } from 'hooks'; 4 | 5 | import { IProps } from './types'; 6 | 7 | export const PermissionGuard: React.FC = ({ children, ...props }) => { 8 | const [isAvailable] = usePermissionGuard(props); 9 | 10 | if (!isAvailable) return null; 11 | 12 | return <>{children}; 13 | }; 14 | -------------------------------------------------------------------------------- /frontend/src/components/PermissionGuard/types.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { GlobalUserRole, ProjectUserRole } from 'types'; 4 | 5 | export interface IProps { 6 | allowedGlobalRoles?: GlobalUserRole[]; 7 | allowedProjectRoles?: ProjectUserRole[]; 8 | projectRole?: string; 9 | children: React.ReactNode; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/components/Tabs/styles.module.scss: -------------------------------------------------------------------------------- 1 | .tabs { 2 | &:not(.hasContent) { 3 | :global { 4 | [class^="awsui_tabs-content-wrapper"] { 5 | display: none; 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/components/form/Checkbox/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | import { ControllerProps, FieldValues } from 'react-hook-form'; 3 | import { CheckboxProps } from '@cloudscape-design/components/checkbox'; 4 | import { FormFieldProps } from '@cloudscape-design/components/form-field'; 5 | 6 | export type FormCheckboxProps = Omit & 7 | Omit & 8 | Pick, 'control' | 'name' | 'rules'> & { 9 | leftContent?: ReactNode; 10 | checkboxLabel?: string; 11 | }; 12 | -------------------------------------------------------------------------------- /frontend/src/components/form/CodeEditor/types.ts: -------------------------------------------------------------------------------- 1 | import { ControllerProps, FieldValues } from 'react-hook-form'; 2 | import { CodeEditorProps } from '@cloudscape-design/components/code-editor'; 3 | import { FormFieldProps } from '@cloudscape-design/components/form-field'; 4 | 5 | export type FormCodeEditorProps = Omit< 6 | CodeEditorProps, 7 | 'value' | 'name' | 'i18nStrings' | 'ace' | 'onPreferencesChange' | 'preferences' 8 | > & 9 | Omit & 10 | Pick, 'control' | 'name' | 'rules'>; 11 | -------------------------------------------------------------------------------- /frontend/src/components/form/Input/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | import { ControllerProps, FieldValues } from 'react-hook-form'; 3 | import { FormFieldProps } from '@cloudscape-design/components/form-field'; 4 | import { InputProps } from '@cloudscape-design/components/input'; 5 | 6 | export type FormInputProps = Omit & 7 | Omit & 8 | Pick, 'control' | 'name' | 'rules'> & { 9 | leftContent?: ReactNode; 10 | hotspotId?: string; 11 | }; 12 | -------------------------------------------------------------------------------- /frontend/src/components/form/RadioButtons/types.ts: -------------------------------------------------------------------------------- 1 | import { ControllerProps, FieldValues } from 'react-hook-form'; 2 | import { FormFieldProps } from '@cloudscape-design/components/form-field'; 3 | import { RadioGroupProps } from '@cloudscape-design/components/radio-group'; 4 | 5 | export type FormRadioButtonsProps = Omit & 6 | Omit & 7 | Pick, 'control' | 'name' | 'rules'>; 8 | -------------------------------------------------------------------------------- /frontend/src/components/form/Select/types.ts: -------------------------------------------------------------------------------- 1 | import { ControllerProps, FieldValues } from 'react-hook-form'; 2 | import { FormFieldProps } from '@cloudscape-design/components/form-field'; 3 | import { SelectProps } from '@cloudscape-design/components/select'; 4 | 5 | export type FormSelectOption = SelectProps.Option; 6 | export type FormSelectOptions = ReadonlyArray; 7 | 8 | export type FormSelectProps = Omit & 9 | Omit & 10 | Pick, 'control' | 'name' | 'rules'> & { 11 | options: ReadonlyArray; 12 | }; 13 | -------------------------------------------------------------------------------- /frontend/src/components/form/Textarea/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | import { ControllerProps, FieldValues } from 'react-hook-form'; 3 | import { FormFieldProps } from '@cloudscape-design/components/form-field'; 4 | import { TextareaProps } from '@cloudscape-design/components/textarea'; 5 | 6 | export type FormTextareaProps = Omit & 7 | Omit & 8 | Pick, 'control' | 'name' | 'rules'> & { 9 | leftContent?: ReactNode; 10 | }; 11 | -------------------------------------------------------------------------------- /frontend/src/components/form/Tiles/types.ts: -------------------------------------------------------------------------------- 1 | import { Control, FieldValues, Path } from 'react-hook-form'; 2 | import { TilesProps } from '@cloudscape-design/components/tiles'; 3 | 4 | export type FormTilesProps = Omit & { 5 | control: Control; 6 | name: Path; 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/consts.ts: -------------------------------------------------------------------------------- 1 | export const DATE_TIME_FORMAT = 'MM/dd/yyyy HH:mm'; 2 | export const DISCORD_URL = 'https://discord.gg/u8SmfwPpMd'; 3 | export const QUICK_START_URL = 'https://dstack.ai/docs/quickstart/'; 4 | export const TALLY_FORM_ID = '3xYlYG'; 5 | export const DOCS_URL = 'https://dstack.ai/docs/'; 6 | export const DEFAULT_TABLE_PAGE_SIZE = 20; 7 | -------------------------------------------------------------------------------- /frontend/src/consts/index.ts: -------------------------------------------------------------------------------- 1 | export const TEMP = 'temp'; 2 | -------------------------------------------------------------------------------- /frontend/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAppDispatch } from './useAppDispatch'; 2 | export { default as useAppSelector } from './useAppSelector'; 3 | export { useBreadcrumbs } from './useBreadcrumbs'; 4 | export { useNotifications } from './useNotifications'; 5 | export { useHelpPanel } from './useHelpPanel'; 6 | export { usePermissionGuard } from './usePermissionGuard'; 7 | export { useInfiniteScroll } from './useInfiniteScroll'; 8 | 9 | // cloudscape 10 | export { useCollection } from '@cloudscape-design/collection-hooks'; 11 | -------------------------------------------------------------------------------- /frontend/src/hooks/useAppDispatch.ts: -------------------------------------------------------------------------------- 1 | import { useDispatch } from 'react-redux'; 2 | import { AppDispatch } from 'store'; 3 | 4 | const useAppDispatch = () => useDispatch(); 5 | 6 | export default useAppDispatch; 7 | -------------------------------------------------------------------------------- /frontend/src/hooks/useAppSelector.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useSelector } from 'react-redux'; 2 | import { RootState } from 'store'; 3 | 4 | const useAppSelector: TypedUseSelectorHook = useSelector; 5 | 6 | export default useAppSelector; 7 | -------------------------------------------------------------------------------- /frontend/src/hooks/useBreadcrumbs.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | import { setBreadcrumb } from 'App/slice'; 4 | 5 | import useAppDispatch from './useAppDispatch'; 6 | 7 | export const useBreadcrumbs = (breadcrumbs: TBreadcrumb[]) => { 8 | const dispatch = useAppDispatch(); 9 | 10 | useEffect(() => { 11 | dispatch(setBreadcrumb(breadcrumbs)); 12 | 13 | return () => { 14 | dispatch(setBreadcrumb(null)); 15 | }; 16 | }, [breadcrumbs]); 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/hooks/useHelpPanel.ts: -------------------------------------------------------------------------------- 1 | import { openHelpPanel } from 'App/slice'; 2 | 3 | import useAppDispatch from './useAppDispatch'; 4 | 5 | import { THelpPanelContent } from 'App/types'; 6 | 7 | export const useHelpPanel = () => { 8 | const dispatch = useAppDispatch(); 9 | 10 | const openPanel = (content: THelpPanelContent) => { 11 | dispatch(openHelpPanel(content)); 12 | }; 13 | 14 | return [openPanel]; 15 | }; 16 | -------------------------------------------------------------------------------- /frontend/src/hooks/useIsMounted.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useEffect, useRef } from 'react'; 2 | 3 | function useIsMounted() { 4 | const isMounted = useRef(false); 5 | 6 | useEffect(() => { 7 | isMounted.current = true; 8 | 9 | return () => { 10 | isMounted.current = false; 11 | }; 12 | }, []); 13 | 14 | return useCallback(() => isMounted.current, []); 15 | } 16 | 17 | export default useIsMounted; 18 | -------------------------------------------------------------------------------- /frontend/src/hooks/usePrevious.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | function usePrevious(value: T): T { 4 | const ref = useRef(value); 5 | 6 | useEffect(() => { 7 | ref.current = value; 8 | }, [value]); 9 | 10 | return ref.current; 11 | } 12 | 13 | export default usePrevious; 14 | -------------------------------------------------------------------------------- /frontend/src/layouts/AppLayout/Tally/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | 3 | export const TallyComponent: React.FC = () => { 4 | useEffect(() => { 5 | const widgetScriptSrc = 'https://tally.so/widgets/embed.js'; 6 | 7 | if (document.querySelector(`script[src="${widgetScriptSrc}"]`) === null) { 8 | const script = document.createElement('script'); 9 | script.src = widgetScriptSrc; 10 | document.body.appendChild(script); 11 | return; 12 | } 13 | }, []); 14 | 15 | return null; 16 | }; 17 | -------------------------------------------------------------------------------- /frontend/src/layouts/AppLayout/TutorialPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { TutorialPanel as TutorialPanelGeneric, TutorialPanelProps } from 'components'; 4 | 5 | import { tutorialPanelI18nStrings } from './constants'; 6 | import { useTutorials } from './hooks'; 7 | 8 | export interface Props extends Partial { 9 | test?: string; 10 | } 11 | 12 | export const TutorialPanel: React.FC = () => { 13 | const { tutorials } = useTutorials(); 14 | 15 | return ; 16 | }; 17 | -------------------------------------------------------------------------------- /frontend/src/layouts/UnauthorizedLayout/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './styles.module.scss'; 4 | 5 | export interface UnauthorizedLayoutProps { 6 | children?: React.ReactNode; 7 | } 8 | 9 | export const UnauthorizedLayout: React.FC = ({ children }) => { 10 | return
{children}
; 11 | }; 12 | -------------------------------------------------------------------------------- /frontend/src/layouts/UnauthorizedLayout/styles.module.scss: -------------------------------------------------------------------------------- 1 | @use '@cloudscape-design/design-tokens/index' as awsui; 2 | 3 | .layout { 4 | background: awsui.$color-background-layout-main; 5 | padding-top: 40px; 6 | padding-bottom: 40px; 7 | min-height: 100vh; 8 | box-sizing: border-box; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/libs/fetchBaseQueryHeaders.ts: -------------------------------------------------------------------------------- 1 | import type { BaseQueryApi } from '@reduxjs/toolkit/query'; 2 | 3 | import { RootState } from '../store'; 4 | 5 | function baseQueryHeaders(headers: Headers, { getState }: Pick): Headers { 6 | const token = (getState() as RootState).app.authData?.token; 7 | const authorizationHeader = headers.get('Authorization'); 8 | 9 | if (token && !authorizationHeader) { 10 | headers.set('Authorization', `Bearer ${token}`); 11 | } 12 | 13 | headers.set('X-API-VERSION', 'latest'); 14 | 15 | return headers; 16 | } 17 | 18 | export default baseQueryHeaders; 19 | -------------------------------------------------------------------------------- /frontend/src/libs/form.ts: -------------------------------------------------------------------------------- 1 | import { FormFieldError } from './types'; 2 | 3 | export const getFieldErrorFromServerResponse = (error: FormFieldError): { fieldNamePath: string; message: string } => { 4 | const fieldNamePath = error.loc.filter((key) => key !== 'body').join('.'); 5 | const message = error.msg; 6 | 7 | return { fieldNamePath, message }; 8 | }; 9 | -------------------------------------------------------------------------------- /frontend/src/libs/types.ts: -------------------------------------------------------------------------------- 1 | export type FormFieldError = { 2 | loc: string[]; 3 | msg: string; 4 | type?: string; 5 | code: string; 6 | }; 7 | 8 | export type ResponseServerErrorItem = { 9 | msg: string; 10 | code: string; 11 | }; 12 | 13 | export type ResponseServerError = { 14 | detail: (FormFieldError | ResponseServerErrorItem)[]; 15 | }; 16 | -------------------------------------------------------------------------------- /frontend/src/libs/volumes.ts: -------------------------------------------------------------------------------- 1 | import { StatusIndicatorProps } from '@cloudscape-design/components'; 2 | 3 | export const getStatusIconType = (status: IVolume['status']): StatusIndicatorProps['type'] => { 4 | switch (status) { 5 | case 'failed': 6 | return 'error'; 7 | case 'active': 8 | return 'success'; 9 | case 'provisioning': 10 | return 'in-progress'; 11 | case 'submitted': 12 | default: 13 | console.error(new Error('Undefined volume status')); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /frontend/src/locale/index.ts: -------------------------------------------------------------------------------- 1 | import i18n from 'i18next'; 2 | import { initReactI18next } from 'react-i18next'; 3 | 4 | import en from './en.json'; 5 | 6 | i18n.use(initReactI18next).init({ 7 | returnNull: false, 8 | resources: { 9 | en: { 10 | translation: en, 11 | }, 12 | }, 13 | fallbackLng: 'en', 14 | 15 | interpolation: { 16 | escapeValue: false, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/src/pages/Fleets/List/styles.module.scss: -------------------------------------------------------------------------------- 1 | .filters { 2 | --select-width: calc((688px - 3 * 20px) / 2); 3 | display: flex; 4 | flex-wrap: wrap; 5 | gap: 0 20px; 6 | 7 | .select { 8 | width: var(--select-width, 30%); 9 | } 10 | 11 | .activeOnly { 12 | display: flex; 13 | align-items: center; 14 | padding-top: 26px; 15 | } 16 | 17 | .clear { 18 | padding-top: 26px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/pages/Fleets/index.ts: -------------------------------------------------------------------------------- 1 | export { FleetList } from './List'; 2 | export { FleetDetails } from './Details'; 3 | -------------------------------------------------------------------------------- /frontend/src/pages/Instances/List/styles.module.scss: -------------------------------------------------------------------------------- 1 | .filters { 2 | --select-width: calc((688px - 3 * 20px) / 2); 3 | display: flex; 4 | flex-wrap: wrap; 5 | gap: 0 20px; 6 | 7 | .select { 8 | width: var(--select-width, 30%); 9 | } 10 | 11 | .activeOnly { 12 | display: flex; 13 | align-items: center; 14 | padding-top: 26px; 15 | } 16 | 17 | .clear { 18 | padding-top: 26px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/pages/Instances/index.ts: -------------------------------------------------------------------------------- 1 | export { List as InstanceList } from './List'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Models/Details/types.ts: -------------------------------------------------------------------------------- 1 | export interface FormValues { 2 | instructions?: string; 3 | message: string; 4 | } 5 | 6 | export type Role = 'system' | 'user' | 'assistant' | 'tool'; 7 | 8 | export interface Message { 9 | role: Role; 10 | content: string; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/pages/Models/List/Preferences/useModelListPreferences.ts: -------------------------------------------------------------------------------- 1 | import { CollectionPreferencesProps } from 'components'; 2 | 3 | import { useLocalStorageState } from 'hooks/useLocalStorageState'; 4 | 5 | import { DEFAULT_PREFERENCES } from './consts'; 6 | 7 | export const useModelListPreferences = () => { 8 | const [preferences, setPreferences] = useLocalStorageState( 9 | 'model-list-preferences', 10 | DEFAULT_PREFERENCES, 11 | ); 12 | 13 | return [preferences, setPreferences] as const; 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/pages/Models/List/styles.module.scss: -------------------------------------------------------------------------------- 1 | .selectFilters { 2 | --select-width: calc((688px - 3 * 20px) / 2); 3 | display: flex; 4 | flex-wrap: wrap; 5 | gap: 0 20px; 6 | 7 | .select { 8 | width: var(--select-width, 30%); 9 | } 10 | 11 | .activeOnly { 12 | display: flex; 13 | align-items: center; 14 | padding-top: 26px; 15 | } 16 | 17 | .clear { 18 | padding-top: 26px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/pages/Models/List/types.ts: -------------------------------------------------------------------------------- 1 | export interface IModelExtended extends Partial { 2 | id: string; 3 | run_name: string; 4 | project_name: string; 5 | submitted_at: string; 6 | user: string; 7 | resources: string | null; 8 | price: number | null; 9 | region: string | null; 10 | repository: string | null; 11 | backend: TBackendType | null; 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/pages/Models/helpers.ts: -------------------------------------------------------------------------------- 1 | import { isValidUrl } from 'libs'; 2 | 3 | export const getModelGateway = (baseUrl?: IModel['base_url']) => { 4 | if (!baseUrl) { 5 | return ''; 6 | } 7 | 8 | if (isValidUrl(baseUrl)) { 9 | return baseUrl; 10 | } 11 | 12 | return document.location.origin + baseUrl; 13 | }; 14 | -------------------------------------------------------------------------------- /frontend/src/pages/Models/index.ts: -------------------------------------------------------------------------------- 1 | export { List as ModelsList } from './List'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Backends/Table/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useColumnsDefinitions'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Backends/Table/styles.module.scss: -------------------------------------------------------------------------------- 1 | .cell { 2 | display: flex; 3 | align-items: center; 4 | } 5 | 6 | .contextMenu { 7 | margin-left: auto; 8 | padding-left: 20px; 9 | } 10 | 11 | .ellipsisCell { 12 | overflow: hidden; 13 | white-space: nowrap; 14 | text-overflow: ellipsis; 15 | max-width: 450px; 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Backends/Table/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps { 2 | backends: IProjectBackend[]; 3 | onClickAddBackend?: () => void; 4 | deleteBackends?: (backends: readonly IProjectBackend[] | IProjectBackend[]) => void; 5 | editBackend?: (backend: IProjectBackend) => void; 6 | isDisabledDelete?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Backends/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useBackendsTable } from './useBackendsTable'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Backends/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export { BackendAdd } from './Add'; 3 | export { BackendEdit } from './Edit'; 4 | 5 | export const Backends: React.FC = () => { 6 | return null; 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Details/Settings/styles.module.scss: -------------------------------------------------------------------------------- 1 | .dangerSectionGrid { 2 | display: grid; 3 | gap: 20px 40px; 4 | grid-template-columns: minmax(auto, 300px) 1fr; 5 | } 6 | 7 | .dangerSectionField { 8 | width: 300px; 9 | } 10 | 11 | .codeWrapper { 12 | position: relative; 13 | 14 | .code { 15 | padding: 16px 12px; 16 | } 17 | 18 | .copy { 19 | position: absolute; 20 | top: 10px; 21 | right: 8px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Details/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Outlet, useParams } from 'react-router-dom'; 3 | 4 | import { ContentLayout, DetailsHeader } from 'components'; 5 | 6 | export const ProjectDetails: React.FC = () => { 7 | const params = useParams(); 8 | const paramProjectName = params.projectName ?? ''; 9 | 10 | return ( 11 | }> 12 | 13 | 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Form/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps { 2 | initialValues?: Partial; 3 | loading?: boolean; 4 | onCancel: () => void; 5 | onSubmit: (user: IProject) => Promise; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/Add/styles.module.scss: -------------------------------------------------------------------------------- 1 | .fieldSpinner { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | height: 34px; 6 | width: 34px; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/Edit/styles.module.scss: -------------------------------------------------------------------------------- 1 | .fieldSpinner { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | height: 34px; 6 | width: 34px; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/Table/constants.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const GATEWAYS_INFO = { 4 | header:

Gateways

, 5 | body: ( 6 | <> 7 |

Gateways manage the ingress traffic for running services.

8 |

9 | To learn more about gateways, see the{' '} 10 | 11 | documentation 12 | 13 | . 14 |

15 | 16 | ), 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/Table/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useColumnsDefinitions'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/Table/styles.module.scss: -------------------------------------------------------------------------------- 1 | .cell { 2 | display: flex; 3 | align-items: center; 4 | } 5 | 6 | .contextMenu { 7 | margin-left: auto; 8 | padding-left: 20px; 9 | } 10 | 11 | .ellipsisCell { 12 | overflow: hidden; 13 | white-space: nowrap; 14 | text-overflow: ellipsis; 15 | max-width: 450px; 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/Table/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps { 2 | gateways: IGateway[]; 3 | addItem?: () => void; 4 | deleteItem?: (gateways: readonly IGateway[] | IGateway[]) => void; 5 | editItem?: (gateways: IGateway) => void; 6 | isDisabledDelete?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useGatewaysTable } from './useGatewaysTable'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Gateways/index.tsx: -------------------------------------------------------------------------------- 1 | export { GatewaysTable } from './Table'; 2 | export { AddGateway } from './Add'; 3 | export { EditGateway } from './Edit'; 4 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/List/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useColumnsDefinitions'; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/List/styles.module.scss: -------------------------------------------------------------------------------- 1 | .cell { 2 | display: flex; 3 | align-items: center; 4 | } 5 | 6 | .contextMenu { 7 | margin-left: auto; 8 | padding-left: 20px; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Members/styles.module.scss: -------------------------------------------------------------------------------- 1 | .role { 2 | display: flex; 3 | align-items: center; 4 | gap: 20px; 5 | } 6 | .roleFieldWrapper { 7 | flex-grow: 1; 8 | flex-basis: 0; 9 | max-width: 200px; 10 | } 11 | .deleteMemberButtonWrapper { 12 | margin-left: auto; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/Members/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps { 2 | members?: IProjectMember[]; 3 | loading?: boolean; 4 | onChange: (users: IProjectMember[]) => void; 5 | readonly?: boolean; 6 | isAdmin?: boolean; 7 | } 8 | 9 | export type TProjectMemberWithIndex = IProjectMember & { index: number }; 10 | export type TFormValues = { members: IProjectMember[] }; 11 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/hooks/useConfigProjectCliComand.ts: -------------------------------------------------------------------------------- 1 | import { useAppSelector } from 'hooks'; 2 | import { copyToClipboard } from 'libs'; 3 | 4 | import { selectAuthToken } from 'App/slice'; 5 | 6 | type Args = { 7 | projectName: string; 8 | }; 9 | export const useConfigProjectCliCommand = ({ projectName }: Args) => { 10 | const currentUserToken = useAppSelector(selectAuthToken); 11 | 12 | const cliCommand = `dstack project add --name ${projectName} --url ${location.origin} --token ${currentUserToken}`; 13 | 14 | const copyCliCommand = () => { 15 | copyToClipboard(cliCommand); 16 | }; 17 | 18 | return [cliCommand, copyCliCommand] as const; 19 | }; 20 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export { ProjectList } from './List'; 3 | export { ProjectDetails } from './Details'; 4 | export { ProjectSettings } from './Details/Settings'; 5 | export { ProjectAdd } from './Add'; 6 | 7 | export const Project: React.FC = () => { 8 | return null; 9 | }; 10 | -------------------------------------------------------------------------------- /frontend/src/pages/Project/utils.ts: -------------------------------------------------------------------------------- 1 | export const getProjectRoleByUserName = ( 2 | project: IProject, 3 | userName: IProjectMember['user']['username'], 4 | ): TProjectRole | null => { 5 | return project.members.find((m) => m.user.username === userName)?.project_role ?? null; 6 | }; 7 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Artifacts/styles.module.scss: -------------------------------------------------------------------------------- 1 | .artifacts { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Artifacts/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps extends Partial> { 2 | className?: string; 3 | } 4 | 5 | export interface ITableItem { 6 | name: string; 7 | path: string; 8 | type: string; 9 | size: number | null; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Jobs/Details/JobDetails/styles.module.scss: -------------------------------------------------------------------------------- 1 | .details { 2 | height: calc(100vh - 272px); 3 | display: flex; 4 | flex-direction: column; 5 | gap: 16px; 6 | 7 | & > [class^="awsui_layout"] { 8 | height: 100%; 9 | & > [class^="awsui_content"] { 10 | display: flex; 11 | flex-direction: column; 12 | gap: 20px; 13 | height: 100%; 14 | } 15 | } 16 | } 17 | 18 | .logs { 19 | flex-grow: 1; 20 | min-height: 0; 21 | max-height: calc(100vh - 380px); 22 | } 23 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Jobs/Details/styles.module.scss: -------------------------------------------------------------------------------- 1 | .page { 2 | height: 100%; 3 | 4 | & > [class^="awsui_layout"] { 5 | height: 100%; 6 | 7 | & > [class^="awsui_content"] { 8 | display: flex; 9 | flex-direction: column; 10 | gap: 20px; 11 | height: 100%; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Jobs/Metrics/consts.ts: -------------------------------------------------------------------------------- 1 | export const second = 1000; 2 | export const minute = 60 * second; 3 | export const hour = minute * 60; 4 | 5 | export const kByte = 1024; 6 | export const MByte = kByte * 1024; 7 | export const GByte = MByte * 1024; 8 | 9 | export const CPU_NUMS = 'cpus_detected_num'; 10 | export const ALL_CPU_USAGE = 'cpu_usage_percent'; 11 | export const MEMORY_WORKING_SET = 'memory_working_set_bytes'; 12 | export const MEMORY_TOTAL = 'memory_total_bytes'; 13 | export const EACH_GPU_USAGE_PREFIX = 'gpu_util_percent_gpu'; 14 | export const EACH_GPU_MEMORY_USAGE_PREFIX = 'gpu_memory_usage_bytes_gpu'; 15 | export const EACH_GPU_MEMORY_TOTAL = 'gpu_memory_total_bytes'; 16 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Logs/helpers.ts: -------------------------------------------------------------------------------- 1 | export const getJobSubmissionId = (run?: IRun): string | undefined => { 2 | if (!run) return; 3 | 4 | const lastJob = run.jobs[run.jobs.length - 1]; 5 | 6 | if (!lastJob) return; 7 | 8 | return lastJob.job_submissions[lastJob.job_submissions.length - 1]?.id; 9 | }; 10 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/Logs/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps { 2 | projectName: string; 3 | runName: string; 4 | jobSubmissionId?: string | null; 5 | className?: string; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/RunDetails/styles.module.scss: -------------------------------------------------------------------------------- 1 | .logs { 2 | flex-grow: 1; 3 | min-height: 0; 4 | max-height: calc(100vh - 480px); 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/Details/styles.module.scss: -------------------------------------------------------------------------------- 1 | .page { 2 | height: 100%; 3 | 4 | & [class^="awsui_tabs-content"] { 5 | display: none; 6 | } 7 | 8 | & > [class^="awsui_layout"] { 9 | height: 100%; 10 | 11 | & > [class^="awsui_content"] { 12 | display: flex; 13 | flex-direction: column; 14 | gap: 20px; 15 | height: 100%; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/List/Preferences/useRunListPreferences.ts: -------------------------------------------------------------------------------- 1 | import { CollectionPreferencesProps } from 'components'; 2 | 3 | import { useLocalStorageState } from 'hooks/useLocalStorageState'; 4 | 5 | import { DEFAULT_PREFERENCES } from './consts'; 6 | 7 | export const useRunListPreferences = () => { 8 | const [preferences, setPreferences] = useLocalStorageState( 9 | 'run-list-preferences', 10 | DEFAULT_PREFERENCES, 11 | ); 12 | 13 | return [preferences, setPreferences] as const; 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/List/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useColumnsDefinitions'; 2 | export * from './useStopRuns'; 3 | export * from './useDeleteRuns'; 4 | export * from './useDisabledStatesForButtons'; 5 | export * from './useEmptyMessages'; 6 | export * from './useFilters'; 7 | -------------------------------------------------------------------------------- /frontend/src/pages/Runs/index.ts: -------------------------------------------------------------------------------- 1 | export { RunList } from './List'; 2 | export { RunDetailsPage } from './Details'; 3 | export { RunDetails } from './Details/RunDetails'; 4 | export { JobMetrics } from './Details/Jobs/Metrics'; 5 | export { Logs } from './Details/Logs'; 6 | export { Artifacts } from './Details/Artifacts'; 7 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/Billing/PayForm/types.ts: -------------------------------------------------------------------------------- 1 | export type FormValues = { 2 | amount: number; 3 | }; 4 | 5 | export interface IProps { 6 | defaultValues?: Partial; 7 | isLoading?: boolean; 8 | onCancel?: () => void; 9 | onSubmit: (values: FormValues) => void; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/Billing/components/AmountField/styles.module.scss: -------------------------------------------------------------------------------- 1 | .amountInput { 2 | .prefix { 3 | position: absolute; 4 | z-index: 1; 5 | transform: translate(8px, 6px); 6 | pointer-events: none; 7 | } 8 | 9 | input { 10 | padding-left: 18px !important; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/CreditsHistory/Add/types.ts: -------------------------------------------------------------------------------- 1 | export type TFormValue = Pick; 2 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/CreditsHistory/constants.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export const PAYMENTS_INFO = { 3 | header:

Credits history

, 4 | body: ( 5 | <> 6 |

Available for only the global admin role

7 | 8 | ), 9 | }; 10 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/CreditsHistory/types.ts: -------------------------------------------------------------------------------- 1 | export interface IProps { 2 | username: string; 3 | } 4 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/Payments/types.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export interface IProps { 4 | payments: IPayment[]; 5 | emptyMessageContent?: React.ReactNode; 6 | isLoading?: boolean; 7 | tableHeaderContent?: React.ReactNode; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/Settings/styles.module.scss: -------------------------------------------------------------------------------- 1 | .token { 2 | display: flex; 3 | align-items: center; 4 | height: 20px; 5 | gap: 12px; 6 | 7 | button { 8 | padding: 0 !important; 9 | border: none !important; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Details/types.ts: -------------------------------------------------------------------------------- 1 | export enum UserDetailsTabTypeEnum { 2 | SETTINGS = 'settings', 3 | PROJECTS = 'projects', 4 | BILLING = 'billing', 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/pages/User/Form/types.ts: -------------------------------------------------------------------------------- 1 | export type TRoleSelectOption = { label: string; value: TProjectRole; disabled?: boolean }; 2 | export type TActiveSelectOption = { label: string; value: 'active' | 'inactive'; disabled?: boolean }; 3 | -------------------------------------------------------------------------------- /frontend/src/pages/User/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export { UserList } from './List'; 3 | export { UserDetails } from './Details'; 4 | export { UserEdit } from './Edit'; 5 | export { UserAdd } from './Add'; 6 | export { Add as CreditsHistoryAdd } from './Details/CreditsHistory/Add'; 7 | 8 | export const User: React.FC = () => { 9 | return null; 10 | }; 11 | -------------------------------------------------------------------------------- /frontend/src/pages/Volumes/List/styles.module.scss: -------------------------------------------------------------------------------- 1 | .filters { 2 | --select-width: calc((688px - 3 * 20px) / 2); 3 | display: flex; 4 | flex-wrap: wrap; 5 | gap: 0 20px; 6 | 7 | .select { 8 | width: var(--select-width, 30%); 9 | } 10 | 11 | .activeOnly { 12 | display: flex; 13 | align-items: center; 14 | padding-top: 26px; 15 | } 16 | 17 | .clear { 18 | padding-top: 26px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/pages/Volumes/index.ts: -------------------------------------------------------------------------------- 1 | export { VolumeList } from './List'; 2 | -------------------------------------------------------------------------------- /frontend/src/services/mainApi.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; 2 | 3 | import fetchBaseQueryHeaders from '../libs/fetchBaseQueryHeaders'; 4 | 5 | export const mainApi = createApi({ 6 | baseQuery: fetchBaseQuery({ 7 | prepareHeaders: fetchBaseQueryHeaders, 8 | }), 9 | endpoints: () => ({}), 10 | }); 11 | -------------------------------------------------------------------------------- /frontend/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /frontend/src/types/artifact.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare interface IArtifactFile { 3 | filepath: string, 4 | filesize_in_bytes: number | null 5 | } 6 | declare interface IArtifact { 7 | job_id: string, 8 | name: string, 9 | path: string, 10 | 11 | files: IArtifactFile[] 12 | } 13 | 14 | declare type TRequestArtifactListParams = { 15 | name: IProject['project_name'], 16 | run_name: IRun['run_name'], 17 | prefix: string, 18 | recursive?: boolean 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/types/bread-crums.d.ts: -------------------------------------------------------------------------------- 1 | declare type TBreadcrumb = { text: string, href: string } 2 | -------------------------------------------------------------------------------- /frontend/src/types/gateway.d.ts: -------------------------------------------------------------------------------- 1 | declare interface IGateway { 2 | backend: string, 3 | name: string, 4 | ip_address: string, 5 | instance_id: string, 6 | region:string 7 | wildcard_domain?: string 8 | default: boolean 9 | created_at?: number, 10 | } 11 | 12 | declare type TGatewayBackendsListResponse = { 13 | backend: string, 14 | regions: string[], 15 | }[] 16 | 17 | declare type TCreateGatewayParams = { 18 | backend_type: string, 19 | region?: string, 20 | } 21 | 22 | declare type TUpdateGatewayParams = { 23 | wildcard_domain?: string, 24 | default?: boolean, 25 | } 26 | -------------------------------------------------------------------------------- /frontend/src/types/i18next.d.ts: -------------------------------------------------------------------------------- 1 | import 'i18next'; 2 | 3 | declare module 'i18next' { 4 | interface CustomTypeOptions { 5 | returnNull: false; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/types/labmda-backend.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare interface ILambdaBackendValues { 3 | type: 'lambda', 4 | regions: TBackendValueField, 5 | } 6 | 7 | declare interface IBackendLambda { 8 | type: 'lambda', 9 | creds: { 10 | api_key: string, 11 | }, 12 | regions: string[], 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/types/log.d.ts: -------------------------------------------------------------------------------- 1 | declare interface ILogItem { 2 | log_source: 'stdout' | 'stderr' 3 | timestamp: string, 4 | message: string | Uint8Array, 5 | } 6 | 7 | declare type TRequestLogsParams = { 8 | project_name: IProject['project_name'], 9 | run_name: IRun['run_name'], 10 | job_submission_id: string 11 | start_time?: DateTime, 12 | end_time?: DateTime, 13 | descending?: boolean, 14 | limit?: number 15 | diagnose?: boolean 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/types/payment.d.ts: -------------------------------------------------------------------------------- 1 | declare interface IPayment { 2 | id: string, 3 | type: "invoice" | "manual", 4 | created_at: string, 5 | value: number, 6 | description: string 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/types/repo.d.ts: -------------------------------------------------------------------------------- 1 | enum RepoTypeEnum { 2 | REMOTE = 'remote', 3 | LOCAL = 'local', 4 | } 5 | 6 | declare interface IRemoteRunRepoData { 7 | repo_type: 'remote' 8 | repo_name: string 9 | repo_branch?: string 10 | repo_hash?: string 11 | repo_diff?: string 12 | repo_config_name?: string 13 | repo_config_email?: string 14 | } 15 | 16 | declare interface ILocalRunRepoData { 17 | repo_type: 'local' 18 | repo_dir: string 19 | } 20 | 21 | declare interface VirtualRunRepoData { 22 | repo_type: 'virtual' 23 | } 24 | 25 | declare interface IRepo { 26 | repo_id: string, 27 | repo_info: IRemoteRunRepoData | ILocalRunRepoData | VirtualRunRepoData 28 | } 29 | -------------------------------------------------------------------------------- /frontend/tests/__mocks__/MockStore.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import { store } from 'store'; 4 | 5 | type Props = { 6 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 7 | children: any; 8 | }; 9 | 10 | const MockStore = ({ children }: Props) => { 11 | return {children}; 12 | }; 13 | 14 | export default MockStore; 15 | -------------------------------------------------------------------------------- /frontend/tests/__mocks__/fileMock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 2 | // @ts-ignore 3 | module.exports = 'test-file-stub'; 4 | -------------------------------------------------------------------------------- /frontend/tests/__mocks__/shim.ts: -------------------------------------------------------------------------------- 1 | global.requestAnimationFrame = (callback): number => { 2 | setTimeout(callback, 0); 3 | return 0; 4 | }; 5 | -------------------------------------------------------------------------------- /frontend/tests/__mocks__/svgrMock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line 2 | export default 'SvgrURL'; 3 | export const ReactComponent = 'IconMock'; 4 | -------------------------------------------------------------------------------- /frontend/tests/setupEnzyme.ts: -------------------------------------------------------------------------------- 1 | import Enzyme from 'enzyme'; 2 | import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; 3 | 4 | Enzyme.configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /frontend/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { merge } = require("webpack-merge"); 2 | const base = require("./webpack/base"); 3 | const dev = require("./webpack/dev"); 4 | const prod = require("./webpack/prod"); 5 | 6 | const {isDev} = require('./webpack/env'); 7 | 8 | module.exports = isDev ? merge(base, dev) : merge(base, prod); 9 | -------------------------------------------------------------------------------- /gateway/README.md: -------------------------------------------------------------------------------- 1 | # `dstack-gateway` 2 | 3 | A thin package to deliver and install the gateway app. Expected to be merged with the `dstack` package in [#2251](https://github.com/dstackai/dstack/issues/2251). 4 | 5 | For details about gateways, see [contributing/PROXY.md](../contributing/PROXY.md). 6 | -------------------------------------------------------------------------------- /gateway/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "dstack-gateway" 7 | authors = [ 8 | { name = "dstack GmbH" }, 9 | ] 10 | requires-python = ">=3.10" 11 | dynamic = ["version"] 12 | dependencies = [ 13 | # release builds of dstack-gateway depend on a PyPI version of dstack instead 14 | "dstack[gateway] @ git+https://github.com/dstackai/dstack.git@master", 15 | ] 16 | 17 | [tool.setuptools.package-data] 18 | "dstack.gateway" = [ 19 | "resources/systemd/*", 20 | ] 21 | 22 | [tool.setuptools.dynamic] 23 | version = {attr = "dstack.gateway.version.__version__"} 24 | -------------------------------------------------------------------------------- /gateway/src/dstack/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/gateway/src/dstack/__init__.py -------------------------------------------------------------------------------- /gateway/src/dstack/gateway/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/gateway/src/dstack/gateway/__init__.py -------------------------------------------------------------------------------- /gateway/src/dstack/gateway/main.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.proxy.gateway.main import app as app 2 | -------------------------------------------------------------------------------- /gateway/src/dstack/gateway/resources/systemd/dstack.gateway.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=dstack gateway service 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/bin/sh {working_dir}/start.sh 7 | WorkingDirectory={working_dir} 8 | User=ubuntu 9 | Group=ubuntu 10 | Restart=always 11 | RestartSec=5 12 | 13 | [Install] 14 | WantedBy=default.target 15 | -------------------------------------------------------------------------------- /gateway/src/dstack/gateway/resources/systemd/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | root="$( cd -- "$(dirname "$0")" >/dev/null 2>&1; pwd -P )" 4 | 5 | if [ -f "$root/version" ]; then 6 | version=$(cat "$root/version") # blue/green 7 | else 8 | version="blue" 9 | echo "$version" > "$root/version" 10 | fi 11 | "$root/$version/bin/uvicorn" dstack.gateway.main:app 12 | -------------------------------------------------------------------------------- /gateway/src/dstack/gateway/systemd/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/gateway/src/dstack/gateway/systemd/__init__.py -------------------------------------------------------------------------------- /gateway/src/dstack/gateway/version.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.0.0" 2 | -------------------------------------------------------------------------------- /gateway/src/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/gateway/src/tests/__init__.py -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = src/tests 3 | addopts = 4 | --disable-socket 5 | --allow-hosts=127.0.0.1,localhost 6 | ; unix socket for Docker/testcontainers 7 | --allow-unix-socket 8 | markers = 9 | shim_version 10 | dockerized 11 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | target-version = "py39" 2 | line-length = 99 3 | 4 | [lint] 5 | select = ['E', 'F', 'I' ,'Q', 'W', 'PGH', 'FLY', 'S113'] 6 | ignore = [ 7 | 'E501', 8 | 'E712', 9 | ] 10 | 11 | [lint.isort] 12 | known-first-party = ["dstack"] 13 | known-third-party = ["mkdocs_gen_files", "datacrunch"] 14 | -------------------------------------------------------------------------------- /runner/internal/common/string.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import "strings" 4 | 5 | func IndexWithOffset(hay string, needle string, start int) int { 6 | idx := strings.Index(hay[start:], needle) 7 | if idx < 0 { 8 | return -1 9 | } 10 | return start + idx 11 | } 12 | -------------------------------------------------------------------------------- /runner/internal/executor/exec.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | import ( 4 | "path/filepath" 5 | "strings" 6 | 7 | "github.com/dstackai/dstack/runner/internal/gerrors" 8 | ) 9 | 10 | func joinRelPath(rootDir string, path string) (string, error) { 11 | if filepath.IsAbs(path) { 12 | return "", gerrors.New("path must be relative") 13 | } 14 | targetPath := filepath.Join(rootDir, path) 15 | if !strings.HasPrefix(targetPath, rootDir) { 16 | return "", gerrors.New("path is outside of the root directory") 17 | } 18 | return targetPath, nil 19 | } 20 | -------------------------------------------------------------------------------- /runner/internal/executor/exec_test.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestJoinRelPath(t *testing.T) { 10 | base := "/tmp/repo" 11 | var err error 12 | var res string 13 | 14 | res, err = joinRelPath(base, ".") 15 | assert.NoError(t, err) 16 | assert.Equal(t, "/tmp/repo", res) 17 | 18 | _, err = joinRelPath(base, "..") 19 | assert.Error(t, err) 20 | 21 | res, err = joinRelPath(base, "task") 22 | assert.NoError(t, err) 23 | assert.Equal(t, "/tmp/repo/task", res) 24 | 25 | _, err = joinRelPath(base, "/tmp/repo/task") 26 | assert.Error(t, err) 27 | } 28 | -------------------------------------------------------------------------------- /runner/internal/executor/lock.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | func (ex *RunExecutor) Lock() { 4 | ex.mu.Lock() 5 | } 6 | 7 | func (ex *RunExecutor) Unlock() { 8 | ex.mu.Unlock() 9 | } 10 | 11 | func (ex *RunExecutor) RLock() { 12 | ex.mu.RLock() 13 | } 14 | 15 | func (ex *RunExecutor) RUnlock() { 16 | ex.mu.RUnlock() 17 | } 18 | -------------------------------------------------------------------------------- /runner/internal/executor/states.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | const ( 4 | WaitSubmit = "wait_submit" 5 | WaitCode = "wait_code" 6 | WaitRun = "wait_run" 7 | ServeLogs = "serve_logs" 8 | WaitLogsFinished = "wait_logs_finished" 9 | ) 10 | -------------------------------------------------------------------------------- /runner/internal/shim/backends/base.go: -------------------------------------------------------------------------------- 1 | package backends 2 | 3 | type Backend interface { 4 | // GetRealDeviceName returns the real device name for the given volume ID and virtual device name. 5 | GetRealDeviceName(volumeID, deviceName string) (string, error) 6 | } 7 | -------------------------------------------------------------------------------- /scripts/build_frontend.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | script_path="$(realpath $0)" 4 | root_dir="$(dirname $(dirname $script_path))" 5 | 6 | cd $root_dir 7 | cd frontend 8 | npm install 9 | npm run build 10 | rm -rf ../src/dstack/_internal/server/statics 11 | cp -a build ../src/dstack/_internal/server/statics 12 | -------------------------------------------------------------------------------- /scripts/docs/gen_openapi_reference.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generates OpenAPI schema from dstack server app. 3 | """ 4 | 5 | import json 6 | 7 | import mkdocs_gen_files 8 | 9 | from dstack._internal.server.main import app 10 | from dstack._internal.settings import DSTACK_VERSION 11 | 12 | app.title = "OpenAPI Spec" 13 | app.servers = [ 14 | {"url": "http://localhost:3000", "description": "Local server"}, 15 | {"url": "https://sky.dstack.ai", "description": "Managed server"}, 16 | ] 17 | app.version = DSTACK_VERSION or "0.0.0" 18 | with mkdocs_gen_files.open("docs/reference/api/rest/openapi.json", "w") as f: 19 | json.dump(app.openapi(), f) 20 | -------------------------------------------------------------------------------- /scripts/packer/aws-vars-prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "ami_regions": "us-east-2,us-east-1,us-west-1,us-west-2,ca-central-1,eu-central-1,eu-west-1,eu-west-2,eu-west-3,eu-north-1,ap-southeast-1", 3 | "ami_groups": "all" 4 | } 5 | -------------------------------------------------------------------------------- /scripts/packer/config.pkr.hcl: -------------------------------------------------------------------------------- 1 | packer { 2 | required_plugins { 3 | yandex = { 4 | version = ">= 1.1.2" 5 | source = "github.com/hashicorp/yandex" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /scripts/packer/locals.pkr.hcl: -------------------------------------------------------------------------------- 1 | locals { 2 | clean_image_version = regex_replace(var.image_version, "[^a-z0-9-]", "-") 3 | image_name = "${var.build_prefix}dstack-${local.clean_image_version}" 4 | docker_version = "" 5 | cuda_drivers_version = "" 6 | } 7 | -------------------------------------------------------------------------------- /scripts/packer/provisioners/kernel/apt-upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Upgrade apt packages to latest versions. 4 | # 5 | 6 | set -e 7 | 8 | sudo apt-get update 9 | sudo DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Lock::Timeout=60 dist-upgrade -y -q 10 | -------------------------------------------------------------------------------- /scripts/packer/provisioners/pull-docker-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | IMAGES=" 6 | dstackai/${IMAGE_REPO}:py3.13-${IMAGE_VERSION}-cuda-12.1 7 | dstackai/${IMAGE_REPO}:py3.12-${IMAGE_VERSION}-cuda-12.1 8 | dstackai/${IMAGE_REPO}:py3.11-${IMAGE_VERSION}-cuda-12.1 9 | dstackai/${IMAGE_REPO}:py3.10-${IMAGE_VERSION}-cuda-12.1 10 | dstackai/${IMAGE_REPO}:py3.9-${IMAGE_VERSION}-cuda-12.1 11 | " 12 | echo "START pull image" 13 | for img in $IMAGES; do 14 | docker pull --platform linux/amd64 $img 15 | done 16 | echo "LIST installed images" 17 | docker image ls --all 18 | echo "END " 19 | -------------------------------------------------------------------------------- /scripts/packer/provisioners/wait-for-dpkg-lock.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Wait until another process releases an apt/dpkg lock. 4 | # 5 | # This is a hack and it might not work for all cases. A better way of handling 6 | # apt races is the `-o DPkg::Lock::Timeout=X` option, but it does not work for 7 | # `apt-get update`. 8 | # 9 | 10 | while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do 11 | sleep 1 12 | done 13 | -------------------------------------------------------------------------------- /scripts/packer/variables.pkr.hcl: -------------------------------------------------------------------------------- 1 | variable "build_prefix" { 2 | type = string 3 | default = "" 4 | } 5 | 6 | variable "image_version" { 7 | type = string 8 | } 9 | -------------------------------------------------------------------------------- /scripts/packer/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "docker_version": "27.1.1", 3 | "cuda_drivers_version": "535" 4 | } 5 | -------------------------------------------------------------------------------- /scripts/sqlite_to_psql.load: -------------------------------------------------------------------------------- 1 | LOAD DATABASE 2 | FROM {{SOURCE_PATH}} /* e.g. sqlite:///Users/me/.dstack/server/data/sqlite.db */ 3 | INTO {{TARGET_PATH}} /* e.g. postgresql://postgres:postgres@localhost:5432/postgres */ 4 | 5 | WITH preserve index names, data only 6 | 7 | EXCLUDING TABLE NAMES LIKE 'alembic_version' 8 | 9 | SET work_mem to '16MB', maintenance_work_mem to '512 MB'; 10 | -------------------------------------------------------------------------------- /src/dstack/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/cli/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/cli/commands/completion.py: -------------------------------------------------------------------------------- 1 | import argcomplete 2 | 3 | from dstack._internal.cli.commands import BaseCommand 4 | 5 | 6 | class CompletionCommand(BaseCommand): 7 | NAME = "completion" 8 | DESCRIPTION = "Generate shell completion scripts" 9 | 10 | def _register(self): 11 | super()._register() 12 | self._parser.add_argument( 13 | "shell", 14 | help="The shell to generate the completion script for", 15 | choices=["bash", "zsh"], 16 | ) 17 | 18 | def _command(self, args): 19 | super()._command(args) 20 | print(argcomplete.shellcode(["dstack"], shell=args.shell)) 21 | -------------------------------------------------------------------------------- /src/dstack/_internal/cli/commands/stats.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from dstack._internal.cli.commands.metrics import MetricsCommand 4 | from dstack._internal.utils.logging import get_logger 5 | 6 | logger = get_logger(__name__) 7 | 8 | 9 | class StatsCommand(MetricsCommand): 10 | NAME = "stats" 11 | 12 | def _command(self, args: argparse.Namespace): 13 | logger.warning("`dstack stats` is deprecated in favor of `dstack metrics`") 14 | super()._command(args) 15 | -------------------------------------------------------------------------------- /src/dstack/_internal/cli/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/cli/services/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/cli/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/cli/utils/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/compat.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | IS_WINDOWS = os.name == "nt" 4 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/aws/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/aws/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/azure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/azure/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/base/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/base/backend.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import ClassVar 3 | 4 | from dstack._internal.core.backends.base.compute import Compute 5 | from dstack._internal.core.models.backends.base import BackendType 6 | 7 | 8 | class Backend(ABC): 9 | TYPE: ClassVar[BackendType] 10 | # `COMPUTE_CLASS` is used to introspect compute features without initializing it. 11 | COMPUTE_CLASS: ClassVar[type[Compute]] 12 | 13 | @abstractmethod 14 | def compute(self) -> Compute: 15 | """ 16 | Returns Compute instance. 17 | """ 18 | pass 19 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/base/models.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | 4 | def fill_data(values: dict, filename_field: str = "filename", data_field: str = "data") -> dict: 5 | if values.get(data_field) is not None: 6 | return values 7 | if (filename := values.get(filename_field)) is None: 8 | raise ValueError(f"Either `{filename_field}` or `{data_field}` must be specified") 9 | try: 10 | with open(Path(filename).expanduser()) as f: 11 | values[data_field] = f.read() 12 | except OSError: 13 | raise ValueError(f"No such file {filename}") 14 | return values 15 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/cudo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/cudo/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/cudo/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.cudo.compute import CudoCompute 3 | from dstack._internal.core.backends.cudo.models import CudoConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class CudoBackend(Backend): 8 | TYPE = BackendType.CUDO 9 | COMPUTE_CLASS = CudoCompute 10 | 11 | def __init__(self, config: CudoConfig): 12 | self.config = config 13 | self._compute = CudoCompute(self.config) 14 | 15 | def compute(self) -> CudoCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/datacrunch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/datacrunch/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/datacrunch/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.datacrunch.compute import DataCrunchCompute 3 | from dstack._internal.core.backends.datacrunch.models import DataCrunchConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class DataCrunchBackend(Backend): 8 | TYPE = BackendType.DATACRUNCH 9 | COMPUTE_CLASS = DataCrunchCompute 10 | 11 | def __init__(self, config: DataCrunchConfig): 12 | self.config = config 13 | self._compute = DataCrunchCompute(self.config) 14 | 15 | def compute(self) -> DataCrunchCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/dstack/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/dstack/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/gcp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/gcp/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/gcp/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.gcp.compute import GCPCompute 3 | from dstack._internal.core.backends.gcp.models import GCPConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class GCPBackend(Backend): 8 | TYPE = BackendType.GCP 9 | COMPUTE_CLASS = GCPCompute 10 | 11 | def __init__(self, config: GCPConfig): 12 | self.config = config 13 | self._compute = GCPCompute(self.config) 14 | # self._check_credentials() 15 | 16 | def compute(self) -> GCPCompute: 17 | return self._compute 18 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/gcp/features/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/gcp/features/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/kubernetes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/kubernetes/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/kubernetes/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.kubernetes.compute import KubernetesCompute 3 | from dstack._internal.core.backends.kubernetes.models import KubernetesConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class KubernetesBackend(Backend): 8 | TYPE = BackendType.KUBERNETES 9 | COMPUTE_CLASS = KubernetesCompute 10 | 11 | def __init__(self, config: KubernetesConfig): 12 | self.config = config 13 | self._compute = KubernetesCompute(self.config) 14 | 15 | def compute(self) -> KubernetesCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/lambdalabs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/lambdalabs/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/lambdalabs/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.lambdalabs.compute import LambdaCompute 3 | from dstack._internal.core.backends.lambdalabs.models import LambdaConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class LambdaBackend(Backend): 8 | TYPE = BackendType.LAMBDA 9 | COMPUTE_CLASS = LambdaCompute 10 | 11 | def __init__(self, config: LambdaConfig): 12 | self.config = config 13 | self._compute = LambdaCompute(self.config) 14 | # self._check_credentials() 15 | 16 | def compute(self) -> LambdaCompute: 17 | return self._compute 18 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/local/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/local/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/local/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.local.compute import LocalCompute 3 | from dstack._internal.core.models.backends.base import BackendType 4 | 5 | 6 | class LocalBackend(Backend): 7 | TYPE = BackendType.LOCAL 8 | COMPUTE_CLASS = LocalCompute 9 | 10 | def __init__(self): 11 | self._compute = LocalCompute() 12 | 13 | def compute(self) -> LocalCompute: 14 | return self._compute 15 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/nebius/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/nebius/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/nebius/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.nebius.compute import NebiusCompute 3 | from dstack._internal.core.backends.nebius.models import NebiusConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class NebiusBackend(Backend): 8 | TYPE = BackendType.NEBIUS 9 | COMPUTE_CLASS = NebiusCompute 10 | 11 | def __init__(self, config: NebiusConfig): 12 | self.config = config 13 | self._compute = NebiusCompute(self.config) 14 | 15 | def compute(self) -> NebiusCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/oci/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/oci/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/oci/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.oci.compute import OCICompute 3 | from dstack._internal.core.backends.oci.models import OCIConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class OCIBackend(Backend): 8 | TYPE = BackendType.OCI 9 | COMPUTE_CLASS = OCICompute 10 | 11 | def __init__(self, config: OCIConfig): 12 | self.config = config 13 | self._compute = OCICompute(self.config) 14 | 15 | def compute(self) -> OCICompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/oci/exceptions.py: -------------------------------------------------------------------------------- 1 | from oci.exceptions import ( 2 | BaseRequestException, 3 | ClientError, 4 | CompositeOperationError, 5 | MultipartUploadError, 6 | ServiceError, 7 | ) 8 | 9 | any_oci_exception = ( 10 | BaseRequestException, 11 | ClientError, 12 | CompositeOperationError, 13 | MultipartUploadError, 14 | ServiceError, 15 | ) 16 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/remote/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/remote/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/runpod/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/runpod/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/runpod/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.runpod.compute import RunpodCompute 3 | from dstack._internal.core.backends.runpod.models import RunpodConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class RunpodBackend(Backend): 8 | TYPE = BackendType.RUNPOD 9 | COMPUTE_CLASS = RunpodCompute 10 | 11 | def __init__(self, config: RunpodConfig): 12 | self.config = config 13 | self._compute = RunpodCompute(self.config) 14 | 15 | def compute(self) -> RunpodCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/template/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/template/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/tensordock/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/tensordock/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/tensordock/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.tensordock.compute import TensorDockCompute 3 | from dstack._internal.core.backends.tensordock.models import TensorDockConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class TensorDockBackend(Backend): 8 | TYPE = BackendType.TENSORDOCK 9 | COMPUTE_CLASS = TensorDockCompute 10 | 11 | def __init__(self, config: TensorDockConfig): 12 | self.config = config 13 | self._compute = TensorDockCompute(self.config) 14 | 15 | def compute(self) -> TensorDockCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/vastai/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/vastai/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/vastai/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.vastai.compute import VastAICompute 3 | from dstack._internal.core.backends.vastai.models import VastAIConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class VastAIBackend(Backend): 8 | TYPE = BackendType.VASTAI 9 | COMPUTE_CLASS = VastAICompute 10 | 11 | def __init__(self, config: VastAIConfig): 12 | self.config = config 13 | self._compute = VastAICompute(self.config) 14 | 15 | def compute(self) -> VastAICompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/vultr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/backends/vultr/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/backends/vultr/backend.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.backends.base.backend import Backend 2 | from dstack._internal.core.backends.vultr.compute import VultrCompute 3 | from dstack._internal.core.backends.vultr.models import VultrConfig 4 | from dstack._internal.core.models.backends.base import BackendType 5 | 6 | 7 | class VultrBackend(Backend): 8 | TYPE = BackendType.VULTR 9 | COMPUTE_CLASS = VultrCompute 10 | 11 | def __init__(self, config: VultrConfig): 12 | self.config = config 13 | self._compute = VultrCompute(self.config) 14 | 15 | def compute(self) -> VultrCompute: 16 | return self._compute 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/consts.py: -------------------------------------------------------------------------------- 1 | # shim (runs on the host) HTTP API port 2 | DSTACK_SHIM_HTTP_PORT = 10998 3 | # runner (runs inside a container) HTTP API port 4 | DSTACK_RUNNER_HTTP_PORT = 10999 5 | # ssh server (runs alongside the runner inside a container) listen port 6 | DSTACK_RUNNER_SSH_PORT = 10022 7 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/models/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/backends/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/core/models/backends/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/config.py: -------------------------------------------------------------------------------- 1 | from pydantic.fields import Field 2 | from typing_extensions import Annotated, List, Optional 3 | 4 | from dstack._internal.core.models.common import CoreModel 5 | from dstack._internal.core.models.repos.base import RepoType 6 | 7 | 8 | class ProjectConfig(CoreModel): 9 | name: str 10 | url: str 11 | token: str 12 | default: Optional[bool] 13 | 14 | 15 | class RepoConfig(CoreModel): 16 | path: str 17 | repo_id: str 18 | repo_type: RepoType 19 | ssh_key_path: str 20 | 21 | 22 | class GlobalConfig(CoreModel): 23 | projects: Annotated[List[ProjectConfig], Field(description="The list of projects")] = [] 24 | repos: List[RepoConfig] = [] 25 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/logs.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from enum import Enum 3 | from typing import List 4 | 5 | from dstack._internal.core.models.common import CoreModel 6 | 7 | 8 | class LogProducer(Enum): 9 | RUNNER = "runner" 10 | JOB = "job" 11 | 12 | 13 | class LogEventSource(str, Enum): 14 | STDOUT = "stdout" 15 | STDERR = "stderr" 16 | 17 | 18 | class LogEvent(CoreModel): 19 | timestamp: datetime 20 | log_source: LogEventSource 21 | message: str 22 | 23 | 24 | class JobSubmissionLogs(CoreModel): 25 | logs: List[LogEvent] 26 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/metrics.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Any, List 3 | 4 | from dstack._internal.core.models.common import CoreModel 5 | 6 | 7 | class Metric(CoreModel): 8 | name: str 9 | timestamps: List[datetime] 10 | values: List[Any] 11 | 12 | 13 | class JobMetrics(CoreModel): 14 | metrics: List[Metric] 15 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/secrets.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.core.models.common import CoreModel 2 | 3 | 4 | class Secret(CoreModel): 5 | name: str 6 | value: str 7 | 8 | def __str__(self) -> str: 9 | return f'Secret(name="{self.name}", value={"*" * len(self.value)})' 10 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/models/server.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from dstack._internal.core.models.common import CoreModel 4 | 5 | 6 | class ServerInfo(CoreModel): 7 | server_version: Optional[str] 8 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/services/__init__.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from dstack._internal.core.errors import ServerClientError 4 | 5 | 6 | def validate_dstack_resource_name(resource_name: str): 7 | if not is_valid_dstack_resource_name(resource_name): 8 | raise ServerClientError("Resource name should match regex '^[a-z][a-z0-9-]{1,40}$'") 9 | 10 | 11 | def is_valid_dstack_resource_name(resource_name: str) -> bool: 12 | return re.match("^[a-z][a-z0-9-]{1,40}$", resource_name) is not None 13 | -------------------------------------------------------------------------------- /src/dstack/_internal/core/services/diff.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | # TODO: calculate nested diffs 7 | def diff_models(old: BaseModel, new: BaseModel) -> Dict[str, Any]: 8 | if type(old) is not type(new): 9 | raise TypeError("Both instances must be of the same Pydantic model class.") 10 | 11 | changes = {} 12 | for field in old.__fields__: 13 | old_value = getattr(old, field) 14 | new_value = getattr(new, field) 15 | if old_value != new_value: 16 | changes[field] = {"old": old_value, "new": new_value} 17 | 18 | return changes 19 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | dstack-proxy is a component responsible for proxying ingress HTTP traffic to 3 | services and models hosted by dstack. It can also perform load balancing, 4 | collect service usage stats, obtain SSL certificates, etc. 5 | 6 | This component can run as a standalone web application on a gateway instance or 7 | as part of the dstack-server web application. 8 | """ 9 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/gateway/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/const.py: -------------------------------------------------------------------------------- 1 | """Gateway-related constants useful in various dstack modules.""" 2 | 3 | from pathlib import Path 4 | 5 | DSTACK_DIR_ON_GATEWAY = Path("/home/ubuntu/dstack") 6 | SERVER_CONNECTIONS_DIR_ON_GATEWAY = DSTACK_DIR_ON_GATEWAY / "server-connections" 7 | PROXY_PORT_ON_GATEWAY = 8000 8 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/main.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from dstack._internal.proxy.gateway.app import make_app 4 | 5 | 6 | def configure_logging(level: int = logging.INFO): 7 | formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 8 | handler = logging.StreamHandler() 9 | handler.setFormatter(formatter) 10 | 11 | logger = logging.getLogger("dstack") 12 | logger.setLevel(level) 13 | logger.addHandler(handler) 14 | 15 | 16 | configure_logging(logging.DEBUG) 17 | app = make_app() 18 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/models.py: -------------------------------------------------------------------------------- 1 | """Things stored in GatewayProxyRepo in addition to those from BaseProxyRepo.""" 2 | 3 | from typing import Optional 4 | 5 | from pydantic import AnyHttpUrl 6 | 7 | from dstack._internal.proxy.lib.models import ImmutableModel 8 | 9 | 10 | class ModelEntrypoint(ImmutableModel): 11 | project_name: str 12 | domain: str 13 | https: bool 14 | 15 | 16 | class ACMESettings(ImmutableModel): 17 | server: Optional[AnyHttpUrl] = None 18 | eab_kid: Optional[str] = None 19 | eab_hmac_key: Optional[str] = None 20 | 21 | 22 | class GlobalProxyConfig(ImmutableModel): 23 | acme_settings: ACMESettings = ACMESettings() 24 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/repo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/gateway/repo/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf: -------------------------------------------------------------------------------- 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 | } 12 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/gateway/routers/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/routers/auth.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends 2 | 3 | from dstack._internal.proxy.lib.deps import ProxyAuth 4 | 5 | router = APIRouter() 6 | 7 | 8 | @router.get("/{project_name}", dependencies=[Depends(ProxyAuth(auto_enforce=True))]) 9 | async def get_auth(): 10 | return {"status": "ok"} 11 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/schemas/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/gateway/schemas/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/schemas/common.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class OkResponse(BaseModel): 5 | status: str = "ok" 6 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/schemas/config.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import AnyHttpUrl, BaseModel 4 | 5 | 6 | class ConfigRequest(BaseModel): 7 | acme_server: Optional[AnyHttpUrl] 8 | acme_eab_kid: Optional[str] 9 | acme_eab_hmac_key: Optional[str] 10 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/schemas/stats.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class Stat(BaseModel): 5 | requests: int 6 | request_time: float 7 | 8 | 9 | PerWindowStats = dict[int, Stat] # keys - length of time window in seconds 10 | 11 | 12 | class ServiceStats(BaseModel): 13 | project_name: str 14 | run_name: str 15 | stats: PerWindowStats 16 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/gateway/services/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/testing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/gateway/testing/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/gateway/testing/common.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import Union 3 | from unittest.mock import AsyncMock, MagicMock 4 | 5 | AnyMock = Union[MagicMock, AsyncMock] 6 | 7 | 8 | @dataclass 9 | class Mocks: 10 | reload_nginx: AnyMock 11 | run_certbot: AnyMock 12 | open_conn: AnyMock 13 | close_conn: AnyMock 14 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/auth.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class BaseProxyAuthProvider(ABC): 5 | @abstractmethod 6 | async def is_project_member(self, project_name: str, token: str) -> bool: 7 | pass 8 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/errors.py: -------------------------------------------------------------------------------- 1 | from fastapi import HTTPException, status 2 | 3 | 4 | class ProxyError(HTTPException): 5 | """Errors in dstack-proxy that are caused by and should be reported to the user""" 6 | 7 | def __init__(self, detail: str, code: int = status.HTTP_400_BAD_REQUEST) -> None: 8 | super().__init__(detail=detail, status_code=code) 9 | 10 | 11 | class UnexpectedProxyError(RuntimeError): 12 | """Internal errors in dstack-proxy that should have never happened""" 13 | 14 | pass 15 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/routers/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/schemas/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/schemas/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/services/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/services/model_proxy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/services/model_proxy/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/services/model_proxy/clients/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/services/model_proxy/clients/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/services/model_proxy/clients/base.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import AsyncIterator 3 | 4 | from dstack._internal.proxy.lib.schemas.model_proxy import ( 5 | ChatCompletionsChunk, 6 | ChatCompletionsRequest, 7 | ChatCompletionsResponse, 8 | ) 9 | 10 | 11 | class ChatCompletionsClient(ABC): 12 | @abstractmethod 13 | async def generate(self, request: ChatCompletionsRequest) -> ChatCompletionsResponse: 14 | pass 15 | 16 | @abstractmethod 17 | async def stream(self, request: ChatCompletionsRequest) -> AsyncIterator[ChatCompletionsChunk]: 18 | yield 19 | -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/testing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/proxy/lib/testing/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/proxy/lib/testing/auth.py: -------------------------------------------------------------------------------- 1 | from typing import Container, Optional 2 | 3 | from dstack._internal.proxy.lib.auth import BaseProxyAuthProvider 4 | 5 | 6 | class ProxyTestAuthProvider(BaseProxyAuthProvider): 7 | def __init__(self, project_to_tokens: Optional[dict[str, Container[str]]] = None) -> None: 8 | self._project_to_tokens = project_to_tokens or {} 9 | 10 | async def is_project_member(self, project_name: str, token: str) -> bool: 11 | return token in self._project_to_tokens.get(project_name, set()) 12 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/background/tasks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/background/tasks/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/main.py: -------------------------------------------------------------------------------- 1 | from dstack._internal.server.app import create_app, register_routes 2 | 3 | app = create_app() 4 | register_routes(app) 5 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/migrations/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/migrations/versions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/migrations/versions/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/migrations/versions/b88d55c2a07d_replace_instancestatus_ready.py: -------------------------------------------------------------------------------- 1 | """Replace InstanceStatus.READY with InstanceStatus.IDLE 2 | 3 | Revision ID: b88d55c2a07d 4 | Revises: ed0ca30e13bb 5 | Create Date: 2024-02-28 06:15:32.172109 6 | 7 | """ 8 | 9 | # revision identifiers, used by Alembic. 10 | revision = "b88d55c2a07d" 11 | down_revision = "ed0ca30e13bb" 12 | branch_labels = None 13 | depends_on = None 14 | 15 | 16 | def upgrade() -> None: 17 | pass 18 | 19 | 20 | def downgrade() -> None: 21 | pass 22 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/routers/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/routers/server.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | 3 | from dstack._internal import settings 4 | from dstack._internal.core.models.server import ServerInfo 5 | 6 | router = APIRouter( 7 | prefix="/api/server", 8 | tags=["server"], 9 | ) 10 | 11 | 12 | @router.post("/get_info") 13 | async def get_server_info() -> ServerInfo: 14 | return ServerInfo( 15 | server_version=settings.DSTACK_VERSION, 16 | ) 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/schemas/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/backends.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from dstack._internal.core.models.backends.base import BackendType 4 | from dstack._internal.core.models.common import CoreModel 5 | 6 | 7 | class DeleteBackendsRequest(CoreModel): 8 | backends_names: List[BackendType] 9 | 10 | 11 | class CreateBackendYAMLRequest(CoreModel): 12 | config_yaml: str 13 | 14 | 15 | class UpdateBackendYAMLRequest(CreateBackendYAMLRequest): 16 | pass 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/common.py: -------------------------------------------------------------------------------- 1 | from typing import Annotated 2 | 3 | from pydantic import Field 4 | 5 | from dstack._internal.core.models.common import CoreModel 6 | 7 | 8 | class RepoRequest(CoreModel): 9 | repo_id: Annotated[str, Field(description="A unique identifier of the repo")] 10 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/instances.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Optional 3 | from uuid import UUID 4 | 5 | from dstack._internal.core.models.common import CoreModel 6 | 7 | 8 | class ListInstancesRequest(CoreModel): 9 | project_names: Optional[list[str]] = None 10 | fleet_ids: Optional[list[UUID]] = None 11 | only_active: bool = False 12 | prev_created_at: Optional[datetime] = None 13 | prev_id: Optional[UUID] = None 14 | limit: int = 1000 15 | ascending: bool = False 16 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/logs.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Optional 3 | 4 | from pydantic import UUID4, Field 5 | 6 | from dstack._internal.core.models.common import CoreModel 7 | 8 | 9 | class PollLogsRequest(CoreModel): 10 | run_name: str 11 | job_submission_id: UUID4 12 | start_time: Optional[datetime] 13 | end_time: Optional[datetime] 14 | descending: bool = False 15 | limit: int = Field(100, ge=0, le=1000) 16 | diagnose: bool = False 17 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/projects.py: -------------------------------------------------------------------------------- 1 | from typing import Annotated, List 2 | 3 | from pydantic import Field 4 | 5 | from dstack._internal.core.models.common import CoreModel 6 | from dstack._internal.core.models.users import ProjectRole 7 | 8 | 9 | class CreateProjectRequest(CoreModel): 10 | project_name: str 11 | 12 | 13 | class DeleteProjectsRequest(CoreModel): 14 | projects_names: List[str] 15 | 16 | 17 | class MemberSetting(CoreModel): 18 | username: Annotated[ 19 | str, 20 | Field(description="The username or email of the user"), 21 | ] 22 | project_role: ProjectRole 23 | 24 | 25 | class SetProjectMembersRequest(CoreModel): 26 | members: List[MemberSetting] 27 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/secrets.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from dstack._internal.core.models.secrets import Secret 4 | from dstack._internal.server.schemas.common import RepoRequest 5 | 6 | 7 | class ListSecretsRequest(RepoRequest): 8 | pass 9 | 10 | 11 | class GetSecretsRequest(RepoRequest): 12 | pass 13 | 14 | 15 | class AddSecretRequest(RepoRequest): 16 | secret: Secret 17 | 18 | 19 | class DeleteSecretsRequest(RepoRequest): 20 | secrets_names: List[str] 21 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/schemas/users.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from dstack._internal.core.models.common import CoreModel 4 | from dstack._internal.core.models.users import GlobalRole 5 | 6 | 7 | class GetUserRequest(CoreModel): 8 | username: str 9 | 10 | 11 | class CreateUserRequest(CoreModel): 12 | username: str 13 | global_role: GlobalRole 14 | email: Optional[str] 15 | active: bool = True 16 | 17 | 18 | UpdateUserRequest = CreateUserRequest 19 | 20 | 21 | class RefreshTokenRequest(CoreModel): 22 | username: str 23 | 24 | 25 | class DeleteUsersRequest(CoreModel): 26 | users: List[str] 27 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/security/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/security/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/encryption/keys/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/encryption/keys/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/encryption/keys/base.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import ClassVar 3 | 4 | 5 | class EncryptionKey(ABC): 6 | TYPE: ClassVar[str] 7 | 8 | @property 9 | @abstractmethod 10 | def name(self) -> str: 11 | pass 12 | 13 | @abstractmethod 14 | def encrypt(self, plaintext: str) -> str: 15 | pass 16 | 17 | @abstractmethod 18 | def decrypt(self, ciphertext: str) -> str: 19 | pass 20 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/jobs/configurators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/jobs/configurators/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/jobs/configurators/extensions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/jobs/configurators/extensions/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/jobs/configurators/extensions/base.py: -------------------------------------------------------------------------------- 1 | from typing import Callable, List 2 | 3 | CommandsExtension = Callable[[], List[str]] 4 | 5 | 6 | def get_required_commands(executables: List[str]) -> CommandsExtension: 7 | def wrapper() -> List[str]: 8 | commands = [] 9 | for exe in executables: 10 | commands.append( 11 | f'((command -v {exe} > /dev/null) || (echo "{exe} is required" && exit 1))' 12 | ) 13 | return commands 14 | 15 | return wrapper 16 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/logging.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from dstack._internal.server.models import JobModel, RunModel 4 | 5 | 6 | def fmt(model: Union[RunModel, JobModel]) -> str: 7 | """Consistent string representation of a model for logging.""" 8 | if isinstance(model, RunModel): 9 | return f"run({model.id.hex[:6]}){model.run_name}" 10 | if isinstance(model, JobModel): 11 | return f"job({model.id.hex[:6]}){model.job_name}" 12 | return str(model) 13 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/proxy/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dependencies for dstack-proxy that allow it to run as part of dstack-server. 3 | """ 4 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/proxy/auth.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.ext.asyncio import AsyncSession 2 | 3 | from dstack._internal.proxy.lib.auth import BaseProxyAuthProvider 4 | from dstack._internal.server.security.permissions import is_project_member 5 | 6 | 7 | class ServerProxyAuthProvider(BaseProxyAuthProvider): 8 | def __init__(self, session: AsyncSession) -> None: 9 | self.session = session 10 | 11 | async def is_project_member(self, project_name: str, token: str) -> bool: 12 | return await is_project_member(self.session, project_name, token) 13 | -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/proxy/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/proxy/routers/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/proxy/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/proxy/services/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/services/runner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/services/runner/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/testing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/testing/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/server/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/server/utils/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/_internal/utils/__init__.py -------------------------------------------------------------------------------- /src/dstack/_internal/utils/env.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_bool(name: str, default: bool = False) -> bool: 5 | try: 6 | value = os.environ[name] 7 | except KeyError: 8 | return default 9 | value = value.lower() 10 | if value in ["0", "false", "off"]: 11 | return False 12 | if value in ["1", "true", "on"]: 13 | return True 14 | raise ValueError(f"Invalid bool value: {name}={value}") 15 | -------------------------------------------------------------------------------- /src/dstack/_internal/utils/json_schema.py: -------------------------------------------------------------------------------- 1 | def add_extra_schema_types(schema_property: dict, extra_types: list[dict]): 2 | if "allOf" in schema_property: 3 | refs = [schema_property.pop("allOf")[0]] 4 | elif "anyOf" in schema_property: 5 | refs = schema_property.pop("anyOf") 6 | else: 7 | refs = [{"type": schema_property.pop("type")}] 8 | refs.extend(extra_types) 9 | schema_property["anyOf"] = refs 10 | -------------------------------------------------------------------------------- /src/dstack/_internal/utils/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | 4 | def get_logger(name: str) -> logging.Logger: 5 | return logging.getLogger(name) 6 | -------------------------------------------------------------------------------- /src/dstack/api/server/_group.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | import requests 4 | from typing_extensions import Protocol 5 | 6 | 7 | class APIRequest(Protocol): 8 | def __call__( 9 | self, 10 | path: str, 11 | body: Optional[str] = None, 12 | raise_for_status: bool = True, 13 | method: str = "POST", 14 | **kwargs, 15 | ) -> requests.Response: 16 | pass 17 | 18 | 19 | class APIClientGroup: 20 | def __init__(self, _request: APIRequest): 21 | self._request = _request 22 | -------------------------------------------------------------------------------- /src/dstack/api/server/_logs.py: -------------------------------------------------------------------------------- 1 | from pydantic import parse_obj_as 2 | 3 | from dstack._internal.core.models.logs import JobSubmissionLogs 4 | from dstack._internal.server.schemas.logs import PollLogsRequest 5 | from dstack.api.server._group import APIClientGroup 6 | 7 | 8 | class LogsAPIClient(APIClientGroup): 9 | def poll(self, project_name: str, body: PollLogsRequest) -> JobSubmissionLogs: 10 | resp = self._request(f"/api/project/{project_name}/logs/poll", body=body.json()) 11 | return parse_obj_as(JobSubmissionLogs.__response__, resp.json()) 12 | -------------------------------------------------------------------------------- /src/dstack/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/core/__init__.py -------------------------------------------------------------------------------- /src/dstack/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | # ruff: noqa: F401 2 | from dstack._internal.core.models.fleets import FleetSpec 3 | from dstack._internal.core.models.gateways import GatewaySpec 4 | from dstack._internal.core.models.runs import RunSpec 5 | from dstack._internal.core.models.volumes import VolumeSpec 6 | from dstack.plugins._base import ApplyPolicy, Plugin 7 | from dstack.plugins._models import ApplySpec 8 | from dstack.plugins._utils import get_plugin_logger 9 | -------------------------------------------------------------------------------- /src/dstack/plugins/_models.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar 2 | 3 | from dstack._internal.core.models.fleets import FleetSpec 4 | from dstack._internal.core.models.gateways import GatewaySpec 5 | from dstack._internal.core.models.runs import RunSpec 6 | from dstack._internal.core.models.volumes import VolumeSpec 7 | 8 | ApplySpec = TypeVar("ApplySpec", RunSpec, FleetSpec, VolumeSpec, GatewaySpec) 9 | -------------------------------------------------------------------------------- /src/dstack/plugins/_utils.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from dstack._internal.utils.logging import get_logger 4 | 5 | 6 | def get_plugin_logger(name: str) -> logging.Logger: 7 | """ 8 | Use this function to set up loggers in plugins. 9 | 10 | Put at the top of the plugin modules: 11 | 12 | ``` 13 | from dstack.plugins import get_plugin_logger 14 | 15 | logger = get_plugin_logger(__name__) 16 | ``` 17 | 18 | """ 19 | return get_logger(f"dstack.plugins.{name}") 20 | -------------------------------------------------------------------------------- /src/dstack/plugins/builtin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/dstack/plugins/builtin/__init__.py -------------------------------------------------------------------------------- /src/dstack/plugins/builtin/rest_plugin/__init__.py: -------------------------------------------------------------------------------- 1 | # ruff: noqa: F401 2 | from dstack.plugins.builtin.rest_plugin._models import ( 3 | FleetSpecRequest, 4 | FleetSpecResponse, 5 | GatewaySpecRequest, 6 | GatewaySpecResponse, 7 | RunSpecRequest, 8 | RunSpecResponse, 9 | SpecApplyRequest, 10 | SpecApplyResponse, 11 | VolumeSpecRequest, 12 | VolumeSpecResponse, 13 | ) 14 | from dstack.plugins.builtin.rest_plugin._plugin import ( 15 | PLUGIN_SERVICE_URI_ENV_VAR_NAME, 16 | CustomApplyPolicy, 17 | RESTPlugin, 18 | ) 19 | -------------------------------------------------------------------------------- /src/dstack/version.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.0.0" 2 | __is_release__ = False 3 | base_image = "0.8" 4 | -------------------------------------------------------------------------------- /src/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/cli/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/cli/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/cli/commands/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/cli/commands/test_dstack.py: -------------------------------------------------------------------------------- 1 | from pytest import CaptureFixture 2 | 3 | from tests._internal.cli.common import run_dstack_cli 4 | 5 | 6 | class TestDstack: 7 | def test_prints_help_and_exists_with_0_exit_code(self, capsys: CaptureFixture): 8 | exit_code = run_dstack_cli([]) 9 | assert exit_code == 0 10 | assert capsys.readouterr().out.startswith("Usage: dstack [-h] [-v] COMMAND ...") 11 | -------------------------------------------------------------------------------- /src/tests/_internal/cli/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/cli/services/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/cli/services/configurators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/cli/services/configurators/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/aws/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/aws/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/azure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/azure/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/base/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/cudo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/cudo/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/datacrunch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/datacrunch/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/gcp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/gcp/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/kubernetes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/kubernetes/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/lambdalabs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/lambdalabs/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/oci/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/oci/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/runpod/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/runpod/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/tensordock/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/tensordock/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/vastai/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/vastai/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/backends/vultr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/backends/vultr/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/models/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/models/repos/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/models/repos/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/services/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/core/services/ssh/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/core/services/ssh/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/gateway/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/gateway/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/gateway/repo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/gateway/repo/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/gateway/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/gateway/routers/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/gateway/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/gateway/services/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/lib/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/proxy/lib/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/proxy/lib/routers/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/background/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/background/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/background/tasks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/background/tasks/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/routers/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/routers/test_server.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import patch 2 | 3 | import pytest 4 | from httpx import AsyncClient 5 | 6 | from dstack._internal import settings 7 | 8 | 9 | class TestGetInfo: 10 | @pytest.mark.asyncio 11 | async def test_returns_40x_if_not_authenticated(self, test_db, client: AsyncClient): 12 | with patch.object(settings, "DSTACK_VERSION", "0.18.10"): 13 | response = await client.post("/api/server/get_info") 14 | assert response.status_code == 200 15 | assert response.json() == {"server_version": "0.18.10"} 16 | -------------------------------------------------------------------------------- /src/tests/_internal/server/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/backends/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/backends/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/encryption/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/encryption/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/encryption/keys/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/encryption/keys/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/jobs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/jobs/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/jobs/configurators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/jobs/configurators/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/proxy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/proxy/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/proxy/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/proxy/routers/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/runner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/runner/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/services/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/services/services/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/server/test_app.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from fastapi.testclient import TestClient 3 | from httpx import AsyncClient 4 | from sqlalchemy.ext.asyncio import AsyncSession 5 | 6 | from dstack._internal.server.main import app 7 | 8 | client = TestClient(app) 9 | 10 | 11 | class TestIndex: 12 | @pytest.mark.ui 13 | @pytest.mark.asyncio 14 | @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True) 15 | async def test_returns_html(self, test_db, session: AsyncSession, client: AsyncClient): 16 | response = await client.get("/") 17 | assert response.status_code == 200 18 | assert response.content.startswith(b'<') 19 | -------------------------------------------------------------------------------- /src/tests/_internal/server/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/server/utils/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/_internal/utils/__init__.py -------------------------------------------------------------------------------- /src/tests/_internal/utils/test_event_loop.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from dstack._internal.utils.event_loop import DaemonEventLoop 4 | 5 | 6 | def test_daemon_event_loop(): 7 | q = asyncio.Queue() 8 | 9 | async def worker(i): 10 | await q.put(i) 11 | 12 | async def all_workers(): 13 | await asyncio.gather(*[worker(i) for i in range(3)]) 14 | 15 | loop = DaemonEventLoop() 16 | loop.await_(all_workers()) 17 | assert q.qsize() == 3 18 | assert {loop.await_(q.get()) for _ in range(3)} == {0, 1, 2} 19 | -------------------------------------------------------------------------------- /src/tests/_internal/utils/test_path.py: -------------------------------------------------------------------------------- 1 | from pathlib import PurePath 2 | 3 | import pytest 4 | 5 | from dstack._internal.utils.path import resolve_relative_path 6 | 7 | 8 | class TestResolveRelativePath: 9 | def test_abs_path(self): 10 | with pytest.raises(ValueError): 11 | resolve_relative_path("/tmp") 12 | 13 | def test_escape_repo(self): 14 | with pytest.raises(ValueError): 15 | resolve_relative_path("repo/../..") 16 | 17 | def test_normalize(self): 18 | assert resolve_relative_path("repo/./../repo2") == PurePath("repo2") 19 | -------------------------------------------------------------------------------- /src/tests/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/api/__init__.py -------------------------------------------------------------------------------- /src/tests/api/test_utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from dstack.api.utils import load_profile 4 | 5 | 6 | class TestLoadProfile: 7 | def test_loads_empty_profile_when_no_profiles(self, monkeypatch, tmpdir): 8 | test_dir = Path(tmpdir) 9 | repo_dir = test_dir / "repo" 10 | home_dir = test_dir / "home_dir" 11 | monkeypatch.setattr(Path, "home", lambda: home_dir) 12 | load_profile(repo_dir, profile_name=None) 13 | -------------------------------------------------------------------------------- /src/tests/plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dstackai/dstack/95650451e5156745cdefb01b59c5dbd356fbad7e/src/tests/plugins/__init__.py --------------------------------------------------------------------------------