urun-cli 0.6.3__tar.gz → 0.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {urun_cli-0.6.3 → urun_cli-0.7.1}/CHANGELOG.md +11 -0
  2. {urun_cli-0.6.3 → urun_cli-0.7.1}/PKG-INFO +110 -2
  3. {urun_cli-0.6.3 → urun_cli-0.7.1}/README.md +106 -1
  4. {urun_cli-0.6.3 → urun_cli-0.7.1}/pyproject.toml +13 -3
  5. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/catalog.py +60 -0
  6. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/cli.py +159 -31
  7. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/deps.py +394 -10
  8. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/dev.py +174 -20
  9. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/discovery.py +450 -2
  10. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/errors.py +54 -0
  11. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/manifest.py +63 -0
  12. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/retry.py +18 -0
  13. urun_cli-0.7.1/src/urun/rust.py +1501 -0
  14. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/scratch.py +389 -22
  15. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/serve.py +174 -10
  16. {urun_cli-0.6.3 → urun_cli-0.7.1}/.gitignore +0 -0
  17. {urun_cli-0.6.3 → urun_cli-0.7.1}/LICENSE +0 -0
  18. {urun_cli-0.6.3 → urun_cli-0.7.1}/SECURITY.md +0 -0
  19. {urun_cli-0.6.3 → urun_cli-0.7.1}/hatch_build.py +0 -0
  20. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/__init__.py +0 -0
  21. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/_bin/README.md +0 -0
  22. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/api.py +0 -0
  23. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/buildlogs.py +0 -0
  24. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/client_tokens.py +0 -0
  25. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/config.py +0 -0
  26. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/devconsole.py +0 -0
  27. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/devstream.py +0 -0
  28. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/fleet.py +0 -0
  29. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/frontend_launch.py +0 -0
  30. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/launch_auth.py +0 -0
  31. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/nodes.py +0 -0
  32. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/openai_proxy_bin.py +0 -0
  33. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/repo_deps.py +0 -0
  34. {urun_cli-0.6.3 → urun_cli-0.7.1}/src/urun/runtime_health.py +0 -0
@@ -1,3 +1,14 @@
1
+ ## 0.7.1
2
+
3
+ - `urun serve --warm N` — an idle replica floor on a serve deploy (the
4
+ catalog's `warm` marker for platform-operated shared endpoints; absent =
5
+ the unchanged scale-to-zero default). Pins `URUN_SERVE_WARM` into the
6
+ generated shim so the bundled app's `@app.function(warm=...)` reads it.
7
+ - `urun serve --exo-class / --exo-image` — pin a deploy's provider on the EXO rail.
8
+ - Deploy Python and Rust functions in one app release.
9
+ - Compat: bundle the proxy with the queued session identity; stop reporting
10
+ an unconverged roll as ready and stop dropping the server's error message.
11
+
1
12
  ## 0.6.3
2
13
 
3
14
  - Bump the vendored `urun-openai` binary pin to `@urun-sh/openai@0.5.0` — the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urun-cli
3
- Version: 0.6.3
3
+ Version: 0.7.1
4
4
  Summary: End-user CLI for deploying apps to urun
5
5
  Project-URL: Homepage, https://urun.sh
6
6
  Project-URL: Repository, https://github.com/urun-sh/urun-cli
@@ -18,11 +18,14 @@ Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Topic :: Software Development :: Build Tools
20
20
  Requires-Python: >=3.11
21
+ Provides-Extra: rust
22
+ Requires-Dist: tree-sitter-rust==0.24.0; extra == 'rust'
23
+ Requires-Dist: tree-sitter==0.25.2; extra == 'rust'
21
24
  Description-Content-Type: text/markdown
22
25
 
23
26
  # urun CLI
24
27
 
25
- Deploy Python apps to urun from your terminal.
28
+ Deploy Python and Rust (native SDK) apps to urun from your terminal.
26
29
 
27
30
  [![PyPI](https://img.shields.io/pypi/v/urun-cli.svg)](https://pypi.org/project/urun-cli/)
28
31
  [![Python](https://img.shields.io/pypi/pyversions/urun-cli.svg)](https://pypi.org/project/urun-cli/)
@@ -35,6 +38,15 @@ uv tool install urun-cli
35
38
  pip install urun-cli
36
39
  ```
37
40
 
41
+ For Rust (native SDK) deploys, install with the `[rust]` extra — see
42
+ [Deploy a Rust app (native SDK)](#deploy-a-rust-app-native-sdk):
43
+
44
+ ```bash
45
+ uv tool install "urun-cli[rust]"
46
+ # or
47
+ pip install "urun-cli[rust]"
48
+ ```
49
+
38
50
  The package installs the `urun` command:
39
51
 
40
52
  ```bash
@@ -154,6 +166,100 @@ Override the examples checkout with `--examples-root` or `URUN_EXAMPLES_ROOT`;
154
166
  override the session API with `--session-url` or `URUN_SESSION_BASE_URL`; pin
155
167
  the function with `--function` and the environment with `--environment`.
156
168
 
169
+ ## Deploy a Rust app (native SDK)
170
+
171
+ Rust apps use the native SDK crate `urun` and are declared by an inline module
172
+ owning `#[urun::app(name = "...")]` with nested `#[urun::function]` handlers.
173
+
174
+ The executable calls `urun::main!(app)` from `fn main()`. Each handler crosses
175
+ the `ctx.self_test(...)` barrier before accessing session state. The runnable
176
+ `native-echo` example below includes the complete lifecycle.
177
+
178
+ Install the CLI with the Rust parser extra (a plain install stays
179
+ dependency-free; the extra pulls the pinned `tree-sitter`/`tree-sitter-rust`
180
+ wheels used for static declaration extraction — no Rust toolchain needed):
181
+
182
+ ```bash
183
+ uv tool install "urun-cli[rust]"
184
+ # or
185
+ pip install "urun-cli[rust]"
186
+ ```
187
+
188
+ Deploy by pointing at the project's `Cargo.toml` (a `src/main.rs` or the
189
+ project directory also work):
190
+
191
+ ```bash
192
+ urun deploy path/to/project/Cargo.toml
193
+ ```
194
+
195
+ - **Vendor the SDK in-root.** The `urun` SDK crate is not published to
196
+ crates.io and the build environment has no private git credentials, so the
197
+ crate must ship inside your deploy root: reference it by a relative path
198
+ dependency (`urun = { path = "vendor/urun" }`) or as a member of the Cargo
199
+ workspace rooted there. Credential-free registry/git dependencies are fine.
200
+ - **`Cargo.lock` is mandatory.** The builder builds with `--locked`; a missing
201
+ lock file fails the deploy.
202
+ - The bundle is the full in-root Cargo workspace / path-dependency / resource
203
+ closure, minus `target/`, `.git`, and `.cargo/credentials{,.toml}`.
204
+
205
+ A runnable starting point is the SDK checkout's `examples/native-echo` app,
206
+ which vendors the SDK via a path dependency and deploys as-is:
207
+
208
+ ```bash
209
+ git clone git@github.com:urun-sh/urun-rs.git
210
+ urun deploy urun-rs/examples/native-echo
211
+ ```
212
+
213
+ ## Deploy a mixed Python + Rust app
214
+
215
+ ONE app can hold functions implemented in BOTH languages: one identity, one
216
+ release, the full function set replaced atomically on every deploy. Declare
217
+ the sources explicitly in the project's `pyproject.toml` — nothing is scanned
218
+ or inferred, so vendored SDK examples are never pulled into your app:
219
+
220
+ ```toml
221
+ # pyproject.toml
222
+ [tool.urun]
223
+ entrypoints = ["app.py", "native/src/main.rs"]
224
+ ```
225
+
226
+ Python functions register on one `App("mixed-app")`. Rust functions use
227
+ `#[urun::function(...)]` inside `#[urun::app(name = "mixed-app")]`.
228
+ The builder assembles both into one function registry: the language belongs
229
+ to the function, not to a separate app. See the runnable
230
+ [`examples/mixed-app`](https://github.com/urun-sh/urun-rs/tree/main/examples/mixed-app)
231
+ for complete Python and Rust implementations, including self-tests and calls
232
+ in both directions.
233
+
234
+ Deploy the whole app with any of these — each resolves the ENTIRE declared
235
+ app, so one component invocation never accidentally retires its sibling
236
+ functions:
237
+
238
+ ```bash
239
+ urun deploy . # the config directory
240
+ urun deploy pyproject.toml # the declaration itself
241
+ urun deploy app.py # a declared component
242
+ urun deploy native/src/main.rs
243
+ ```
244
+
245
+ - **One identity across all sources.** Python helpers may import the same
246
+ `App` object; Rust declarations use the same app-name literal. A different
247
+ App object, mismatched name, or duplicate function name is a hard error.
248
+ - **Declared paths stay in the config directory** (root-relative, no `..`
249
+ escapes, every declared file present). The bundle root may widen through
250
+ ordinary Cargo workspace resolution — e.g. a crate that is a member of a
251
+ wider workspace ships that whole workspace closure — and every entrypoint
252
+ and `manifest_path` rebases onto it.
253
+ - **Python dependencies stay Python.** The manifest's `deps` block is
254
+ resolved from the Python source exactly like a pure Python deploy
255
+ (`Dependencies(python=...)`, `requirements.txt`, `python_version`); the
256
+ Rust sources' `apt`/`build_deps` function options fold into the same lists.
257
+ - **Resources ride with their code** in both halves: the Python import/data
258
+ closure plus each Rust crate's full workspace/path closure and every
259
+ referenced `Cargo.lock`.
260
+
261
+ A runnable starting point is the SDK checkout's `examples/mixed-app` app.
262
+
157
263
  ## Serve a model from the catalog
158
264
 
159
265
  `urun serve` deploys a model straight from the urun model catalog — no app code
@@ -449,6 +555,8 @@ would fire kubectl at a cluster you are not looking at.
449
555
  | Entrypoint | Included source |
450
556
  | --- | --- |
451
557
  | `urun deploy app.py` | `app.py` and local Python files it imports |
558
+ | `urun deploy Cargo.toml` | The in-root Cargo workspace / path-dependency closure (see [Deploy a Rust app (native SDK)](#deploy-a-rust-app-native-sdk)). |
559
+ | `urun deploy .` / `pyproject.toml` | The whole explicitly-declared `[tool.urun]` app — Python + Rust sources, both closures (see [Deploy a mixed Python + Rust app](#deploy-a-mixed-python--rust-app)). A declared component (`app.py`, `native/src/main.rs`) resolves the same entire app. |
452
560
 
453
561
  Dependencies are declared in your urun app code. Project-level files such as
454
562
  `pyproject.toml` and `requirements.txt` are not uploaded as dependency
@@ -1,6 +1,6 @@
1
1
  # urun CLI
2
2
 
3
- Deploy Python apps to urun from your terminal.
3
+ Deploy Python and Rust (native SDK) apps to urun from your terminal.
4
4
 
5
5
  [![PyPI](https://img.shields.io/pypi/v/urun-cli.svg)](https://pypi.org/project/urun-cli/)
6
6
  [![Python](https://img.shields.io/pypi/pyversions/urun-cli.svg)](https://pypi.org/project/urun-cli/)
@@ -13,6 +13,15 @@ uv tool install urun-cli
13
13
  pip install urun-cli
14
14
  ```
15
15
 
16
+ For Rust (native SDK) deploys, install with the `[rust]` extra — see
17
+ [Deploy a Rust app (native SDK)](#deploy-a-rust-app-native-sdk):
18
+
19
+ ```bash
20
+ uv tool install "urun-cli[rust]"
21
+ # or
22
+ pip install "urun-cli[rust]"
23
+ ```
24
+
16
25
  The package installs the `urun` command:
17
26
 
18
27
  ```bash
@@ -132,6 +141,100 @@ Override the examples checkout with `--examples-root` or `URUN_EXAMPLES_ROOT`;
132
141
  override the session API with `--session-url` or `URUN_SESSION_BASE_URL`; pin
133
142
  the function with `--function` and the environment with `--environment`.
134
143
 
144
+ ## Deploy a Rust app (native SDK)
145
+
146
+ Rust apps use the native SDK crate `urun` and are declared by an inline module
147
+ owning `#[urun::app(name = "...")]` with nested `#[urun::function]` handlers.
148
+
149
+ The executable calls `urun::main!(app)` from `fn main()`. Each handler crosses
150
+ the `ctx.self_test(...)` barrier before accessing session state. The runnable
151
+ `native-echo` example below includes the complete lifecycle.
152
+
153
+ Install the CLI with the Rust parser extra (a plain install stays
154
+ dependency-free; the extra pulls the pinned `tree-sitter`/`tree-sitter-rust`
155
+ wheels used for static declaration extraction — no Rust toolchain needed):
156
+
157
+ ```bash
158
+ uv tool install "urun-cli[rust]"
159
+ # or
160
+ pip install "urun-cli[rust]"
161
+ ```
162
+
163
+ Deploy by pointing at the project's `Cargo.toml` (a `src/main.rs` or the
164
+ project directory also work):
165
+
166
+ ```bash
167
+ urun deploy path/to/project/Cargo.toml
168
+ ```
169
+
170
+ - **Vendor the SDK in-root.** The `urun` SDK crate is not published to
171
+ crates.io and the build environment has no private git credentials, so the
172
+ crate must ship inside your deploy root: reference it by a relative path
173
+ dependency (`urun = { path = "vendor/urun" }`) or as a member of the Cargo
174
+ workspace rooted there. Credential-free registry/git dependencies are fine.
175
+ - **`Cargo.lock` is mandatory.** The builder builds with `--locked`; a missing
176
+ lock file fails the deploy.
177
+ - The bundle is the full in-root Cargo workspace / path-dependency / resource
178
+ closure, minus `target/`, `.git`, and `.cargo/credentials{,.toml}`.
179
+
180
+ A runnable starting point is the SDK checkout's `examples/native-echo` app,
181
+ which vendors the SDK via a path dependency and deploys as-is:
182
+
183
+ ```bash
184
+ git clone git@github.com:urun-sh/urun-rs.git
185
+ urun deploy urun-rs/examples/native-echo
186
+ ```
187
+
188
+ ## Deploy a mixed Python + Rust app
189
+
190
+ ONE app can hold functions implemented in BOTH languages: one identity, one
191
+ release, the full function set replaced atomically on every deploy. Declare
192
+ the sources explicitly in the project's `pyproject.toml` — nothing is scanned
193
+ or inferred, so vendored SDK examples are never pulled into your app:
194
+
195
+ ```toml
196
+ # pyproject.toml
197
+ [tool.urun]
198
+ entrypoints = ["app.py", "native/src/main.rs"]
199
+ ```
200
+
201
+ Python functions register on one `App("mixed-app")`. Rust functions use
202
+ `#[urun::function(...)]` inside `#[urun::app(name = "mixed-app")]`.
203
+ The builder assembles both into one function registry: the language belongs
204
+ to the function, not to a separate app. See the runnable
205
+ [`examples/mixed-app`](https://github.com/urun-sh/urun-rs/tree/main/examples/mixed-app)
206
+ for complete Python and Rust implementations, including self-tests and calls
207
+ in both directions.
208
+
209
+ Deploy the whole app with any of these — each resolves the ENTIRE declared
210
+ app, so one component invocation never accidentally retires its sibling
211
+ functions:
212
+
213
+ ```bash
214
+ urun deploy . # the config directory
215
+ urun deploy pyproject.toml # the declaration itself
216
+ urun deploy app.py # a declared component
217
+ urun deploy native/src/main.rs
218
+ ```
219
+
220
+ - **One identity across all sources.** Python helpers may import the same
221
+ `App` object; Rust declarations use the same app-name literal. A different
222
+ App object, mismatched name, or duplicate function name is a hard error.
223
+ - **Declared paths stay in the config directory** (root-relative, no `..`
224
+ escapes, every declared file present). The bundle root may widen through
225
+ ordinary Cargo workspace resolution — e.g. a crate that is a member of a
226
+ wider workspace ships that whole workspace closure — and every entrypoint
227
+ and `manifest_path` rebases onto it.
228
+ - **Python dependencies stay Python.** The manifest's `deps` block is
229
+ resolved from the Python source exactly like a pure Python deploy
230
+ (`Dependencies(python=...)`, `requirements.txt`, `python_version`); the
231
+ Rust sources' `apt`/`build_deps` function options fold into the same lists.
232
+ - **Resources ride with their code** in both halves: the Python import/data
233
+ closure plus each Rust crate's full workspace/path closure and every
234
+ referenced `Cargo.lock`.
235
+
236
+ A runnable starting point is the SDK checkout's `examples/mixed-app` app.
237
+
135
238
  ## Serve a model from the catalog
136
239
 
137
240
  `urun serve` deploys a model straight from the urun model catalog — no app code
@@ -427,6 +530,8 @@ would fire kubectl at a cluster you are not looking at.
427
530
  | Entrypoint | Included source |
428
531
  | --- | --- |
429
532
  | `urun deploy app.py` | `app.py` and local Python files it imports |
533
+ | `urun deploy Cargo.toml` | The in-root Cargo workspace / path-dependency closure (see [Deploy a Rust app (native SDK)](#deploy-a-rust-app-native-sdk)). |
534
+ | `urun deploy .` / `pyproject.toml` | The whole explicitly-declared `[tool.urun]` app — Python + Rust sources, both closures (see [Deploy a mixed Python + Rust app](#deploy-a-mixed-python--rust-app)). A declared component (`app.py`, `native/src/main.rs`) resolves the same entire app. |
430
535
 
431
536
  Dependencies are declared in your urun app code. Project-level files such as
432
537
  `pyproject.toml` and `requirements.txt` are not uploaded as dependency
@@ -10,7 +10,7 @@ build-backend = "hatchling.build"
10
10
 
11
11
  [project]
12
12
  name = "urun-cli"
13
- # Cut the paused-function recovery fixes merged after v0.6.0.
13
+ # Cut the native Rust SDK deploy path (feature minor on 0.6.x).
14
14
  #
15
15
  # WHY THIS IS EDITED BY HAND. [tool.semantic_release] below is fully
16
16
  # configured -- conventional commit parser, version_toml pointing here, tag
@@ -19,8 +19,8 @@ name = "urun-cli"
19
19
  # READS this value and skips publishing when the matching tag already exists,
20
20
  # so every merge remains on the already-published version until this value is
21
21
  # advanced. Wiring semantic-release into CI remains separate work; this patch
22
- # bump is the minimal release unblock for the three post-v0.6.0 fixes.
23
- version = "0.6.3"
22
+ # bump is the minimal release unblock (post-v0.6.3 fixes + the Rust feature minor).
23
+ version = "0.7.1"
24
24
  description = "End-user CLI for deploying apps to urun"
25
25
  readme = "README.md"
26
26
  requires-python = ">=3.11"
@@ -49,6 +49,16 @@ Issues = "https://github.com/urun-sh/urun-cli/issues"
49
49
  urun = "urun.cli:main"
50
50
  urun-cli = "urun.cli:main"
51
51
 
52
+ [project.optional-dependencies]
53
+ # Rust app discovery (urun/rust.py) parses with the pinned native
54
+ # tree-sitter wheels; lazy-imported only for Rust deploys, so the ordinary
55
+ # wheel stays dependency-free. Pin advance = contract native_crate_baselines
56
+ # (tree-sitter 0.25.2 / tree-sitter-rust 0.24.0).
57
+ rust = [
58
+ "tree-sitter==0.25.2",
59
+ "tree-sitter-rust==0.24.0",
60
+ ]
61
+
52
62
  [dependency-groups]
53
63
  dev = [
54
64
  # The build backend, present in the dev env so tests can import hatch_build.py
@@ -104,6 +104,7 @@ ENGINE_DEPS: dict[str, list[str]] = {
104
104
  "echo-speak": [],
105
105
  "echo-video": [],
106
106
  "echo-video-diffusion": [],
107
+ "echo-t2av": [],
107
108
  "vllm": [
108
109
  "vllm==0.24.0",
109
110
  "arctic-inference==0.1.1",
@@ -386,6 +387,65 @@ ENGINE_DEPS: dict[str, list[str]] = {
386
387
  "huggingface_hub[hf_transfer]>=0.30.0,<1.0.0",
387
388
  "sentencepiece",
388
389
  ],
390
+ "t2av": [
391
+ "remote_pdb>=1.4",
392
+ "scipy>=1.14.1",
393
+ "six>=1.16.0",
394
+ "h5py>=3.12.1",
395
+ "requests>=2.32.2",
396
+ "numpy>=1.26,<2",
397
+ "transformers>=5.0.0",
398
+ "tokenizers>=0.20.1,<0.23",
399
+ "sentencepiece>=0.2.0",
400
+ "timm>=1.0.11",
401
+ "peft>=0.15.0",
402
+ "diffusers>=0.38.0",
403
+ "torch==2.12.0",
404
+ "torchvision",
405
+ "torchaudio",
406
+ "accelerate==1.0.1",
407
+ "opencv-python>=4.10,<5",
408
+ "pillow>=10.3.0",
409
+ "imageio>=2.36.0",
410
+ "imageio-ffmpeg>=0.5.1",
411
+ "einops",
412
+ "loguru",
413
+ "tqdm",
414
+ "PyYAML>=6.0.1",
415
+ "protobuf>=5.28.3",
416
+ "aiohttp",
417
+ "huggingface_hub",
418
+ "cloudpickle",
419
+ "omegaconf",
420
+ "gpustat",
421
+ "ninja",
422
+ "fastvideo-kernel==0.3.2; sys_platform == 'linux'",
423
+ ],
424
+ "ltx-realtime": [
425
+ "torch~=2.7",
426
+ "torchaudio",
427
+ "einops",
428
+ "numpy",
429
+ "av",
430
+ "transformers>=5.8.0,<5.15",
431
+ "safetensors",
432
+ "accelerate",
433
+ "scipy>=1.14",
434
+ "tqdm",
435
+ "pillow>=10.0.0",
436
+ "openimageio",
437
+ "cloudpickle>=3.1",
438
+ "huggingface_hub[hf_transfer]>=0.30.0,<1.0.0",
439
+ "sentencepiece",
440
+ "nvidia-cuda-nvcc==13.0.88",
441
+ "nvidia-cuda-crt==13.0.88",
442
+ "nvidia-cuda-cccl==13.0.85",
443
+ "nvidia-nvvm==13.0.88",
444
+ "nvidia-cuda-runtime==13.0.96",
445
+ "ninja",
446
+ "pip",
447
+ "nvidia-cutlass-dsl>=4.6.0.dev0,<5",
448
+ ],
389
449
  "media-transform": [
390
450
  "torch==2.6.0",
391
451
  "transformers==4.51.3",