From 1580a6a1fe5cef8b8b0db901f5041202b9c52d47 Mon Sep 17 00:00:00 2001 From: Connor Carpenter Date: Fri, 10 Jul 2026 12:23:44 -0700 Subject: [PATCH 1/6] feat(packages): add Python and Rust releases Signed-off-by: Connor Carpenter --- .github/workflows/packages.yml | 127 + .github/workflows/release.yml | 151 + .gitignore | 10 +- CHANGELOG.md | 20 + CONTRIBUTING.md | 27 +- Cargo.lock | 996 +++++++ Cargo.toml | 13 + README.md | 76 +- RELEASING.md | 75 + packages/python/README.md | 28 + packages/python/pyproject.toml | 39 + packages/python/src/openengine/__init__.py | 15 + packages/python/src/openengine/py.typed | 1 + packages/python/src/openengine/v1/__init__.py | 1 + .../python/src/openengine/v1/engine_pb2.py | 43 + .../python/src/openengine/v1/engine_pb2.pyi | 62 + .../python/src/openengine/v1/error_pb2.py | 39 + .../python/src/openengine/v1/error_pb2.pyi | 51 + .../openengine/v1/generation_params_pb2.py | 57 + .../openengine/v1/generation_params_pb2.pyi | 126 + .../src/openengine/v1/generation_pb2.py | 67 + .../src/openengine/v1/generation_pb2.pyi | 188 ++ packages/python/src/openengine/v1/kv_pb2.py | 70 + packages/python/src/openengine/v1/kv_pb2.pyi | 207 ++ .../python/src/openengine/v1/lifecycle_pb2.py | 59 + .../src/openengine/v1/lifecycle_pb2.pyi | 120 + packages/python/src/openengine/v1/lora_pb2.py | 48 + .../python/src/openengine/v1/lora_pb2.pyi | 53 + .../python/src/openengine/v1/model_pb2.py | 48 + .../python/src/openengine/v1/model_pb2.pyi | 118 + .../src/openengine/v1/observability_pb2.py | 57 + .../src/openengine/v1/observability_pb2.pyi | 116 + .../src/openengine/v1/openengine_pb2.py | 43 + .../src/openengine/v1/openengine_pb2.pyi | 11 + .../src/openengine/v1/openengine_pb2_grpc.py | 668 +++++ packages/python/tests/test_bindings.py | 41 + packages/rust/openengine-proto/Cargo.toml | 17 + packages/rust/openengine-proto/README.md | 24 + .../examples/cross_language_fixture.rs | 39 + .../src/generated/openengine.v1.rs | 2594 +++++++++++++++++ .../src/generated/openengine_descriptor.bin | Bin 0 -> 51923 bytes packages/rust/openengine-proto/src/lib.rs | 18 + .../rust/openengine-proto/tests/bindings.rs | 45 + proto/openengine/v1/README.md | 4 + scripts/check-generated.sh | 20 + scripts/check_release_version.py | 42 + scripts/cross_language_fixture.py | 40 + scripts/generate-python.sh | 34 + scripts/generate-rust.sh | 10 + scripts/test-cross-language.sh | 25 + tools/rust-codegen/Cargo.toml | 11 + tools/rust-codegen/src/main.rs | 39 + 52 files changed, 6811 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/packages.yml create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 RELEASING.md create mode 100644 packages/python/README.md create mode 100644 packages/python/pyproject.toml create mode 100644 packages/python/src/openengine/__init__.py create mode 100644 packages/python/src/openengine/py.typed create mode 100644 packages/python/src/openengine/v1/__init__.py create mode 100644 packages/python/src/openengine/v1/engine_pb2.py create mode 100644 packages/python/src/openengine/v1/engine_pb2.pyi create mode 100644 packages/python/src/openengine/v1/error_pb2.py create mode 100644 packages/python/src/openengine/v1/error_pb2.pyi create mode 100644 packages/python/src/openengine/v1/generation_params_pb2.py create mode 100644 packages/python/src/openengine/v1/generation_params_pb2.pyi create mode 100644 packages/python/src/openengine/v1/generation_pb2.py create mode 100644 packages/python/src/openengine/v1/generation_pb2.pyi create mode 100644 packages/python/src/openengine/v1/kv_pb2.py create mode 100644 packages/python/src/openengine/v1/kv_pb2.pyi create mode 100644 packages/python/src/openengine/v1/lifecycle_pb2.py create mode 100644 packages/python/src/openengine/v1/lifecycle_pb2.pyi create mode 100644 packages/python/src/openengine/v1/lora_pb2.py create mode 100644 packages/python/src/openengine/v1/lora_pb2.pyi create mode 100644 packages/python/src/openengine/v1/model_pb2.py create mode 100644 packages/python/src/openengine/v1/model_pb2.pyi create mode 100644 packages/python/src/openengine/v1/observability_pb2.py create mode 100644 packages/python/src/openengine/v1/observability_pb2.pyi create mode 100644 packages/python/src/openengine/v1/openengine_pb2.py create mode 100644 packages/python/src/openengine/v1/openengine_pb2.pyi create mode 100644 packages/python/src/openengine/v1/openengine_pb2_grpc.py create mode 100644 packages/python/tests/test_bindings.py create mode 100644 packages/rust/openengine-proto/Cargo.toml create mode 100644 packages/rust/openengine-proto/README.md create mode 100644 packages/rust/openengine-proto/examples/cross_language_fixture.rs create mode 100644 packages/rust/openengine-proto/src/generated/openengine.v1.rs create mode 100644 packages/rust/openengine-proto/src/generated/openengine_descriptor.bin create mode 100644 packages/rust/openengine-proto/src/lib.rs create mode 100644 packages/rust/openengine-proto/tests/bindings.rs create mode 100755 scripts/check-generated.sh create mode 100755 scripts/check_release_version.py create mode 100755 scripts/cross_language_fixture.py create mode 100755 scripts/generate-python.sh create mode 100755 scripts/generate-rust.sh create mode 100755 scripts/test-cross-language.sh create mode 100644 tools/rust-codegen/Cargo.toml create mode 100644 tools/rust-codegen/src/main.rs diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml new file mode 100644 index 0000000..ecb48ec --- /dev/null +++ b/.github/workflows/packages.yml @@ -0,0 +1,127 @@ +name: Packages + +on: + push: + branches: + - main + paths: + - "proto/**" + - "packages/**" + - "tools/rust-codegen/**" + - "scripts/**" + - "Cargo.toml" + - "Cargo.lock" + - ".github/workflows/packages.yml" + - ".github/workflows/release.yml" + pull_request: + paths: + - "proto/**" + - "packages/**" + - "tools/rust-codegen/**" + - "scripts/**" + - "Cargo.toml" + - "Cargo.lock" + - ".github/workflows/packages.yml" + - ".github/workflows/release.yml" + +permissions: + contents: read + +jobs: + generated: + name: Generated bindings + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install Python generator + run: python -m pip install grpcio-tools==1.81.1 + + - name: Check generated bindings + run: ./scripts/check-generated.sh + + python: + name: Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.14"] + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Install build tools + run: python -m pip install build==1.3.0 twine==6.2.0 + + - name: Build distributions + run: python -m build packages/python --outdir dist/python + + - name: Check distribution metadata + run: python -m twine check dist/python/* + + - name: Install wheel + run: python -m pip install dist/python/*.whl + + - name: Test installed bindings + run: python -m unittest discover --start-directory packages/python/tests + + rust: + name: Rust ${{ matrix.toolchain }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + toolchain: ["1.88.0", "stable"] + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + + - name: Test crate + run: cargo test --locked --package openengine-proto + + - name: Build publishable crate + run: cargo package --locked --package openengine-proto + + - name: List packaged files + run: cargo package --locked --package openengine-proto --list + + interoperability: + name: Python and Rust interoperability + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install Python package + run: python -m pip install ./packages/python + + - name: Test both serialization directions + run: ./scripts/test-cross-language.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6dbe5cc --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,151 @@ +name: Release + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +permissions: + contents: read + +jobs: + build: + name: Build and verify release + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Check release versions + run: python scripts/check_release_version.py "${GITHUB_REF_NAME}" + + - name: Lint schema + uses: bufbuild/buf-action@v1 + with: + version: "1.71.0" + lint: true + format: false + breaking: false + push: false + archive: false + pr_comment: false + + - name: Install Python tools + run: >- + python -m pip install + build==1.3.0 + grpcio-tools==1.81.1 + twine==6.2.0 + + - name: Check generated bindings + run: ./scripts/check-generated.sh + + - name: Test Rust crate + run: cargo test --locked --package openengine-proto + + - name: Build Rust crate + run: cargo package --locked --package openengine-proto + + - name: Build Python distributions + run: python -m build packages/python --outdir dist/python + + - name: Check Python distributions + run: python -m twine check dist/python/* + + - name: Install and test Python wheel + run: | + python -m pip install dist/python/*.whl + python -m unittest discover --start-directory packages/python/tests + + - name: Test cross-language serialization + run: ./scripts/test-cross-language.sh + + - name: Assemble release artifacts + run: | + mkdir -p dist/release + cp dist/python/* dist/release/ + cp target/package/openengine-proto-*.crate dist/release/ + cp packages/rust/openengine-proto/src/generated/openengine_descriptor.bin \ + "dist/release/openengine-${GITHUB_REF_NAME}-descriptor.bin" + tar --create --gzip \ + --file "dist/release/openengine-${GITHUB_REF_NAME}-proto.tar.gz" \ + --directory proto \ + openengine + cd dist/release + sha256sum openengine* > SHA256SUMS + + - name: Upload release artifacts + uses: actions/upload-artifact@v4 + with: + name: openengine-${{ github.ref_name }} + path: dist + if-no-files-found: error + + publish-python: + name: Publish Python package + needs: build + runs-on: ubuntu-latest + environment: release + permissions: + actions: read + contents: read + id-token: write + steps: + - name: Download release artifacts + uses: actions/download-artifact@v4 + with: + name: openengine-${{ github.ref_name }} + path: dist + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/python + + publish-rust: + name: Publish Rust crate + needs: build + runs-on: ubuntu-latest + environment: release + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Publish to crates.io + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: cargo publish --locked --package openengine-proto + + github-release: + name: Create GitHub release + needs: [publish-python, publish-rust] + runs-on: ubuntu-latest + permissions: + actions: read + contents: write + steps: + - name: Download release artifacts + uses: actions/download-artifact@v4 + with: + name: openengine-${{ github.ref_name }} + path: dist + + - name: Create release + env: + GH_TOKEN: ${{ github.token }} + run: >- + gh release create "${GITHUB_REF_NAME}" + dist/release/* + --generate-notes + --title "OpenEngine ${GITHUB_REF_NAME}" diff --git a/.gitignore b/.gitignore index ed1af5a..a681dea 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ __pycache__/ *.py[cod] -# Ignore generated Python gRPC stubs if the README example is run locally. -*_pb2.py -*_pb2_grpc.py +# Local Python environments and package artifacts +.venv/ +*.egg-info/ +dist/ + +# Rust build artifacts +target/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6d01c76 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ + + +# Changelog + +All notable changes to the OpenEngine schema and generated packages are +documented here. OpenEngine uses the same version for its Git tag, Python +distribution, and Rust crate. + +## [Unreleased] + +### Added + +- Generated Python protobuf and gRPC bindings. +- Generated Rust Prost and Tonic client/server bindings. +- Reproducible code generation, package CI, and tag-driven releases. + +[Unreleased]: https://github.com/ai-dynamo/openengine/commits/main diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 85ece56..1050dfb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,32 @@ sending a PR. - **Bugs / feedback / design questions**: open a [GitHub issue](https://github.com/ai-dynamo/openengine/issues). - **Pull requests**: open against `main`. Keep changes focused (one logical change per PR). -## Signing Your Work +## Development checks + +The schema under `proto/openengine/v1/` is the source of truth. Generated Python +and Rust bindings are checked in for package consumers and must be updated in +the same pull request as a schema change. + +```bash +buf build +buf lint + +python -m pip install grpcio-tools==1.81.1 +./scripts/generate-python.sh +./scripts/generate-rust.sh +./scripts/check-generated.sh + +cargo test --locked --package openengine-proto +cargo package --locked --package openengine-proto +python -m build packages/python --outdir dist/python +python -m twine check dist/python/* +./scripts/test-cross-language.sh +``` + +The Python generator and Rust code-generation toolchain are pinned. Do not edit +generated files by hand; update the schema or generator and regenerate them. + +## Signing your work We require that all contributors "sign off" on their commits. This certifies that you wrote the contribution, or otherwise have the right to submit it under the diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..51c63bc --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,996 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", +] + +[[package]] +name = "h2" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mio" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "openengine-proto" +version = "0.1.0" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tonic-prost", +] + +[[package]] +name = "openengine-rust-codegen" +version = "0.0.0" +dependencies = [ + "protoc-bin-vendored", + "tonic-prost-build", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" +dependencies = [ + "prost", +] + +[[package]] +name = "protoc-bin-vendored" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1c381df33c98266b5f08186583660090a4ffa0889e76c7e9a5e175f645a67fa" +dependencies = [ + "protoc-bin-vendored-linux-aarch_64", + "protoc-bin-vendored-linux-ppcle_64", + "protoc-bin-vendored-linux-s390_64", + "protoc-bin-vendored-linux-x86_32", + "protoc-bin-vendored-linux-x86_64", + "protoc-bin-vendored-macos-aarch_64", + "protoc-bin-vendored-macos-x86_64", + "protoc-bin-vendored-win32", +] + +[[package]] +name = "protoc-bin-vendored-linux-aarch_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c350df4d49b5b9e3ca79f7e646fde2377b199e13cfa87320308397e1f37e1a4c" + +[[package]] +name = "protoc-bin-vendored-linux-ppcle_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55a63e6c7244f19b5c6393f025017eb5d793fd5467823a099740a7a4222440c" + +[[package]] +name = "protoc-bin-vendored-linux-s390_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dba5565db4288e935d5330a07c264a4ee8e4a5b4a4e6f4e83fad824cc32f3b0" + +[[package]] +name = "protoc-bin-vendored-linux-x86_32" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8854774b24ee28b7868cd71dccaae8e02a2365e67a4a87a6cd11ee6cdbdf9cf5" + +[[package]] +name = "protoc-bin-vendored-linux-x86_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38b07546580df720fa464ce124c4b03630a6fb83e05c336fea2a241df7e5d78" + +[[package]] +name = "protoc-bin-vendored-macos-aarch_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89278a9926ce312e51f1d999fee8825d324d603213344a9a706daa009f1d8092" + +[[package]] +name = "protoc-bin-vendored-macos-x86_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81745feda7ccfb9471d7a4de888f0652e806d5795b61480605d4943176299756" + +[[package]] +name = "protoc-bin-vendored-win32" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95067976aca6421a523e491fce939a3e65249bac4b977adee0ee9771568e8aa3" + +[[package]] +name = "pulldown-cmark" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "regex" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "socket2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "tokio" +version = "1.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn", + "tempfile", + "tonic-build", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..eb92e3c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +members = [ + "packages/rust/openengine-proto", + "tools/rust-codegen", +] +resolver = "2" + +[workspace.package] +version = "0.1.0" +edition = "2021" +rust-version = "1.88" +license = "Apache-2.0" +repository = "https://github.com/ai-dynamo/openengine" diff --git a/README.md b/README.md index aadc6fc..f866df0 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ SPDX-License-Identifier: Apache-2.0 Why OpenEngine? · API reference · Canonical schema + · Generated packages · Contributing

@@ -43,6 +44,7 @@ SPDX-License-Identifier: Apache-2.0 - [Architecture](#architecture) - [Capabilities](#capabilities) - [Getting started](#getting-started) +- [Generated packages](#generated-packages) - [Project status](#project-status) - [Contributing](#contributing) - [Security](#security) @@ -134,31 +136,68 @@ buf lint Buf lint, Markdown lint, and link checks run in GitHub Actions for relevant pull requests. -### Generate Python bindings +### Regenerate package bindings -Use a proto3 toolchain with explicit-optional support (`protoc` 3.15 or newer). -The contract imports protobuf well-known types, so their include path must be -available to the compiler. +The repository checks in generated Python and Rust bindings so that package +users do not need a protobuf compiler. Contributors changing the schema must +regenerate both packages: ```bash -python -m pip install grpcio-tools +python -m pip install grpcio-tools==1.81.1 +./scripts/generate-python.sh +./scripts/generate-rust.sh +./scripts/check-generated.sh +``` + +Other protobuf-supported languages can generate clients and servers from the +same canonical package. + +## Generated packages -OUT_DIR=/tmp/openengine-python -mkdir -p "$OUT_DIR" +Each OpenEngine release publishes Python and Rust bindings from the same schema +and version tag. The artifacts contain generated code; installing them does not +run Buf or `protoc`. -PROTO_INCLUDE=$(python -c \ - 'import grpc_tools, os; print(os.path.join(os.path.dirname(grpc_tools.__file__), "_proto"))') +### Python -python -m grpc_tools.protoc \ - -I proto \ - -I "$PROTO_INCLUDE" \ - --python_out="$OUT_DIR" \ - --grpc_python_out="$OUT_DIR" \ - proto/openengine/v1/*.proto +```bash +pip install openengine-proto ``` -Other protobuf-supported languages can generate clients and servers from the -same canonical package. +```python +import grpc + +from openengine.v1.generation_pb2 import GenerateRequest +from openengine.v1.openengine_pb2_grpc import OpenEngineStub + +channel = grpc.aio.insecure_channel("localhost:50051") +engine = OpenEngineStub(channel) +request = GenerateRequest(request_id="example", model="model", prompt="Hello") +``` + +### Rust + +```bash +cargo add openengine-proto +``` + +```rust +use openengine_proto::openengine::v1::{ + open_engine_client::OpenEngineClient, + GenerateRequest, +}; +``` + +The package version is the immutable `schema_release` identifier. Both packages +also expose schema revision `1`; a client should still inspect `EngineInfo` to +determine the revision and compatibility advertised by a running engine. + +| Package release | Protobuf package | Schema revision | +| --------------- | ---------------- | --------------- | +| `0.1.x` | `openengine.v1` | `1` | + +See [`RELEASING.md`](RELEASING.md) for the coordinated release process and +[`CHANGELOG.md`](CHANGELOG.md) for schema and package changes. ## Project status @@ -189,7 +228,8 @@ git commit --signoff -m "docs: describe the change" Please validate protobuf changes with Buf and keep [`proto/openengine/v1/`](proto/openengine/v1/) and [`docs/api.md`](docs/api.md) -synchronized. +synchronized. Changes to the schema must also regenerate and commit both +language packages. ## Security diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..96d7f27 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,75 @@ + + +# Releasing OpenEngine + +OpenEngine publishes the canonical schema and generated Python and Rust +bindings from the same `vMAJOR.MINOR.PATCH` tag. Releases are immutable and all +published artifacts must use the same version. + +## One-time repository configuration + +Before the first release: + +1. Register `openengine-proto` on PyPI and crates.io. +2. Configure a PyPI Trusted Publisher for the `Release` workflow, the + `publish-python` job, and the `release` GitHub environment. +3. Add a crates.io publishing token as the `CARGO_REGISTRY_TOKEN` environment + secret. +4. Protect the `release` GitHub environment with the desired approval policy. +5. Add the appropriate project owners on both registries. + +The PyPI job uses OpenID Connect and does not require a stored PyPI token. + +## Prepare a release + +1. Choose the release version and update both version declarations: + - `packages/python/pyproject.toml` under `[project]`. + - `Cargo.toml` under `[workspace.package]`. +2. Move the relevant entries from `Unreleased` in `CHANGELOG.md` into a section + named for the version and release date. +3. Install the pinned Python generator and regenerate bindings: + + ```bash + python -m pip install grpcio-tools==1.81.1 + ./scripts/generate-python.sh + ./scripts/generate-rust.sh + ``` + +4. Run the package checks: + + ```bash + ./scripts/check-generated.sh + cargo test --locked --package openengine-proto + cargo package --locked --package openengine-proto + python -m build packages/python --outdir dist/python + python -m twine check dist/python/* + ./scripts/test-cross-language.sh + ``` + +5. Open and merge the release-preparation pull request. + +## Publish + +Create and push a signed tag from the release commit: + +```bash +python scripts/check_release_version.py v0.1.0 +git tag --sign v0.1.0 -m "OpenEngine v0.1.0" +git push origin v0.1.0 +``` + +The `Release` workflow validates the schema, regenerates and tests both +packages, publishes them, and creates a GitHub release containing: + +- The Python wheel and source distribution. +- The packaged Rust crate. +- The canonical proto source archive. +- The complete protobuf descriptor set. +- SHA-256 checksums. + +If publication fails after one registry accepts a package, do not overwrite or +delete that artifact. Fix the workflow and rerun only if the remaining steps +are safe, or prepare a new patch release. diff --git a/packages/python/README.md b/packages/python/README.md new file mode 100644 index 0000000..6d6a089 --- /dev/null +++ b/packages/python/README.md @@ -0,0 +1,28 @@ + + +# OpenEngine Python bindings + +Generated protobuf messages and gRPC client/server bindings for the +[`openengine.v1`](https://github.com/ai-dynamo/openengine/tree/main/proto/openengine/v1) +protocol. + +```bash +pip install openengine-proto +``` + +```python +import grpc + +from openengine.v1.generation_pb2 import GenerateRequest +from openengine.v1.openengine_pb2_grpc import OpenEngineStub + +channel = grpc.aio.insecure_channel("localhost:50051") +engine = OpenEngineStub(channel) +request = GenerateRequest(request_id="example", model="model", prompt="Hello") +``` + +The package contains generated code. Applications do not need Buf, `protoc`, +or `grpcio-tools`. diff --git a/packages/python/pyproject.toml b/packages/python/pyproject.toml new file mode 100644 index 0000000..830f4cb --- /dev/null +++ b/packages/python/pyproject.toml @@ -0,0 +1,39 @@ +[build-system] +requires = ["hatchling>=1.27,<2"] +build-backend = "hatchling.build" + +[project] +name = "openengine-proto" +version = "0.1.0" +description = "Generated Python bindings for the OpenEngine gRPC protocol" +readme = "README.md" +requires-python = ">=3.10" +license = "Apache-2.0" +authors = [{ name = "OpenEngine contributors" }] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Software Development :: Libraries", + "Topic :: System :: Distributed Computing", +] +dependencies = [ + "grpcio>=1.81.1,<2", + "protobuf>=6.33.5,<8", +] + +[project.urls] +Documentation = "https://github.com/ai-dynamo/openengine/tree/main/docs" +Issues = "https://github.com/ai-dynamo/openengine/issues" +Repository = "https://github.com/ai-dynamo/openengine" + +[tool.hatch.build.targets.sdist] +include = [ + "/README.md", + "/pyproject.toml", + "/src", +] + +[tool.hatch.build.targets.wheel] +packages = ["src/openengine"] diff --git a/packages/python/src/openengine/__init__.py b/packages/python/src/openengine/__init__.py new file mode 100644 index 0000000..3dc6063 --- /dev/null +++ b/packages/python/src/openengine/__init__.py @@ -0,0 +1,15 @@ +"""Generated Python bindings for the OpenEngine protocol.""" + +from importlib.metadata import PackageNotFoundError, version + +try: + __version__ = version("openengine-proto") +except PackageNotFoundError: + __version__ = "0.0.0+local" + +SCHEMA_REVISION = 1 +SCHEMA_RELEASE = ( + "unreleased" if __version__ == "0.0.0+local" else f"v{__version__}" +) + +__all__ = ["SCHEMA_RELEASE", "SCHEMA_REVISION", "__version__"] diff --git a/packages/python/src/openengine/py.typed b/packages/python/src/openengine/py.typed new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/packages/python/src/openengine/py.typed @@ -0,0 +1 @@ + diff --git a/packages/python/src/openengine/v1/__init__.py b/packages/python/src/openengine/v1/__init__.py new file mode 100644 index 0000000..32b0339 --- /dev/null +++ b/packages/python/src/openengine/v1/__init__.py @@ -0,0 +1 @@ +"""The generated ``openengine.v1`` protobuf package.""" diff --git a/packages/python/src/openengine/v1/engine_pb2.py b/packages/python/src/openengine/v1/engine_pb2.py new file mode 100644 index 0000000..30df65b --- /dev/null +++ b/packages/python/src/openengine/v1/engine_pb2.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/engine.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/engine.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aopenengine/v1/engine.proto\x12\ropenengine.v1\x1a\x16openengine/v1/kv.proto\"\x16\n\x14GetEngineInfoRequest\"\xce\x02\n\nEngineInfo\x12\x13\n\x0b\x65ngine_name\x18\x01 \x01(\t\x12\x16\n\x0e\x65ngine_version\x18\x02 \x01(\t\x12\'\n\x04role\x18\x03 \x01(\x0e\x32\x19.openengine.v1.EngineRole\x12\x13\n\x0binstance_id\x18\x04 \x01(\t\x12\x18\n\x10supported_models\x18\x05 \x03(\t\x12\x33\n\x0bparallelism\x18\x06 \x01(\x0b\x32\x1e.openengine.v1.ParallelismInfo\x12\x34\n\x0ckv_connector\x18\x07 \x01(\x0b\x32\x1e.openengine.v1.KvConnectorInfo\x12\x17\n\x0fschema_revision\x18\x08 \x01(\r\x12\x1f\n\x17minimum_client_revision\x18\t \x01(\r\x12\x16\n\x0eschema_release\x18\n \x01(\t\"\xc1\x02\n\x0fParallelismInfo\x12!\n\x14tensor_parallel_size\x18\x01 \x01(\rH\x00\x88\x01\x01\x12#\n\x16pipeline_parallel_size\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1f\n\x12\x64\x61ta_parallel_size\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x04 \x01(\rH\x03\x88\x01\x01\x12%\n\x18\x64\x61ta_parallel_start_rank\x18\x05 \x01(\rH\x04\x88\x01\x01\x42\x17\n\x15_tensor_parallel_sizeB\x19\n\x17_pipeline_parallel_sizeB\x15\n\x13_data_parallel_sizeB\x15\n\x13_data_parallel_rankB\x1b\n\x19_data_parallel_start_rank*v\n\nEngineRole\x12\x1b\n\x17\x45NGINE_ROLE_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x45NGINE_ROLE_AGGREGATED\x10\x01\x12\x17\n\x13\x45NGINE_ROLE_PREFILL\x10\x02\x12\x16\n\x12\x45NGINE_ROLE_DECODE\x10\x03\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.engine_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_ENGINEROLE']._serialized_start=754 + _globals['_ENGINEROLE']._serialized_end=872 + _globals['_GETENGINEINFOREQUEST']._serialized_start=69 + _globals['_GETENGINEINFOREQUEST']._serialized_end=91 + _globals['_ENGINEINFO']._serialized_start=94 + _globals['_ENGINEINFO']._serialized_end=428 + _globals['_PARALLELISMINFO']._serialized_start=431 + _globals['_PARALLELISMINFO']._serialized_end=752 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/engine_pb2.pyi b/packages/python/src/openengine/v1/engine_pb2.pyi new file mode 100644 index 0000000..e07e53b --- /dev/null +++ b/packages/python/src/openengine/v1/engine_pb2.pyi @@ -0,0 +1,62 @@ +from openengine.v1 import kv_pb2 as _kv_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class EngineRole(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ENGINE_ROLE_UNSPECIFIED: _ClassVar[EngineRole] + ENGINE_ROLE_AGGREGATED: _ClassVar[EngineRole] + ENGINE_ROLE_PREFILL: _ClassVar[EngineRole] + ENGINE_ROLE_DECODE: _ClassVar[EngineRole] +ENGINE_ROLE_UNSPECIFIED: EngineRole +ENGINE_ROLE_AGGREGATED: EngineRole +ENGINE_ROLE_PREFILL: EngineRole +ENGINE_ROLE_DECODE: EngineRole + +class GetEngineInfoRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class EngineInfo(_message.Message): + __slots__ = ("engine_name", "engine_version", "role", "instance_id", "supported_models", "parallelism", "kv_connector", "schema_revision", "minimum_client_revision", "schema_release") + ENGINE_NAME_FIELD_NUMBER: _ClassVar[int] + ENGINE_VERSION_FIELD_NUMBER: _ClassVar[int] + ROLE_FIELD_NUMBER: _ClassVar[int] + INSTANCE_ID_FIELD_NUMBER: _ClassVar[int] + SUPPORTED_MODELS_FIELD_NUMBER: _ClassVar[int] + PARALLELISM_FIELD_NUMBER: _ClassVar[int] + KV_CONNECTOR_FIELD_NUMBER: _ClassVar[int] + SCHEMA_REVISION_FIELD_NUMBER: _ClassVar[int] + MINIMUM_CLIENT_REVISION_FIELD_NUMBER: _ClassVar[int] + SCHEMA_RELEASE_FIELD_NUMBER: _ClassVar[int] + engine_name: str + engine_version: str + role: EngineRole + instance_id: str + supported_models: _containers.RepeatedScalarFieldContainer[str] + parallelism: ParallelismInfo + kv_connector: _kv_pb2.KvConnectorInfo + schema_revision: int + minimum_client_revision: int + schema_release: str + def __init__(self, engine_name: _Optional[str] = ..., engine_version: _Optional[str] = ..., role: _Optional[_Union[EngineRole, str]] = ..., instance_id: _Optional[str] = ..., supported_models: _Optional[_Iterable[str]] = ..., parallelism: _Optional[_Union[ParallelismInfo, _Mapping]] = ..., kv_connector: _Optional[_Union[_kv_pb2.KvConnectorInfo, _Mapping]] = ..., schema_revision: _Optional[int] = ..., minimum_client_revision: _Optional[int] = ..., schema_release: _Optional[str] = ...) -> None: ... + +class ParallelismInfo(_message.Message): + __slots__ = ("tensor_parallel_size", "pipeline_parallel_size", "data_parallel_size", "data_parallel_rank", "data_parallel_start_rank") + TENSOR_PARALLEL_SIZE_FIELD_NUMBER: _ClassVar[int] + PIPELINE_PARALLEL_SIZE_FIELD_NUMBER: _ClassVar[int] + DATA_PARALLEL_SIZE_FIELD_NUMBER: _ClassVar[int] + DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] + DATA_PARALLEL_START_RANK_FIELD_NUMBER: _ClassVar[int] + tensor_parallel_size: int + pipeline_parallel_size: int + data_parallel_size: int + data_parallel_rank: int + data_parallel_start_rank: int + def __init__(self, tensor_parallel_size: _Optional[int] = ..., pipeline_parallel_size: _Optional[int] = ..., data_parallel_size: _Optional[int] = ..., data_parallel_rank: _Optional[int] = ..., data_parallel_start_rank: _Optional[int] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/error_pb2.py b/packages/python/src/openengine/v1/error_pb2.py new file mode 100644 index 0000000..907d15a --- /dev/null +++ b/packages/python/src/openengine/v1/error_pb2.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/error.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/error.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19openengine/v1/error.proto\x12\ropenengine.v1\x1a\x1cgoogle/protobuf/struct.proto\"\xb3\x01\n\x0b\x45ngineError\x12&\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x18.openengine.v1.ErrorCode\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\tretryable\x18\x03 \x01(\x08\x12\x1b\n\x0eretry_after_ms\x18\x04 \x01(\x04H\x00\x88\x01\x01\x12(\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructB\x11\n\x0f_retry_after_ms*\x9d\x03\n\tErrorCode\x12\x1a\n\x16\x45RROR_CODE_UNSPECIFIED\x10\x00\x12\x1f\n\x1b\x45RROR_CODE_INVALID_ARGUMENT\x10\x01\x12\"\n\x1e\x45RROR_CODE_UNSUPPORTED_FEATURE\x10\x02\x12\x1c\n\x18\x45RROR_CODE_ROLE_MISMATCH\x10\x03\x12\x1e\n\x1a\x45RROR_CODE_MODEL_NOT_FOUND\x10\x04\x12\x19\n\x15\x45RROR_CODE_OVERLOADED\x10\x05\x12 \n\x1c\x45RROR_CODE_REQUEST_NOT_FOUND\x10\x06\x12 \n\x1c\x45RROR_CODE_DUPLICATE_REQUEST\x10\x07\x12#\n\x1f\x45RROR_CODE_KV_SESSION_NOT_FOUND\x10\x08\x12!\n\x1d\x45RROR_CODE_KV_TRANSFER_FAILED\x10\t\x12\x18\n\x14\x45RROR_CODE_CANCELLED\x10\n\x12\x17\n\x13\x45RROR_CODE_DRAINING\x10\x0b\x12\x17\n\x13\x45RROR_CODE_INTERNAL\x10\x0c\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.error_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_ERRORCODE']._serialized_start=257 + _globals['_ERRORCODE']._serialized_end=670 + _globals['_ENGINEERROR']._serialized_start=75 + _globals['_ENGINEERROR']._serialized_end=254 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/error_pb2.pyi b/packages/python/src/openengine/v1/error_pb2.pyi new file mode 100644 index 0000000..4933b85 --- /dev/null +++ b/packages/python/src/openengine/v1/error_pb2.pyi @@ -0,0 +1,51 @@ +from google.protobuf import struct_pb2 as _struct_pb2 +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ErrorCode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ERROR_CODE_UNSPECIFIED: _ClassVar[ErrorCode] + ERROR_CODE_INVALID_ARGUMENT: _ClassVar[ErrorCode] + ERROR_CODE_UNSUPPORTED_FEATURE: _ClassVar[ErrorCode] + ERROR_CODE_ROLE_MISMATCH: _ClassVar[ErrorCode] + ERROR_CODE_MODEL_NOT_FOUND: _ClassVar[ErrorCode] + ERROR_CODE_OVERLOADED: _ClassVar[ErrorCode] + ERROR_CODE_REQUEST_NOT_FOUND: _ClassVar[ErrorCode] + ERROR_CODE_DUPLICATE_REQUEST: _ClassVar[ErrorCode] + ERROR_CODE_KV_SESSION_NOT_FOUND: _ClassVar[ErrorCode] + ERROR_CODE_KV_TRANSFER_FAILED: _ClassVar[ErrorCode] + ERROR_CODE_CANCELLED: _ClassVar[ErrorCode] + ERROR_CODE_DRAINING: _ClassVar[ErrorCode] + ERROR_CODE_INTERNAL: _ClassVar[ErrorCode] +ERROR_CODE_UNSPECIFIED: ErrorCode +ERROR_CODE_INVALID_ARGUMENT: ErrorCode +ERROR_CODE_UNSUPPORTED_FEATURE: ErrorCode +ERROR_CODE_ROLE_MISMATCH: ErrorCode +ERROR_CODE_MODEL_NOT_FOUND: ErrorCode +ERROR_CODE_OVERLOADED: ErrorCode +ERROR_CODE_REQUEST_NOT_FOUND: ErrorCode +ERROR_CODE_DUPLICATE_REQUEST: ErrorCode +ERROR_CODE_KV_SESSION_NOT_FOUND: ErrorCode +ERROR_CODE_KV_TRANSFER_FAILED: ErrorCode +ERROR_CODE_CANCELLED: ErrorCode +ERROR_CODE_DRAINING: ErrorCode +ERROR_CODE_INTERNAL: ErrorCode + +class EngineError(_message.Message): + __slots__ = ("code", "message", "retryable", "retry_after_ms", "details") + CODE_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + RETRYABLE_FIELD_NUMBER: _ClassVar[int] + RETRY_AFTER_MS_FIELD_NUMBER: _ClassVar[int] + DETAILS_FIELD_NUMBER: _ClassVar[int] + code: ErrorCode + message: str + retryable: bool + retry_after_ms: int + details: _struct_pb2.Struct + def __init__(self, code: _Optional[_Union[ErrorCode, str]] = ..., message: _Optional[str] = ..., retryable: _Optional[bool] = ..., retry_after_ms: _Optional[int] = ..., details: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/generation_params_pb2.py b/packages/python/src/openengine/v1/generation_params_pb2.py new file mode 100644 index 0000000..c0ac8c6 --- /dev/null +++ b/packages/python/src/openengine/v1/generation_params_pb2.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/generation_params.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/generation_params.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%openengine/v1/generation_params.proto\x12\ropenengine.v1\x1a\x16openengine/v1/kv.proto\"\x17\n\x08TokenIds\x12\x0b\n\x03ids\x18\x01 \x03(\r\"\x80\x03\n\x0eSamplingParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x01H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x12\n\x05min_p\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x1e\n\x11\x66requency_penalty\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x1d\n\x10presence_penalty\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12\x1f\n\x12repetition_penalty\x18\x07 \x01(\x01H\x06\x88\x01\x01\x12\x11\n\x04seed\x18\x08 \x01(\x04H\x07\x88\x01\x01\x12\x1a\n\rnum_sequences\x18\t \x01(\rH\x08\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\x08\n\x06_min_pB\x14\n\x12_frequency_penaltyB\x13\n\x11_presence_penaltyB\x15\n\x13_repetition_penaltyB\x07\n\x05_seedB\x10\n\x0e_num_sequences\"\xfb\x01\n\x0fStoppingOptions\x12\x17\n\nmax_tokens\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x17\n\nmin_tokens\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x30\n\nconditions\x18\x03 \x03(\x0b\x32\x1c.openengine.v1.StopCondition\x12\x17\n\nignore_eos\x18\x04 \x01(\x08H\x02\x88\x01\x01\x12#\n\x16include_stop_in_output\x18\x05 \x01(\x08H\x03\x88\x01\x01\x42\r\n\x0b_max_tokensB\r\n\x0b_min_tokensB\r\n\x0b_ignore_eosB\x19\n\x17_include_stop_in_output\"\xd3\x02\n\x0fResponseOptions\x12#\n\x16return_prompt_logprobs\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x41\n\x11prompt_candidates\x18\x02 \x01(\x0b\x32&.openengine.v1.CandidateTokenSelection\x12#\n\x16return_output_logprobs\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x41\n\x11output_candidates\x18\x04 \x01(\x0b\x32&.openengine.v1.CandidateTokenSelection\x12!\n\x14prompt_logprob_start\x18\x05 \x01(\rH\x02\x88\x01\x01\x42\x19\n\x17_return_prompt_logprobsB\x19\n\x17_return_output_logprobsB\x17\n\x15_prompt_logprob_start\"\x92\x01\n\x17\x43\x61ndidateTokenSelection\x12\x0f\n\x05top_n\x18\x01 \x01(\rH\x00\x12,\n\ttoken_ids\x18\x02 \x01(\x0b\x32\x17.openengine.v1.TokenIdsH\x00\x12+\n\x03\x61ll\x18\x03 \x01(\x0b\x32\x1c.openengine.v1.AllCandidatesH\x00\x42\x0b\n\tselection\"\x0f\n\rAllCandidates\"\xd3\x01\n\tKvOptions\x12,\n\x07session\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRef\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x02 \x01(\rH\x00\x88\x01\x01\x12 \n\x13\x62ypass_prefix_cache\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x17\n\ncache_salt\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\x15\n\x13_data_parallel_rankB\x16\n\x14_bypass_prefix_cacheB\r\n\x0b_cache_salt\"J\n\rStopCondition\x12\x13\n\tstop_text\x18\x01 \x01(\tH\x00\x12\x17\n\rstop_token_id\x18\x02 \x01(\rH\x00\x42\x0b\n\tcondition\"\xf3\x01\n\x0eGuidedDecoding\x12\x15\n\x0bjson_schema\x18\x01 \x01(\tH\x00\x12\x0f\n\x05regex\x18\x02 \x01(\tH\x00\x12\x16\n\x0c\x65\x62nf_grammar\x18\x03 \x01(\tH\x00\x12\x18\n\x0estructural_tag\x18\x04 \x01(\tH\x00\x12\x31\n\x06\x63hoice\x18\x05 \x01(\x0b\x32\x1f.openengine.v1.ChoiceConstraintH\x00\x12:\n\x0bjson_object\x18\x06 \x01(\x0b\x32#.openengine.v1.JsonObjectConstraintH\x00\x12\x0f\n\x07\x62\x61\x63kend\x18\x07 \x01(\tB\x07\n\x05guide\"#\n\x10\x43hoiceConstraint\x12\x0f\n\x07\x63hoices\x18\x01 \x03(\t\"\x16\n\x14JsonObjectConstraintb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.generation_params_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_TOKENIDS']._serialized_start=80 + _globals['_TOKENIDS']._serialized_end=103 + _globals['_SAMPLINGPARAMS']._serialized_start=106 + _globals['_SAMPLINGPARAMS']._serialized_end=490 + _globals['_STOPPINGOPTIONS']._serialized_start=493 + _globals['_STOPPINGOPTIONS']._serialized_end=744 + _globals['_RESPONSEOPTIONS']._serialized_start=747 + _globals['_RESPONSEOPTIONS']._serialized_end=1086 + _globals['_CANDIDATETOKENSELECTION']._serialized_start=1089 + _globals['_CANDIDATETOKENSELECTION']._serialized_end=1235 + _globals['_ALLCANDIDATES']._serialized_start=1237 + _globals['_ALLCANDIDATES']._serialized_end=1252 + _globals['_KVOPTIONS']._serialized_start=1255 + _globals['_KVOPTIONS']._serialized_end=1466 + _globals['_STOPCONDITION']._serialized_start=1468 + _globals['_STOPCONDITION']._serialized_end=1542 + _globals['_GUIDEDDECODING']._serialized_start=1545 + _globals['_GUIDEDDECODING']._serialized_end=1788 + _globals['_CHOICECONSTRAINT']._serialized_start=1790 + _globals['_CHOICECONSTRAINT']._serialized_end=1825 + _globals['_JSONOBJECTCONSTRAINT']._serialized_start=1827 + _globals['_JSONOBJECTCONSTRAINT']._serialized_end=1849 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/generation_params_pb2.pyi b/packages/python/src/openengine/v1/generation_params_pb2.pyi new file mode 100644 index 0000000..79dc46e --- /dev/null +++ b/packages/python/src/openengine/v1/generation_params_pb2.pyi @@ -0,0 +1,126 @@ +from openengine.v1 import kv_pb2 as _kv_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class TokenIds(_message.Message): + __slots__ = ("ids",) + IDS_FIELD_NUMBER: _ClassVar[int] + ids: _containers.RepeatedScalarFieldContainer[int] + def __init__(self, ids: _Optional[_Iterable[int]] = ...) -> None: ... + +class SamplingParams(_message.Message): + __slots__ = ("temperature", "top_p", "top_k", "min_p", "frequency_penalty", "presence_penalty", "repetition_penalty", "seed", "num_sequences") + TEMPERATURE_FIELD_NUMBER: _ClassVar[int] + TOP_P_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + MIN_P_FIELD_NUMBER: _ClassVar[int] + FREQUENCY_PENALTY_FIELD_NUMBER: _ClassVar[int] + PRESENCE_PENALTY_FIELD_NUMBER: _ClassVar[int] + REPETITION_PENALTY_FIELD_NUMBER: _ClassVar[int] + SEED_FIELD_NUMBER: _ClassVar[int] + NUM_SEQUENCES_FIELD_NUMBER: _ClassVar[int] + temperature: float + top_p: float + top_k: int + min_p: float + frequency_penalty: float + presence_penalty: float + repetition_penalty: float + seed: int + num_sequences: int + def __init__(self, temperature: _Optional[float] = ..., top_p: _Optional[float] = ..., top_k: _Optional[int] = ..., min_p: _Optional[float] = ..., frequency_penalty: _Optional[float] = ..., presence_penalty: _Optional[float] = ..., repetition_penalty: _Optional[float] = ..., seed: _Optional[int] = ..., num_sequences: _Optional[int] = ...) -> None: ... + +class StoppingOptions(_message.Message): + __slots__ = ("max_tokens", "min_tokens", "conditions", "ignore_eos", "include_stop_in_output") + MAX_TOKENS_FIELD_NUMBER: _ClassVar[int] + MIN_TOKENS_FIELD_NUMBER: _ClassVar[int] + CONDITIONS_FIELD_NUMBER: _ClassVar[int] + IGNORE_EOS_FIELD_NUMBER: _ClassVar[int] + INCLUDE_STOP_IN_OUTPUT_FIELD_NUMBER: _ClassVar[int] + max_tokens: int + min_tokens: int + conditions: _containers.RepeatedCompositeFieldContainer[StopCondition] + ignore_eos: bool + include_stop_in_output: bool + def __init__(self, max_tokens: _Optional[int] = ..., min_tokens: _Optional[int] = ..., conditions: _Optional[_Iterable[_Union[StopCondition, _Mapping]]] = ..., ignore_eos: _Optional[bool] = ..., include_stop_in_output: _Optional[bool] = ...) -> None: ... + +class ResponseOptions(_message.Message): + __slots__ = ("return_prompt_logprobs", "prompt_candidates", "return_output_logprobs", "output_candidates", "prompt_logprob_start") + RETURN_PROMPT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] + PROMPT_CANDIDATES_FIELD_NUMBER: _ClassVar[int] + RETURN_OUTPUT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] + OUTPUT_CANDIDATES_FIELD_NUMBER: _ClassVar[int] + PROMPT_LOGPROB_START_FIELD_NUMBER: _ClassVar[int] + return_prompt_logprobs: bool + prompt_candidates: CandidateTokenSelection + return_output_logprobs: bool + output_candidates: CandidateTokenSelection + prompt_logprob_start: int + def __init__(self, return_prompt_logprobs: _Optional[bool] = ..., prompt_candidates: _Optional[_Union[CandidateTokenSelection, _Mapping]] = ..., return_output_logprobs: _Optional[bool] = ..., output_candidates: _Optional[_Union[CandidateTokenSelection, _Mapping]] = ..., prompt_logprob_start: _Optional[int] = ...) -> None: ... + +class CandidateTokenSelection(_message.Message): + __slots__ = ("top_n", "token_ids", "all") + TOP_N_FIELD_NUMBER: _ClassVar[int] + TOKEN_IDS_FIELD_NUMBER: _ClassVar[int] + ALL_FIELD_NUMBER: _ClassVar[int] + top_n: int + token_ids: TokenIds + all: AllCandidates + def __init__(self, top_n: _Optional[int] = ..., token_ids: _Optional[_Union[TokenIds, _Mapping]] = ..., all: _Optional[_Union[AllCandidates, _Mapping]] = ...) -> None: ... + +class AllCandidates(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class KvOptions(_message.Message): + __slots__ = ("session", "data_parallel_rank", "bypass_prefix_cache", "cache_salt") + SESSION_FIELD_NUMBER: _ClassVar[int] + DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] + BYPASS_PREFIX_CACHE_FIELD_NUMBER: _ClassVar[int] + CACHE_SALT_FIELD_NUMBER: _ClassVar[int] + session: _kv_pb2.KvSessionRef + data_parallel_rank: int + bypass_prefix_cache: bool + cache_salt: str + def __init__(self, session: _Optional[_Union[_kv_pb2.KvSessionRef, _Mapping]] = ..., data_parallel_rank: _Optional[int] = ..., bypass_prefix_cache: _Optional[bool] = ..., cache_salt: _Optional[str] = ...) -> None: ... + +class StopCondition(_message.Message): + __slots__ = ("stop_text", "stop_token_id") + STOP_TEXT_FIELD_NUMBER: _ClassVar[int] + STOP_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] + stop_text: str + stop_token_id: int + def __init__(self, stop_text: _Optional[str] = ..., stop_token_id: _Optional[int] = ...) -> None: ... + +class GuidedDecoding(_message.Message): + __slots__ = ("json_schema", "regex", "ebnf_grammar", "structural_tag", "choice", "json_object", "backend") + JSON_SCHEMA_FIELD_NUMBER: _ClassVar[int] + REGEX_FIELD_NUMBER: _ClassVar[int] + EBNF_GRAMMAR_FIELD_NUMBER: _ClassVar[int] + STRUCTURAL_TAG_FIELD_NUMBER: _ClassVar[int] + CHOICE_FIELD_NUMBER: _ClassVar[int] + JSON_OBJECT_FIELD_NUMBER: _ClassVar[int] + BACKEND_FIELD_NUMBER: _ClassVar[int] + json_schema: str + regex: str + ebnf_grammar: str + structural_tag: str + choice: ChoiceConstraint + json_object: JsonObjectConstraint + backend: str + def __init__(self, json_schema: _Optional[str] = ..., regex: _Optional[str] = ..., ebnf_grammar: _Optional[str] = ..., structural_tag: _Optional[str] = ..., choice: _Optional[_Union[ChoiceConstraint, _Mapping]] = ..., json_object: _Optional[_Union[JsonObjectConstraint, _Mapping]] = ..., backend: _Optional[str] = ...) -> None: ... + +class ChoiceConstraint(_message.Message): + __slots__ = ("choices",) + CHOICES_FIELD_NUMBER: _ClassVar[int] + choices: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, choices: _Optional[_Iterable[str]] = ...) -> None: ... + +class JsonObjectConstraint(_message.Message): + __slots__ = () + def __init__(self) -> None: ... diff --git a/packages/python/src/openengine/v1/generation_pb2.py b/packages/python/src/openengine/v1/generation_pb2.py new file mode 100644 index 0000000..0f16498 --- /dev/null +++ b/packages/python/src/openengine/v1/generation_pb2.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/generation.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/generation.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 +from openengine.v1 import generation_params_pb2 as openengine_dot_v1_dot_generation__params__pb2 +from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eopenengine/v1/generation.proto\x12\ropenengine.v1\x1a\x19openengine/v1/error.proto\x1a%openengine/v1/generation_params.proto\x1a\x16openengine/v1/kv.proto\"\xb8\x04\n\x0fGenerateRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\x10\n\x06prompt\x18\x03 \x01(\tH\x00\x12,\n\ttoken_ids\x18\x04 \x01(\x0b\x32\x17.openengine.v1.TokenIdsH\x00\x12/\n\x08sampling\x18\x05 \x01(\x0b\x32\x1d.openengine.v1.SamplingParams\x12\x30\n\x08stopping\x18\x06 \x01(\x0b\x32\x1e.openengine.v1.StoppingOptions\x12\x30\n\x08response\x18\x07 \x01(\x0b\x32\x1e.openengine.v1.ResponseOptions\x12$\n\x02kv\x18\x08 \x01(\x0b\x32\x18.openengine.v1.KvOptions\x12-\n\x06guided\x18\t \x01(\x0b\x32\x1d.openengine.v1.GuidedDecoding\x12\'\n\x05media\x18\n \x03(\x0b\x32\x18.openengine.v1.MediaItem\x12\x11\n\tlora_name\x18\x0b \x01(\t\x12\x15\n\x08priority\x18\x0c \x01(\x05H\x01\x88\x01\x01\x12>\n\x08metadata\x18\r \x03(\x0b\x32,.openengine.v1.GenerateRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x07\n\x05inputB\x0b\n\t_priority\"\x99\x01\n\tMediaItem\x12)\n\x08modality\x18\x01 \x01(\x0e\x32\x17.openengine.v1.Modality\x12\r\n\x03url\x18\x02 \x01(\tH\x00\x12\x12\n\x08\x64\x61ta_uri\x18\x03 \x01(\tH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x12\x11\n\tmime_type\x18\x05 \x01(\t\x12\x0c\n\x04uuid\x18\x06 \x01(\tB\x08\n\x06source\"\xca\x02\n\x10GenerateResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12-\n\x06prompt\x18\x02 \x01(\x0b\x32\x1b.openengine.v1.PromptOutputH\x00\x12+\n\x05token\x18\x03 \x01(\x0b\x32\x1a.openengine.v1.TokenOutputH\x00\x12\x34\n\rprefill_ready\x18\x04 \x01(\x0b\x32\x1b.openengine.v1.PrefillReadyH\x00\x12\x35\n\x08\x66inished\x18\x05 \x01(\x0b\x32!.openengine.v1.GenerationFinishedH\x00\x12+\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x12#\n\x05usage\x18\n \x01(\x0b\x32\x14.openengine.v1.UsageB\x07\n\x05\x65vent\"8\n\x0cPromptOutput\x12(\n\x06tokens\x18\x01 \x03(\x0b\x32\x18.openengine.v1.TokenInfo\"q\n\x0bTokenOutput\x12\x19\n\x0coutput_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12(\n\x06tokens\x18\x02 \x03(\x0b\x32\x18.openengine.v1.TokenInfo\x12\x0c\n\x04text\x18\x03 \x01(\tB\x0f\n\r_output_index\"\x96\x01\n\tTokenInfo\x12\x10\n\x08token_id\x18\x01 \x01(\r\x12\r\n\x05token\x18\x02 \x01(\t\x12\x14\n\x07logprob\x18\x03 \x01(\x01H\x00\x88\x01\x01\x12\x11\n\x04rank\x18\x04 \x01(\rH\x01\x88\x01\x01\x12*\n\ncandidates\x18\x05 \x03(\x0b\x32\x16.openengine.v1.LogProbB\n\n\x08_logprobB\x07\n\x05_rank\"W\n\x07LogProb\x12\x10\n\x08token_id\x18\x01 \x01(\r\x12\x0f\n\x07logprob\x18\x02 \x01(\x01\x12\r\n\x05token\x18\x03 \x01(\t\x12\x11\n\x04rank\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x07\n\x05_rank\"?\n\x0cPrefillReady\x12/\n\nkv_session\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRef\"\xac\x01\n\x12GenerationFinished\x12\x19\n\x0coutput_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12+\n\x06reason\x18\x02 \x01(\x0e\x32\x1b.openengine.v1.FinishReason\x12\x0f\n\x07message\x18\x03 \x01(\t\x12,\n\nstop_match\x18\x04 \x01(\x0b\x32\x18.openengine.v1.StopMatchB\x0f\n\r_output_index\"Z\n\tStopMatch\x12\x17\n\rstop_token_id\x18\x01 \x01(\rH\x00\x12\x13\n\tstop_text\x18\x02 \x01(\tH\x00\x12\x16\n\x0c\x65os_token_id\x18\x03 \x01(\rH\x00\x42\x07\n\x05match\"\xbf\x01\n\x05Usage\x12\x15\n\rprompt_tokens\x18\x01 \x01(\r\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\r\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\r\x12!\n\x14\x63\x61\x63hed_prompt_tokens\x18\x04 \x01(\rH\x00\x88\x01\x01\x12\x1d\n\x10reasoning_tokens\x18\x05 \x01(\rH\x01\x88\x01\x01\x42\x17\n\x15_cached_prompt_tokensB\x13\n\x11_reasoning_tokens*`\n\x08Modality\x12\x18\n\x14MODALITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eMODALITY_IMAGE\x10\x01\x12\x12\n\x0eMODALITY_VIDEO\x10\x02\x12\x12\n\x0eMODALITY_AUDIO\x10\x03*|\n\x0c\x46inishReason\x12\x1d\n\x19\x46INISH_REASON_UNSPECIFIED\x10\x00\x12\x16\n\x12\x46INISH_REASON_STOP\x10\x01\x12\x18\n\x14\x46INISH_REASON_LENGTH\x10\x02\x12\x1b\n\x17\x46INISH_REASON_CANCELLED\x10\x03\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.generation_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_GENERATEREQUEST_METADATAENTRY']._loaded_options = None + _globals['_GENERATEREQUEST_METADATAENTRY']._serialized_options = b'8\001' + _globals['_MODALITY']._serialized_start=2140 + _globals['_MODALITY']._serialized_end=2236 + _globals['_FINISHREASON']._serialized_start=2238 + _globals['_FINISHREASON']._serialized_end=2362 + _globals['_GENERATEREQUEST']._serialized_start=140 + _globals['_GENERATEREQUEST']._serialized_end=708 + _globals['_GENERATEREQUEST_METADATAENTRY']._serialized_start=639 + _globals['_GENERATEREQUEST_METADATAENTRY']._serialized_end=686 + _globals['_MEDIAITEM']._serialized_start=711 + _globals['_MEDIAITEM']._serialized_end=864 + _globals['_GENERATERESPONSE']._serialized_start=867 + _globals['_GENERATERESPONSE']._serialized_end=1197 + _globals['_PROMPTOUTPUT']._serialized_start=1199 + _globals['_PROMPTOUTPUT']._serialized_end=1255 + _globals['_TOKENOUTPUT']._serialized_start=1257 + _globals['_TOKENOUTPUT']._serialized_end=1370 + _globals['_TOKENINFO']._serialized_start=1373 + _globals['_TOKENINFO']._serialized_end=1523 + _globals['_LOGPROB']._serialized_start=1525 + _globals['_LOGPROB']._serialized_end=1612 + _globals['_PREFILLREADY']._serialized_start=1614 + _globals['_PREFILLREADY']._serialized_end=1677 + _globals['_GENERATIONFINISHED']._serialized_start=1680 + _globals['_GENERATIONFINISHED']._serialized_end=1852 + _globals['_STOPMATCH']._serialized_start=1854 + _globals['_STOPMATCH']._serialized_end=1944 + _globals['_USAGE']._serialized_start=1947 + _globals['_USAGE']._serialized_end=2138 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/generation_pb2.pyi b/packages/python/src/openengine/v1/generation_pb2.pyi new file mode 100644 index 0000000..8340f78 --- /dev/null +++ b/packages/python/src/openengine/v1/generation_pb2.pyi @@ -0,0 +1,188 @@ +from openengine.v1 import error_pb2 as _error_pb2 +from openengine.v1 import generation_params_pb2 as _generation_params_pb2 +from openengine.v1 import kv_pb2 as _kv_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Modality(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + MODALITY_UNSPECIFIED: _ClassVar[Modality] + MODALITY_IMAGE: _ClassVar[Modality] + MODALITY_VIDEO: _ClassVar[Modality] + MODALITY_AUDIO: _ClassVar[Modality] + +class FinishReason(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + FINISH_REASON_UNSPECIFIED: _ClassVar[FinishReason] + FINISH_REASON_STOP: _ClassVar[FinishReason] + FINISH_REASON_LENGTH: _ClassVar[FinishReason] + FINISH_REASON_CANCELLED: _ClassVar[FinishReason] +MODALITY_UNSPECIFIED: Modality +MODALITY_IMAGE: Modality +MODALITY_VIDEO: Modality +MODALITY_AUDIO: Modality +FINISH_REASON_UNSPECIFIED: FinishReason +FINISH_REASON_STOP: FinishReason +FINISH_REASON_LENGTH: FinishReason +FINISH_REASON_CANCELLED: FinishReason + +class GenerateRequest(_message.Message): + __slots__ = ("request_id", "model", "prompt", "token_ids", "sampling", "stopping", "response", "kv", "guided", "media", "lora_name", "priority", "metadata") + class MetadataEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + MODEL_FIELD_NUMBER: _ClassVar[int] + PROMPT_FIELD_NUMBER: _ClassVar[int] + TOKEN_IDS_FIELD_NUMBER: _ClassVar[int] + SAMPLING_FIELD_NUMBER: _ClassVar[int] + STOPPING_FIELD_NUMBER: _ClassVar[int] + RESPONSE_FIELD_NUMBER: _ClassVar[int] + KV_FIELD_NUMBER: _ClassVar[int] + GUIDED_FIELD_NUMBER: _ClassVar[int] + MEDIA_FIELD_NUMBER: _ClassVar[int] + LORA_NAME_FIELD_NUMBER: _ClassVar[int] + PRIORITY_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + request_id: str + model: str + prompt: str + token_ids: _generation_params_pb2.TokenIds + sampling: _generation_params_pb2.SamplingParams + stopping: _generation_params_pb2.StoppingOptions + response: _generation_params_pb2.ResponseOptions + kv: _generation_params_pb2.KvOptions + guided: _generation_params_pb2.GuidedDecoding + media: _containers.RepeatedCompositeFieldContainer[MediaItem] + lora_name: str + priority: int + metadata: _containers.ScalarMap[str, str] + def __init__(self, request_id: _Optional[str] = ..., model: _Optional[str] = ..., prompt: _Optional[str] = ..., token_ids: _Optional[_Union[_generation_params_pb2.TokenIds, _Mapping]] = ..., sampling: _Optional[_Union[_generation_params_pb2.SamplingParams, _Mapping]] = ..., stopping: _Optional[_Union[_generation_params_pb2.StoppingOptions, _Mapping]] = ..., response: _Optional[_Union[_generation_params_pb2.ResponseOptions, _Mapping]] = ..., kv: _Optional[_Union[_generation_params_pb2.KvOptions, _Mapping]] = ..., guided: _Optional[_Union[_generation_params_pb2.GuidedDecoding, _Mapping]] = ..., media: _Optional[_Iterable[_Union[MediaItem, _Mapping]]] = ..., lora_name: _Optional[str] = ..., priority: _Optional[int] = ..., metadata: _Optional[_Mapping[str, str]] = ...) -> None: ... + +class MediaItem(_message.Message): + __slots__ = ("modality", "url", "data_uri", "raw_bytes", "mime_type", "uuid") + MODALITY_FIELD_NUMBER: _ClassVar[int] + URL_FIELD_NUMBER: _ClassVar[int] + DATA_URI_FIELD_NUMBER: _ClassVar[int] + RAW_BYTES_FIELD_NUMBER: _ClassVar[int] + MIME_TYPE_FIELD_NUMBER: _ClassVar[int] + UUID_FIELD_NUMBER: _ClassVar[int] + modality: Modality + url: str + data_uri: str + raw_bytes: bytes + mime_type: str + uuid: str + def __init__(self, modality: _Optional[_Union[Modality, str]] = ..., url: _Optional[str] = ..., data_uri: _Optional[str] = ..., raw_bytes: _Optional[bytes] = ..., mime_type: _Optional[str] = ..., uuid: _Optional[str] = ...) -> None: ... + +class GenerateResponse(_message.Message): + __slots__ = ("request_id", "prompt", "token", "prefill_ready", "finished", "error", "usage") + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + PROMPT_FIELD_NUMBER: _ClassVar[int] + TOKEN_FIELD_NUMBER: _ClassVar[int] + PREFILL_READY_FIELD_NUMBER: _ClassVar[int] + FINISHED_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + USAGE_FIELD_NUMBER: _ClassVar[int] + request_id: str + prompt: PromptOutput + token: TokenOutput + prefill_ready: PrefillReady + finished: GenerationFinished + error: _error_pb2.EngineError + usage: Usage + def __init__(self, request_id: _Optional[str] = ..., prompt: _Optional[_Union[PromptOutput, _Mapping]] = ..., token: _Optional[_Union[TokenOutput, _Mapping]] = ..., prefill_ready: _Optional[_Union[PrefillReady, _Mapping]] = ..., finished: _Optional[_Union[GenerationFinished, _Mapping]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ..., usage: _Optional[_Union[Usage, _Mapping]] = ...) -> None: ... + +class PromptOutput(_message.Message): + __slots__ = ("tokens",) + TOKENS_FIELD_NUMBER: _ClassVar[int] + tokens: _containers.RepeatedCompositeFieldContainer[TokenInfo] + def __init__(self, tokens: _Optional[_Iterable[_Union[TokenInfo, _Mapping]]] = ...) -> None: ... + +class TokenOutput(_message.Message): + __slots__ = ("output_index", "tokens", "text") + OUTPUT_INDEX_FIELD_NUMBER: _ClassVar[int] + TOKENS_FIELD_NUMBER: _ClassVar[int] + TEXT_FIELD_NUMBER: _ClassVar[int] + output_index: int + tokens: _containers.RepeatedCompositeFieldContainer[TokenInfo] + text: str + def __init__(self, output_index: _Optional[int] = ..., tokens: _Optional[_Iterable[_Union[TokenInfo, _Mapping]]] = ..., text: _Optional[str] = ...) -> None: ... + +class TokenInfo(_message.Message): + __slots__ = ("token_id", "token", "logprob", "rank", "candidates") + TOKEN_ID_FIELD_NUMBER: _ClassVar[int] + TOKEN_FIELD_NUMBER: _ClassVar[int] + LOGPROB_FIELD_NUMBER: _ClassVar[int] + RANK_FIELD_NUMBER: _ClassVar[int] + CANDIDATES_FIELD_NUMBER: _ClassVar[int] + token_id: int + token: str + logprob: float + rank: int + candidates: _containers.RepeatedCompositeFieldContainer[LogProb] + def __init__(self, token_id: _Optional[int] = ..., token: _Optional[str] = ..., logprob: _Optional[float] = ..., rank: _Optional[int] = ..., candidates: _Optional[_Iterable[_Union[LogProb, _Mapping]]] = ...) -> None: ... + +class LogProb(_message.Message): + __slots__ = ("token_id", "logprob", "token", "rank") + TOKEN_ID_FIELD_NUMBER: _ClassVar[int] + LOGPROB_FIELD_NUMBER: _ClassVar[int] + TOKEN_FIELD_NUMBER: _ClassVar[int] + RANK_FIELD_NUMBER: _ClassVar[int] + token_id: int + logprob: float + token: str + rank: int + def __init__(self, token_id: _Optional[int] = ..., logprob: _Optional[float] = ..., token: _Optional[str] = ..., rank: _Optional[int] = ...) -> None: ... + +class PrefillReady(_message.Message): + __slots__ = ("kv_session",) + KV_SESSION_FIELD_NUMBER: _ClassVar[int] + kv_session: _kv_pb2.KvSessionRef + def __init__(self, kv_session: _Optional[_Union[_kv_pb2.KvSessionRef, _Mapping]] = ...) -> None: ... + +class GenerationFinished(_message.Message): + __slots__ = ("output_index", "reason", "message", "stop_match") + OUTPUT_INDEX_FIELD_NUMBER: _ClassVar[int] + REASON_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + STOP_MATCH_FIELD_NUMBER: _ClassVar[int] + output_index: int + reason: FinishReason + message: str + stop_match: StopMatch + def __init__(self, output_index: _Optional[int] = ..., reason: _Optional[_Union[FinishReason, str]] = ..., message: _Optional[str] = ..., stop_match: _Optional[_Union[StopMatch, _Mapping]] = ...) -> None: ... + +class StopMatch(_message.Message): + __slots__ = ("stop_token_id", "stop_text", "eos_token_id") + STOP_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] + STOP_TEXT_FIELD_NUMBER: _ClassVar[int] + EOS_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] + stop_token_id: int + stop_text: str + eos_token_id: int + def __init__(self, stop_token_id: _Optional[int] = ..., stop_text: _Optional[str] = ..., eos_token_id: _Optional[int] = ...) -> None: ... + +class Usage(_message.Message): + __slots__ = ("prompt_tokens", "completion_tokens", "total_tokens", "cached_prompt_tokens", "reasoning_tokens") + PROMPT_TOKENS_FIELD_NUMBER: _ClassVar[int] + COMPLETION_TOKENS_FIELD_NUMBER: _ClassVar[int] + TOTAL_TOKENS_FIELD_NUMBER: _ClassVar[int] + CACHED_PROMPT_TOKENS_FIELD_NUMBER: _ClassVar[int] + REASONING_TOKENS_FIELD_NUMBER: _ClassVar[int] + prompt_tokens: int + completion_tokens: int + total_tokens: int + cached_prompt_tokens: int + reasoning_tokens: int + def __init__(self, prompt_tokens: _Optional[int] = ..., completion_tokens: _Optional[int] = ..., total_tokens: _Optional[int] = ..., cached_prompt_tokens: _Optional[int] = ..., reasoning_tokens: _Optional[int] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/kv_pb2.py b/packages/python/src/openengine/v1/kv_pb2.py new file mode 100644 index 0000000..7bab09d --- /dev/null +++ b/packages/python/src/openengine/v1/kv_pb2.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/kv.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/kv.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16openengine/v1/kv.proto\x12\ropenengine.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x19openengine/v1/error.proto\"\xaf\x01\n\x0cKvSessionRef\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10transfer_backend\x18\x02 \x01(\t\x12,\n\tendpoints\x18\x03 \x03(\x0b\x32\x19.openengine.v1.KvEndpoint\x12\x0f\n\x07\x64p_rank\x18\x04 \x01(\r\x12\x32\n\x11\x61ttributes_struct\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\":\n\nKvEndpoint\x12\x0c\n\x04host\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x10\n\x08protocol\x18\x03 \x01(\t\"\x1b\n\x19GetKvConnectorInfoRequest\"\xbc\x03\n\x0fKvConnectorInfo\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x18\n\x10transfer_backend\x18\x02 \x01(\t\x12\x32\n\x0flocal_endpoints\x18\x03 \x03(\x0b\x32\x19.openengine.v1.KvEndpoint\x12\x1b\n\x13supported_protocols\x18\x04 \x03(\t\x12$\n\x17supports_remote_prefill\x18\x05 \x01(\x08H\x01\x88\x01\x01\x12!\n\x14supports_decode_pull\x18\x06 \x01(\x08H\x02\x88\x01\x01\x12#\n\x16supports_abort_cleanup\x18\x07 \x01(\x08H\x03\x88\x01\x01\x12\x1b\n\x0esupports_drain\x18\x08 \x01(\x08H\x04\x88\x01\x01\x12\x1b\n\x0eschema_version\x18\t \x01(\rH\x05\x88\x01\x01\x42\n\n\x08_enabledB\x1a\n\x18_supports_remote_prefillB\x17\n\x15_supports_decode_pullB\x19\n\x17_supports_abort_cleanupB\x11\n\x0f_supports_drainB\x11\n\x0f_schema_version\"7\n\x18GetKvEventSourcesRequest\x12\x1b\n\x13\x64\x61ta_parallel_ranks\x18\x01 \x03(\r\"J\n\x19GetKvEventSourcesResponse\x12-\n\x07sources\x18\x01 \x03(\x0b\x32\x1c.openengine.v1.KvEventSource\"\xec\x02\n\rKvEventSource\x12\x11\n\ttransport\x18\x01 \x01(\t\x12\x30\n\rendpoint_addr\x18\x02 \x01(\x0b\x32\x19.openengine.v1.KvEndpoint\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x17\n\x0freplay_endpoint\x18\x04 \x01(\t\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x05 \x01(\rH\x00\x88\x01\x01\x12\x10\n\x08\x65ncoding\x18\x06 \x01(\t\x12\x1b\n\x0eschema_version\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x19\n\x0c\x62uffer_steps\x18\x08 \x01(\rH\x02\x88\x01\x01\x12\x10\n\x03hwm\x18\t \x01(\rH\x03\x88\x01\x01\x12\x1b\n\x0emax_queue_size\x18\n \x01(\rH\x04\x88\x01\x01\x42\x15\n\x13_data_parallel_rankB\x11\n\x0f_schema_versionB\x0f\n\r_buffer_stepsB\x06\n\x04_hwmB\x11\n\x0f_max_queue_size\"p\n\x18SubscribeKvEventsRequest\x12\x1b\n\x13\x64\x61ta_parallel_ranks\x18\x01 \x03(\r\x12\x18\n\x10include_snapshot\x18\x02 \x01(\x08\x12\x1d\n\x15start_sequence_number\x18\x03 \x01(\x04\"\x7f\n\x19SubscribeKvEventsResponse\x12,\n\x05\x62\x61tch\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.KvEventBatchH\x00\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x42\x07\n\x05\x65vent\"\x89\x01\n\x0cKvEventBatch\x12\x17\n\x0fsequence_number\x18\x01 \x01(\x04\x12\x1c\n\x14timestamp_unix_nanos\x18\x02 \x01(\x04\x12\x1a\n\x12\x64\x61ta_parallel_rank\x18\x03 \x01(\r\x12&\n\x06\x65vents\x18\x04 \x03(\x0b\x32\x16.openengine.v1.KvEvent\"\x80\x02\n\x07KvEvent\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12/\n\nkv_session\x18\x02 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRef\x12\x32\n\x0c\x62lock_stored\x18\n \x01(\x0b\x32\x1a.openengine.v1.BlockStoredH\x00\x12\x34\n\rblock_removed\x18\x0b \x01(\x0b\x32\x1b.openengine.v1.BlockRemovedH\x00\x12=\n\x12\x61ll_blocks_cleared\x18\x0c \x01(\x0b\x32\x1f.openengine.v1.AllBlocksClearedH\x00\x42\x07\n\x05\x65vent\"\xf7\x02\n\x0b\x42lockStored\x12\x30\n\x0c\x62lock_hashes\x18\x01 \x03(\x0b\x32\x1a.openengine.v1.KvBlockHash\x12\x35\n\x11parent_block_hash\x18\x02 \x01(\x0b\x32\x1a.openengine.v1.KvBlockHash\x12\x11\n\ttoken_ids\x18\x03 \x03(\r\x12\x12\n\nblock_size\x18\x04 \x01(\r\x12\x0f\n\x07lora_id\x18\x05 \x01(\x03\x12\x11\n\tlora_name\x18\x06 \x01(\t\x12,\n\x06medium\x18\x07 \x01(\x0e\x32\x1c.openengine.v1.StorageMedium\x12\x31\n\nextra_keys\x18\x14 \x03(\x0b\x32\x1d.openengine.v1.OpaqueKeyTuple\x12\x11\n\tgroup_idx\x18\x15 \x01(\r\x12\x1a\n\x12kv_cache_spec_kind\x18\x16 \x01(\t\x12$\n\x1ckv_cache_spec_sliding_window\x18\x17 \x01(\r\"\x81\x01\n\x0c\x42lockRemoved\x12\x30\n\x0c\x62lock_hashes\x18\x01 \x03(\x0b\x32\x1a.openengine.v1.KvBlockHash\x12,\n\x06medium\x18\x02 \x01(\x0e\x32\x1c.openengine.v1.StorageMedium\x12\x11\n\tgroup_idx\x18\x03 \x01(\r\"\x12\n\x10\x41llBlocksCleared\".\n\x0bKvBlockHash\x12\r\n\x05value\x18\x01 \x01(\x0c\x12\x10\n\x08\x65ncoding\x18\x02 \x01(\t\" \n\x0eOpaqueKeyTuple\x12\x0e\n\x06values\x18\x01 \x03(\t*\x9c\x01\n\rStorageMedium\x12\x1e\n\x1aSTORAGE_MEDIUM_UNSPECIFIED\x10\x00\x12\x16\n\x12STORAGE_MEDIUM_GPU\x10\x01\x12\x1d\n\x19STORAGE_MEDIUM_CPU_PINNED\x10\x02\x12\x17\n\x13STORAGE_MEDIUM_DISK\x10\x03\x12\x1b\n\x17STORAGE_MEDIUM_EXTERNAL\x10\x04\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.kv_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_STORAGEMEDIUM']._serialized_start=2567 + _globals['_STORAGEMEDIUM']._serialized_end=2723 + _globals['_KVSESSIONREF']._serialized_start=99 + _globals['_KVSESSIONREF']._serialized_end=274 + _globals['_KVENDPOINT']._serialized_start=276 + _globals['_KVENDPOINT']._serialized_end=334 + _globals['_GETKVCONNECTORINFOREQUEST']._serialized_start=336 + _globals['_GETKVCONNECTORINFOREQUEST']._serialized_end=363 + _globals['_KVCONNECTORINFO']._serialized_start=366 + _globals['_KVCONNECTORINFO']._serialized_end=810 + _globals['_GETKVEVENTSOURCESREQUEST']._serialized_start=812 + _globals['_GETKVEVENTSOURCESREQUEST']._serialized_end=867 + _globals['_GETKVEVENTSOURCESRESPONSE']._serialized_start=869 + _globals['_GETKVEVENTSOURCESRESPONSE']._serialized_end=943 + _globals['_KVEVENTSOURCE']._serialized_start=946 + _globals['_KVEVENTSOURCE']._serialized_end=1310 + _globals['_SUBSCRIBEKVEVENTSREQUEST']._serialized_start=1312 + _globals['_SUBSCRIBEKVEVENTSREQUEST']._serialized_end=1424 + _globals['_SUBSCRIBEKVEVENTSRESPONSE']._serialized_start=1426 + _globals['_SUBSCRIBEKVEVENTSRESPONSE']._serialized_end=1553 + _globals['_KVEVENTBATCH']._serialized_start=1556 + _globals['_KVEVENTBATCH']._serialized_end=1693 + _globals['_KVEVENT']._serialized_start=1696 + _globals['_KVEVENT']._serialized_end=1952 + _globals['_BLOCKSTORED']._serialized_start=1955 + _globals['_BLOCKSTORED']._serialized_end=2330 + _globals['_BLOCKREMOVED']._serialized_start=2333 + _globals['_BLOCKREMOVED']._serialized_end=2462 + _globals['_ALLBLOCKSCLEARED']._serialized_start=2464 + _globals['_ALLBLOCKSCLEARED']._serialized_end=2482 + _globals['_KVBLOCKHASH']._serialized_start=2484 + _globals['_KVBLOCKHASH']._serialized_end=2530 + _globals['_OPAQUEKEYTUPLE']._serialized_start=2532 + _globals['_OPAQUEKEYTUPLE']._serialized_end=2564 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/kv_pb2.pyi b/packages/python/src/openengine/v1/kv_pb2.pyi new file mode 100644 index 0000000..ee42789 --- /dev/null +++ b/packages/python/src/openengine/v1/kv_pb2.pyi @@ -0,0 +1,207 @@ +from google.protobuf import struct_pb2 as _struct_pb2 +from openengine.v1 import error_pb2 as _error_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class StorageMedium(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + STORAGE_MEDIUM_UNSPECIFIED: _ClassVar[StorageMedium] + STORAGE_MEDIUM_GPU: _ClassVar[StorageMedium] + STORAGE_MEDIUM_CPU_PINNED: _ClassVar[StorageMedium] + STORAGE_MEDIUM_DISK: _ClassVar[StorageMedium] + STORAGE_MEDIUM_EXTERNAL: _ClassVar[StorageMedium] +STORAGE_MEDIUM_UNSPECIFIED: StorageMedium +STORAGE_MEDIUM_GPU: StorageMedium +STORAGE_MEDIUM_CPU_PINNED: StorageMedium +STORAGE_MEDIUM_DISK: StorageMedium +STORAGE_MEDIUM_EXTERNAL: StorageMedium + +class KvSessionRef(_message.Message): + __slots__ = ("session_id", "transfer_backend", "endpoints", "dp_rank", "attributes_struct") + SESSION_ID_FIELD_NUMBER: _ClassVar[int] + TRANSFER_BACKEND_FIELD_NUMBER: _ClassVar[int] + ENDPOINTS_FIELD_NUMBER: _ClassVar[int] + DP_RANK_FIELD_NUMBER: _ClassVar[int] + ATTRIBUTES_STRUCT_FIELD_NUMBER: _ClassVar[int] + session_id: str + transfer_backend: str + endpoints: _containers.RepeatedCompositeFieldContainer[KvEndpoint] + dp_rank: int + attributes_struct: _struct_pb2.Struct + def __init__(self, session_id: _Optional[str] = ..., transfer_backend: _Optional[str] = ..., endpoints: _Optional[_Iterable[_Union[KvEndpoint, _Mapping]]] = ..., dp_rank: _Optional[int] = ..., attributes_struct: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + +class KvEndpoint(_message.Message): + __slots__ = ("host", "port", "protocol") + HOST_FIELD_NUMBER: _ClassVar[int] + PORT_FIELD_NUMBER: _ClassVar[int] + PROTOCOL_FIELD_NUMBER: _ClassVar[int] + host: str + port: int + protocol: str + def __init__(self, host: _Optional[str] = ..., port: _Optional[int] = ..., protocol: _Optional[str] = ...) -> None: ... + +class GetKvConnectorInfoRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class KvConnectorInfo(_message.Message): + __slots__ = ("enabled", "transfer_backend", "local_endpoints", "supported_protocols", "supports_remote_prefill", "supports_decode_pull", "supports_abort_cleanup", "supports_drain", "schema_version") + ENABLED_FIELD_NUMBER: _ClassVar[int] + TRANSFER_BACKEND_FIELD_NUMBER: _ClassVar[int] + LOCAL_ENDPOINTS_FIELD_NUMBER: _ClassVar[int] + SUPPORTED_PROTOCOLS_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_REMOTE_PREFILL_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_DECODE_PULL_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_ABORT_CLEANUP_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_DRAIN_FIELD_NUMBER: _ClassVar[int] + SCHEMA_VERSION_FIELD_NUMBER: _ClassVar[int] + enabled: bool + transfer_backend: str + local_endpoints: _containers.RepeatedCompositeFieldContainer[KvEndpoint] + supported_protocols: _containers.RepeatedScalarFieldContainer[str] + supports_remote_prefill: bool + supports_decode_pull: bool + supports_abort_cleanup: bool + supports_drain: bool + schema_version: int + def __init__(self, enabled: _Optional[bool] = ..., transfer_backend: _Optional[str] = ..., local_endpoints: _Optional[_Iterable[_Union[KvEndpoint, _Mapping]]] = ..., supported_protocols: _Optional[_Iterable[str]] = ..., supports_remote_prefill: _Optional[bool] = ..., supports_decode_pull: _Optional[bool] = ..., supports_abort_cleanup: _Optional[bool] = ..., supports_drain: _Optional[bool] = ..., schema_version: _Optional[int] = ...) -> None: ... + +class GetKvEventSourcesRequest(_message.Message): + __slots__ = ("data_parallel_ranks",) + DATA_PARALLEL_RANKS_FIELD_NUMBER: _ClassVar[int] + data_parallel_ranks: _containers.RepeatedScalarFieldContainer[int] + def __init__(self, data_parallel_ranks: _Optional[_Iterable[int]] = ...) -> None: ... + +class GetKvEventSourcesResponse(_message.Message): + __slots__ = ("sources",) + SOURCES_FIELD_NUMBER: _ClassVar[int] + sources: _containers.RepeatedCompositeFieldContainer[KvEventSource] + def __init__(self, sources: _Optional[_Iterable[_Union[KvEventSource, _Mapping]]] = ...) -> None: ... + +class KvEventSource(_message.Message): + __slots__ = ("transport", "endpoint_addr", "topic", "replay_endpoint", "data_parallel_rank", "encoding", "schema_version", "buffer_steps", "hwm", "max_queue_size") + TRANSPORT_FIELD_NUMBER: _ClassVar[int] + ENDPOINT_ADDR_FIELD_NUMBER: _ClassVar[int] + TOPIC_FIELD_NUMBER: _ClassVar[int] + REPLAY_ENDPOINT_FIELD_NUMBER: _ClassVar[int] + DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] + ENCODING_FIELD_NUMBER: _ClassVar[int] + SCHEMA_VERSION_FIELD_NUMBER: _ClassVar[int] + BUFFER_STEPS_FIELD_NUMBER: _ClassVar[int] + HWM_FIELD_NUMBER: _ClassVar[int] + MAX_QUEUE_SIZE_FIELD_NUMBER: _ClassVar[int] + transport: str + endpoint_addr: KvEndpoint + topic: str + replay_endpoint: str + data_parallel_rank: int + encoding: str + schema_version: int + buffer_steps: int + hwm: int + max_queue_size: int + def __init__(self, transport: _Optional[str] = ..., endpoint_addr: _Optional[_Union[KvEndpoint, _Mapping]] = ..., topic: _Optional[str] = ..., replay_endpoint: _Optional[str] = ..., data_parallel_rank: _Optional[int] = ..., encoding: _Optional[str] = ..., schema_version: _Optional[int] = ..., buffer_steps: _Optional[int] = ..., hwm: _Optional[int] = ..., max_queue_size: _Optional[int] = ...) -> None: ... + +class SubscribeKvEventsRequest(_message.Message): + __slots__ = ("data_parallel_ranks", "include_snapshot", "start_sequence_number") + DATA_PARALLEL_RANKS_FIELD_NUMBER: _ClassVar[int] + INCLUDE_SNAPSHOT_FIELD_NUMBER: _ClassVar[int] + START_SEQUENCE_NUMBER_FIELD_NUMBER: _ClassVar[int] + data_parallel_ranks: _containers.RepeatedScalarFieldContainer[int] + include_snapshot: bool + start_sequence_number: int + def __init__(self, data_parallel_ranks: _Optional[_Iterable[int]] = ..., include_snapshot: _Optional[bool] = ..., start_sequence_number: _Optional[int] = ...) -> None: ... + +class SubscribeKvEventsResponse(_message.Message): + __slots__ = ("batch", "error") + BATCH_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + batch: KvEventBatch + error: _error_pb2.EngineError + def __init__(self, batch: _Optional[_Union[KvEventBatch, _Mapping]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ...) -> None: ... + +class KvEventBatch(_message.Message): + __slots__ = ("sequence_number", "timestamp_unix_nanos", "data_parallel_rank", "events") + SEQUENCE_NUMBER_FIELD_NUMBER: _ClassVar[int] + TIMESTAMP_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] + DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] + EVENTS_FIELD_NUMBER: _ClassVar[int] + sequence_number: int + timestamp_unix_nanos: int + data_parallel_rank: int + events: _containers.RepeatedCompositeFieldContainer[KvEvent] + def __init__(self, sequence_number: _Optional[int] = ..., timestamp_unix_nanos: _Optional[int] = ..., data_parallel_rank: _Optional[int] = ..., events: _Optional[_Iterable[_Union[KvEvent, _Mapping]]] = ...) -> None: ... + +class KvEvent(_message.Message): + __slots__ = ("request_id", "kv_session", "block_stored", "block_removed", "all_blocks_cleared") + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + KV_SESSION_FIELD_NUMBER: _ClassVar[int] + BLOCK_STORED_FIELD_NUMBER: _ClassVar[int] + BLOCK_REMOVED_FIELD_NUMBER: _ClassVar[int] + ALL_BLOCKS_CLEARED_FIELD_NUMBER: _ClassVar[int] + request_id: str + kv_session: KvSessionRef + block_stored: BlockStored + block_removed: BlockRemoved + all_blocks_cleared: AllBlocksCleared + def __init__(self, request_id: _Optional[str] = ..., kv_session: _Optional[_Union[KvSessionRef, _Mapping]] = ..., block_stored: _Optional[_Union[BlockStored, _Mapping]] = ..., block_removed: _Optional[_Union[BlockRemoved, _Mapping]] = ..., all_blocks_cleared: _Optional[_Union[AllBlocksCleared, _Mapping]] = ...) -> None: ... + +class BlockStored(_message.Message): + __slots__ = ("block_hashes", "parent_block_hash", "token_ids", "block_size", "lora_id", "lora_name", "medium", "extra_keys", "group_idx", "kv_cache_spec_kind", "kv_cache_spec_sliding_window") + BLOCK_HASHES_FIELD_NUMBER: _ClassVar[int] + PARENT_BLOCK_HASH_FIELD_NUMBER: _ClassVar[int] + TOKEN_IDS_FIELD_NUMBER: _ClassVar[int] + BLOCK_SIZE_FIELD_NUMBER: _ClassVar[int] + LORA_ID_FIELD_NUMBER: _ClassVar[int] + LORA_NAME_FIELD_NUMBER: _ClassVar[int] + MEDIUM_FIELD_NUMBER: _ClassVar[int] + EXTRA_KEYS_FIELD_NUMBER: _ClassVar[int] + GROUP_IDX_FIELD_NUMBER: _ClassVar[int] + KV_CACHE_SPEC_KIND_FIELD_NUMBER: _ClassVar[int] + KV_CACHE_SPEC_SLIDING_WINDOW_FIELD_NUMBER: _ClassVar[int] + block_hashes: _containers.RepeatedCompositeFieldContainer[KvBlockHash] + parent_block_hash: KvBlockHash + token_ids: _containers.RepeatedScalarFieldContainer[int] + block_size: int + lora_id: int + lora_name: str + medium: StorageMedium + extra_keys: _containers.RepeatedCompositeFieldContainer[OpaqueKeyTuple] + group_idx: int + kv_cache_spec_kind: str + kv_cache_spec_sliding_window: int + def __init__(self, block_hashes: _Optional[_Iterable[_Union[KvBlockHash, _Mapping]]] = ..., parent_block_hash: _Optional[_Union[KvBlockHash, _Mapping]] = ..., token_ids: _Optional[_Iterable[int]] = ..., block_size: _Optional[int] = ..., lora_id: _Optional[int] = ..., lora_name: _Optional[str] = ..., medium: _Optional[_Union[StorageMedium, str]] = ..., extra_keys: _Optional[_Iterable[_Union[OpaqueKeyTuple, _Mapping]]] = ..., group_idx: _Optional[int] = ..., kv_cache_spec_kind: _Optional[str] = ..., kv_cache_spec_sliding_window: _Optional[int] = ...) -> None: ... + +class BlockRemoved(_message.Message): + __slots__ = ("block_hashes", "medium", "group_idx") + BLOCK_HASHES_FIELD_NUMBER: _ClassVar[int] + MEDIUM_FIELD_NUMBER: _ClassVar[int] + GROUP_IDX_FIELD_NUMBER: _ClassVar[int] + block_hashes: _containers.RepeatedCompositeFieldContainer[KvBlockHash] + medium: StorageMedium + group_idx: int + def __init__(self, block_hashes: _Optional[_Iterable[_Union[KvBlockHash, _Mapping]]] = ..., medium: _Optional[_Union[StorageMedium, str]] = ..., group_idx: _Optional[int] = ...) -> None: ... + +class AllBlocksCleared(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class KvBlockHash(_message.Message): + __slots__ = ("value", "encoding") + VALUE_FIELD_NUMBER: _ClassVar[int] + ENCODING_FIELD_NUMBER: _ClassVar[int] + value: bytes + encoding: str + def __init__(self, value: _Optional[bytes] = ..., encoding: _Optional[str] = ...) -> None: ... + +class OpaqueKeyTuple(_message.Message): + __slots__ = ("values",) + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, values: _Optional[_Iterable[str]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/lifecycle_pb2.py b/packages/python/src/openengine/v1/lifecycle_pb2.py new file mode 100644 index 0000000..69a44ca --- /dev/null +++ b/packages/python/src/openengine/v1/lifecycle_pb2.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/lifecycle.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/lifecycle.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from openengine.v1 import engine_pb2 as openengine_dot_v1_dot_engine__pb2 +from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 +from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dopenengine/v1/lifecycle.proto\x12\ropenengine.v1\x1a\x1aopenengine/v1/engine.proto\x1a\x19openengine/v1/error.proto\x1a\x16openengine/v1/kv.proto\"h\n\rHealthRequest\x12\x1f\n\x17include_inference_probe\x18\x01 \x01(\x08\x12\r\n\x05model\x18\x02 \x01(\t\x12\'\n\x04role\x18\x03 \x01(\x0e\x32\x19.openengine.v1.EngineRole\"g\n\x0eHealthResponse\x12)\n\x05state\x18\x01 \x01(\x0e\x32\x1a.openengine.v1.HealthState\x12*\n\x06\x63hecks\x18\x02 \x03(\x0b\x32\x1a.openengine.v1.HealthCheck\"W\n\x0bHealthCheck\x12\x0c\n\x04name\x18\x01 \x01(\t\x12)\n\x05state\x18\x02 \x01(\x0e\x32\x1a.openengine.v1.HealthState\x12\x0f\n\x07message\x18\x03 \x01(\t\"\x95\x01\n\x0c\x41\x62ortRequest\x12\x14\n\nrequest_id\x18\x01 \x01(\tH\x00\x12\x31\n\nkv_session\x18\x02 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRefH\x00\x12\x32\n\x0c\x61ll_requests\x18\x03 \x01(\x0b\x32\x1a.openengine.v1.AllRequestsH\x00\x42\x08\n\x06target\"\r\n\x0b\x41llRequests\"L\n\rAbortResponse\x12*\n\x06status\x18\x01 \x01(\x0e\x32\x1a.openengine.v1.AbortStatus\x12\x0f\n\x07message\x18\x02 \x01(\t\"{\n\x0c\x44rainRequest\x12#\n\x1bstop_accepting_new_requests\x18\x01 \x01(\x08\x12\x18\n\x0b\x64\x65\x61\x64line_ms\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x14\x61\x62ort_after_deadline\x18\x03 \x01(\x08\x42\x0e\n\x0c_deadline_ms\"\xee\x01\n\rDrainResponse\x12*\n\x05state\x18\x01 \x01(\x0e\x32\x19.openengine.v1.DrainStateH\x00\x12+\n\x05\x65rror\x18\x05 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x12\x1f\n\x12in_flight_requests\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1d\n\x10open_kv_sessions\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x0f\n\x07message\x18\x04 \x01(\tB\x07\n\x05\x65ventB\x15\n\x13_in_flight_requestsB\x13\n\x11_open_kv_sessions*\xb0\x01\n\x0bHealthState\x12\x1c\n\x18HEALTH_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15HEALTH_STATE_STARTING\x10\x01\x12\x16\n\x12HEALTH_STATE_READY\x10\x02\x12\x19\n\x15HEALTH_STATE_DEGRADED\x10\x03\x12\x19\n\x15HEALTH_STATE_DRAINING\x10\x04\x12\x1a\n\x16HEALTH_STATE_NOT_READY\x10\x05*h\n\x0b\x41\x62ortStatus\x12\x1c\n\x18\x41\x42ORT_STATUS_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41\x42ORT_STATUS_ABORTED\x10\x01\x12!\n\x1d\x41\x42ORT_STATUS_ALREADY_FINISHED\x10\x02*y\n\nDrainState\x12\x1b\n\x17\x44RAIN_STATE_UNSPECIFIED\x10\x00\x12\x17\n\x13\x44RAIN_STATE_STARTED\x10\x01\x12\x1b\n\x17\x44RAIN_STATE_IN_PROGRESS\x10\x02\x12\x18\n\x14\x44RAIN_STATE_COMPLETE\x10\x03\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.lifecycle_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_HEALTHSTATE']._serialized_start=1039 + _globals['_HEALTHSTATE']._serialized_end=1215 + _globals['_ABORTSTATUS']._serialized_start=1217 + _globals['_ABORTSTATUS']._serialized_end=1321 + _globals['_DRAINSTATE']._serialized_start=1323 + _globals['_DRAINSTATE']._serialized_end=1444 + _globals['_HEALTHREQUEST']._serialized_start=127 + _globals['_HEALTHREQUEST']._serialized_end=231 + _globals['_HEALTHRESPONSE']._serialized_start=233 + _globals['_HEALTHRESPONSE']._serialized_end=336 + _globals['_HEALTHCHECK']._serialized_start=338 + _globals['_HEALTHCHECK']._serialized_end=425 + _globals['_ABORTREQUEST']._serialized_start=428 + _globals['_ABORTREQUEST']._serialized_end=577 + _globals['_ALLREQUESTS']._serialized_start=579 + _globals['_ALLREQUESTS']._serialized_end=592 + _globals['_ABORTRESPONSE']._serialized_start=594 + _globals['_ABORTRESPONSE']._serialized_end=670 + _globals['_DRAINREQUEST']._serialized_start=672 + _globals['_DRAINREQUEST']._serialized_end=795 + _globals['_DRAINRESPONSE']._serialized_start=798 + _globals['_DRAINRESPONSE']._serialized_end=1036 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/lifecycle_pb2.pyi b/packages/python/src/openengine/v1/lifecycle_pb2.pyi new file mode 100644 index 0000000..329d52d --- /dev/null +++ b/packages/python/src/openengine/v1/lifecycle_pb2.pyi @@ -0,0 +1,120 @@ +from openengine.v1 import engine_pb2 as _engine_pb2 +from openengine.v1 import error_pb2 as _error_pb2 +from openengine.v1 import kv_pb2 as _kv_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class HealthState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + HEALTH_STATE_UNSPECIFIED: _ClassVar[HealthState] + HEALTH_STATE_STARTING: _ClassVar[HealthState] + HEALTH_STATE_READY: _ClassVar[HealthState] + HEALTH_STATE_DEGRADED: _ClassVar[HealthState] + HEALTH_STATE_DRAINING: _ClassVar[HealthState] + HEALTH_STATE_NOT_READY: _ClassVar[HealthState] + +class AbortStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ABORT_STATUS_UNSPECIFIED: _ClassVar[AbortStatus] + ABORT_STATUS_ABORTED: _ClassVar[AbortStatus] + ABORT_STATUS_ALREADY_FINISHED: _ClassVar[AbortStatus] + +class DrainState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + DRAIN_STATE_UNSPECIFIED: _ClassVar[DrainState] + DRAIN_STATE_STARTED: _ClassVar[DrainState] + DRAIN_STATE_IN_PROGRESS: _ClassVar[DrainState] + DRAIN_STATE_COMPLETE: _ClassVar[DrainState] +HEALTH_STATE_UNSPECIFIED: HealthState +HEALTH_STATE_STARTING: HealthState +HEALTH_STATE_READY: HealthState +HEALTH_STATE_DEGRADED: HealthState +HEALTH_STATE_DRAINING: HealthState +HEALTH_STATE_NOT_READY: HealthState +ABORT_STATUS_UNSPECIFIED: AbortStatus +ABORT_STATUS_ABORTED: AbortStatus +ABORT_STATUS_ALREADY_FINISHED: AbortStatus +DRAIN_STATE_UNSPECIFIED: DrainState +DRAIN_STATE_STARTED: DrainState +DRAIN_STATE_IN_PROGRESS: DrainState +DRAIN_STATE_COMPLETE: DrainState + +class HealthRequest(_message.Message): + __slots__ = ("include_inference_probe", "model", "role") + INCLUDE_INFERENCE_PROBE_FIELD_NUMBER: _ClassVar[int] + MODEL_FIELD_NUMBER: _ClassVar[int] + ROLE_FIELD_NUMBER: _ClassVar[int] + include_inference_probe: bool + model: str + role: _engine_pb2.EngineRole + def __init__(self, include_inference_probe: _Optional[bool] = ..., model: _Optional[str] = ..., role: _Optional[_Union[_engine_pb2.EngineRole, str]] = ...) -> None: ... + +class HealthResponse(_message.Message): + __slots__ = ("state", "checks") + STATE_FIELD_NUMBER: _ClassVar[int] + CHECKS_FIELD_NUMBER: _ClassVar[int] + state: HealthState + checks: _containers.RepeatedCompositeFieldContainer[HealthCheck] + def __init__(self, state: _Optional[_Union[HealthState, str]] = ..., checks: _Optional[_Iterable[_Union[HealthCheck, _Mapping]]] = ...) -> None: ... + +class HealthCheck(_message.Message): + __slots__ = ("name", "state", "message") + NAME_FIELD_NUMBER: _ClassVar[int] + STATE_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + name: str + state: HealthState + message: str + def __init__(self, name: _Optional[str] = ..., state: _Optional[_Union[HealthState, str]] = ..., message: _Optional[str] = ...) -> None: ... + +class AbortRequest(_message.Message): + __slots__ = ("request_id", "kv_session", "all_requests") + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + KV_SESSION_FIELD_NUMBER: _ClassVar[int] + ALL_REQUESTS_FIELD_NUMBER: _ClassVar[int] + request_id: str + kv_session: _kv_pb2.KvSessionRef + all_requests: AllRequests + def __init__(self, request_id: _Optional[str] = ..., kv_session: _Optional[_Union[_kv_pb2.KvSessionRef, _Mapping]] = ..., all_requests: _Optional[_Union[AllRequests, _Mapping]] = ...) -> None: ... + +class AllRequests(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class AbortResponse(_message.Message): + __slots__ = ("status", "message") + STATUS_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + status: AbortStatus + message: str + def __init__(self, status: _Optional[_Union[AbortStatus, str]] = ..., message: _Optional[str] = ...) -> None: ... + +class DrainRequest(_message.Message): + __slots__ = ("stop_accepting_new_requests", "deadline_ms", "abort_after_deadline") + STOP_ACCEPTING_NEW_REQUESTS_FIELD_NUMBER: _ClassVar[int] + DEADLINE_MS_FIELD_NUMBER: _ClassVar[int] + ABORT_AFTER_DEADLINE_FIELD_NUMBER: _ClassVar[int] + stop_accepting_new_requests: bool + deadline_ms: int + abort_after_deadline: bool + def __init__(self, stop_accepting_new_requests: _Optional[bool] = ..., deadline_ms: _Optional[int] = ..., abort_after_deadline: _Optional[bool] = ...) -> None: ... + +class DrainResponse(_message.Message): + __slots__ = ("state", "error", "in_flight_requests", "open_kv_sessions", "message") + STATE_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + IN_FLIGHT_REQUESTS_FIELD_NUMBER: _ClassVar[int] + OPEN_KV_SESSIONS_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + state: DrainState + error: _error_pb2.EngineError + in_flight_requests: int + open_kv_sessions: int + message: str + def __init__(self, state: _Optional[_Union[DrainState, str]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ..., in_flight_requests: _Optional[int] = ..., open_kv_sessions: _Optional[int] = ..., message: _Optional[str] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/lora_pb2.py b/packages/python/src/openengine/v1/lora_pb2.py new file mode 100644 index 0000000..a53d2a8 --- /dev/null +++ b/packages/python/src/openengine/v1/lora_pb2.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/lora.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/lora.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18openengine/v1/lora.proto\x12\ropenengine.v1\"F\n\x0bLoraAdapter\x12\x0f\n\x07lora_id\x18\x01 \x01(\x03\x12\x11\n\tlora_name\x18\x02 \x01(\t\x12\x13\n\x0bsource_path\x18\x03 \x01(\t\">\n\x0fLoadLoraRequest\x12+\n\x07\x61\x64\x61pter\x18\x01 \x01(\x0b\x32\x1a.openengine.v1.LoraAdapter\"W\n\x10LoadLoraResponse\x12+\n\x07\x61\x64\x61pter\x18\x01 \x01(\x0b\x32\x1a.openengine.v1.LoraAdapter\x12\x16\n\x0e\x61lready_loaded\x18\x02 \x01(\x08\"&\n\x11UnloadLoraRequest\x12\x11\n\tlora_name\x18\x01 \x01(\t\"A\n\x12UnloadLoraResponse\x12+\n\x07\x61\x64\x61pter\x18\x01 \x01(\x0b\x32\x1a.openengine.v1.LoraAdapter\"\x12\n\x10ListLorasRequest\"A\n\x11ListLorasResponse\x12,\n\x08\x61\x64\x61pters\x18\x01 \x03(\x0b\x32\x1a.openengine.v1.LoraAdapterb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.lora_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_LORAADAPTER']._serialized_start=43 + _globals['_LORAADAPTER']._serialized_end=113 + _globals['_LOADLORAREQUEST']._serialized_start=115 + _globals['_LOADLORAREQUEST']._serialized_end=177 + _globals['_LOADLORARESPONSE']._serialized_start=179 + _globals['_LOADLORARESPONSE']._serialized_end=266 + _globals['_UNLOADLORAREQUEST']._serialized_start=268 + _globals['_UNLOADLORAREQUEST']._serialized_end=306 + _globals['_UNLOADLORARESPONSE']._serialized_start=308 + _globals['_UNLOADLORARESPONSE']._serialized_end=373 + _globals['_LISTLORASREQUEST']._serialized_start=375 + _globals['_LISTLORASREQUEST']._serialized_end=393 + _globals['_LISTLORASRESPONSE']._serialized_start=395 + _globals['_LISTLORASRESPONSE']._serialized_end=460 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/lora_pb2.pyi b/packages/python/src/openengine/v1/lora_pb2.pyi new file mode 100644 index 0000000..e5a6064 --- /dev/null +++ b/packages/python/src/openengine/v1/lora_pb2.pyi @@ -0,0 +1,53 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class LoraAdapter(_message.Message): + __slots__ = ("lora_id", "lora_name", "source_path") + LORA_ID_FIELD_NUMBER: _ClassVar[int] + LORA_NAME_FIELD_NUMBER: _ClassVar[int] + SOURCE_PATH_FIELD_NUMBER: _ClassVar[int] + lora_id: int + lora_name: str + source_path: str + def __init__(self, lora_id: _Optional[int] = ..., lora_name: _Optional[str] = ..., source_path: _Optional[str] = ...) -> None: ... + +class LoadLoraRequest(_message.Message): + __slots__ = ("adapter",) + ADAPTER_FIELD_NUMBER: _ClassVar[int] + adapter: LoraAdapter + def __init__(self, adapter: _Optional[_Union[LoraAdapter, _Mapping]] = ...) -> None: ... + +class LoadLoraResponse(_message.Message): + __slots__ = ("adapter", "already_loaded") + ADAPTER_FIELD_NUMBER: _ClassVar[int] + ALREADY_LOADED_FIELD_NUMBER: _ClassVar[int] + adapter: LoraAdapter + already_loaded: bool + def __init__(self, adapter: _Optional[_Union[LoraAdapter, _Mapping]] = ..., already_loaded: _Optional[bool] = ...) -> None: ... + +class UnloadLoraRequest(_message.Message): + __slots__ = ("lora_name",) + LORA_NAME_FIELD_NUMBER: _ClassVar[int] + lora_name: str + def __init__(self, lora_name: _Optional[str] = ...) -> None: ... + +class UnloadLoraResponse(_message.Message): + __slots__ = ("adapter",) + ADAPTER_FIELD_NUMBER: _ClassVar[int] + adapter: LoraAdapter + def __init__(self, adapter: _Optional[_Union[LoraAdapter, _Mapping]] = ...) -> None: ... + +class ListLorasRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListLorasResponse(_message.Message): + __slots__ = ("adapters",) + ADAPTERS_FIELD_NUMBER: _ClassVar[int] + adapters: _containers.RepeatedCompositeFieldContainer[LoraAdapter] + def __init__(self, adapters: _Optional[_Iterable[_Union[LoraAdapter, _Mapping]]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/model_pb2.py b/packages/python/src/openengine/v1/model_pb2.py new file mode 100644 index 0000000..dab46f0 --- /dev/null +++ b/packages/python/src/openengine/v1/model_pb2.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/model.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/model.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19openengine/v1/model.proto\x12\ropenengine.v1\"$\n\x13GetModelInfoRequest\x12\r\n\x05model\x18\x01 \x01(\t\"\x86\x06\n\tModelInfo\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12\x19\n\x11served_model_name\x18\x02 \x01(\t\x12\x1c\n\x14served_model_aliases\x18\x03 \x03(\t\x12\x1f\n\x12max_context_length\x18\x04 \x01(\rH\x00\x88\x01\x01\x12\x1e\n\x11max_output_tokens\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\x1a\n\rkv_block_size\x18\x06 \x01(\rH\x02\x88\x01\x01\x12\x1c\n\x0ftotal_kv_blocks\x18\x07 \x01(\x04H\x03\x88\x01\x01\x12!\n\x14max_running_requests\x18\x08 \x01(\x04H\x04\x88\x01\x01\x12\x1f\n\x12max_batched_tokens\x18\t \x01(\x04H\x05\x88\x01\x01\x12\x17\n\x0ftokenizer_modes\x18\n \x03(\t\x12 \n\x13supports_text_input\x18\x14 \x01(\x08H\x06\x88\x01\x01\x12%\n\x18supports_token_ids_input\x18\x15 \x01(\x08H\x07\x88\x01\x01\x12\x39\n\ngeneration\x18\x16 \x01(\x0b\x32%.openengine.v1.GenerationCapabilities\x12\x1a\n\rsupports_lora\x18\x17 \x01(\x08H\x08\x88\x01\x01\x12 \n\x13supports_multimodal\x18\x18 \x01(\x08H\t\x88\x01\x01\x12\x18\n\x10reasoning_parser\x18\x19 \x01(\t\x12\x18\n\x10tool_call_parser\x18\x1a \x01(\tB\x15\n\x13_max_context_lengthB\x14\n\x12_max_output_tokensB\x10\n\x0e_kv_block_sizeB\x12\n\x10_total_kv_blocksB\x17\n\x15_max_running_requestsB\x15\n\x13_max_batched_tokensB\x16\n\x14_supports_text_inputB\x1b\n\x19_supports_token_ids_inputB\x10\n\x0e_supports_loraB\x16\n\x14_supports_multimodal\"\x8a\x04\n\x16GenerationCapabilities\x12;\n\x0fprompt_logprobs\x18\x01 \x01(\x0b\x32\".openengine.v1.LogprobCapabilities\x12;\n\x0foutput_logprobs\x18\x02 \x01(\x0b\x32\".openengine.v1.LogprobCapabilities\x12\x42\n\x0fguided_decoding\x18\x03 \x01(\x0b\x32).openengine.v1.GuidedDecodingCapabilities\x12\x1e\n\x11max_num_sequences\x18\x04 \x01(\rH\x00\x88\x01\x01\x12\x1e\n\x11supports_priority\x18\x05 \x01(\x08H\x01\x88\x01\x01\x12$\n\x17supports_stop_in_output\x18\x06 \x01(\x08H\x02\x88\x01\x01\x12 \n\x13supports_cache_salt\x18\x07 \x01(\x08H\x03\x88\x01\x01\x12)\n\x1csupports_prefix_cache_bypass\x18\x08 \x01(\x08H\x04\x88\x01\x01\x42\x14\n\x12_max_num_sequencesB\x14\n\x12_supports_priorityB\x1a\n\x18_supports_stop_in_outputB\x16\n\x14_supports_cache_saltB\x1f\n\x1d_supports_prefix_cache_bypass\"\xb0\x01\n\x13LogprobCapabilities\x12\x16\n\tsupported\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12M\n\x19\x63\x61ndidate_selection_modes\x18\x02 \x03(\x0e\x32*.openengine.v1.CandidateTokenSelectionMode\x12\x16\n\tmax_top_n\x18\x03 \x01(\rH\x01\x88\x01\x01\x42\x0c\n\n_supportedB\x0c\n\n_max_top_n\"t\n\x1aGuidedDecodingCapabilities\x12\x16\n\tsupported\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x30\n\x05modes\x18\x02 \x03(\x0e\x32!.openengine.v1.GuidedDecodingModeB\x0c\n\n_supported*\xcd\x01\n\x1b\x43\x61ndidateTokenSelectionMode\x12.\n*CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED\x10\x00\x12(\n$CANDIDATE_TOKEN_SELECTION_MODE_TOP_N\x10\x01\x12,\n(CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS\x10\x02\x12&\n\"CANDIDATE_TOKEN_SELECTION_MODE_ALL\x10\x03*\x97\x02\n\x12GuidedDecodingMode\x12$\n GUIDED_DECODING_MODE_UNSPECIFIED\x10\x00\x12$\n GUIDED_DECODING_MODE_JSON_SCHEMA\x10\x01\x12\x1e\n\x1aGUIDED_DECODING_MODE_REGEX\x10\x02\x12%\n!GUIDED_DECODING_MODE_EBNF_GRAMMAR\x10\x03\x12\'\n#GUIDED_DECODING_MODE_STRUCTURAL_TAG\x10\x04\x12\x1f\n\x1bGUIDED_DECODING_MODE_CHOICE\x10\x05\x12$\n GUIDED_DECODING_MODE_JSON_OBJECT\x10\x06\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.model_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CANDIDATETOKENSELECTIONMODE']._serialized_start=1682 + _globals['_CANDIDATETOKENSELECTIONMODE']._serialized_end=1887 + _globals['_GUIDEDDECODINGMODE']._serialized_start=1890 + _globals['_GUIDEDDECODINGMODE']._serialized_end=2169 + _globals['_GETMODELINFOREQUEST']._serialized_start=44 + _globals['_GETMODELINFOREQUEST']._serialized_end=80 + _globals['_MODELINFO']._serialized_start=83 + _globals['_MODELINFO']._serialized_end=857 + _globals['_GENERATIONCAPABILITIES']._serialized_start=860 + _globals['_GENERATIONCAPABILITIES']._serialized_end=1382 + _globals['_LOGPROBCAPABILITIES']._serialized_start=1385 + _globals['_LOGPROBCAPABILITIES']._serialized_end=1561 + _globals['_GUIDEDDECODINGCAPABILITIES']._serialized_start=1563 + _globals['_GUIDEDDECODINGCAPABILITIES']._serialized_end=1679 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/model_pb2.pyi b/packages/python/src/openengine/v1/model_pb2.pyi new file mode 100644 index 0000000..27779fc --- /dev/null +++ b/packages/python/src/openengine/v1/model_pb2.pyi @@ -0,0 +1,118 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class CandidateTokenSelectionMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED: _ClassVar[CandidateTokenSelectionMode] + CANDIDATE_TOKEN_SELECTION_MODE_TOP_N: _ClassVar[CandidateTokenSelectionMode] + CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS: _ClassVar[CandidateTokenSelectionMode] + CANDIDATE_TOKEN_SELECTION_MODE_ALL: _ClassVar[CandidateTokenSelectionMode] + +class GuidedDecodingMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + GUIDED_DECODING_MODE_UNSPECIFIED: _ClassVar[GuidedDecodingMode] + GUIDED_DECODING_MODE_JSON_SCHEMA: _ClassVar[GuidedDecodingMode] + GUIDED_DECODING_MODE_REGEX: _ClassVar[GuidedDecodingMode] + GUIDED_DECODING_MODE_EBNF_GRAMMAR: _ClassVar[GuidedDecodingMode] + GUIDED_DECODING_MODE_STRUCTURAL_TAG: _ClassVar[GuidedDecodingMode] + GUIDED_DECODING_MODE_CHOICE: _ClassVar[GuidedDecodingMode] + GUIDED_DECODING_MODE_JSON_OBJECT: _ClassVar[GuidedDecodingMode] +CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED: CandidateTokenSelectionMode +CANDIDATE_TOKEN_SELECTION_MODE_TOP_N: CandidateTokenSelectionMode +CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS: CandidateTokenSelectionMode +CANDIDATE_TOKEN_SELECTION_MODE_ALL: CandidateTokenSelectionMode +GUIDED_DECODING_MODE_UNSPECIFIED: GuidedDecodingMode +GUIDED_DECODING_MODE_JSON_SCHEMA: GuidedDecodingMode +GUIDED_DECODING_MODE_REGEX: GuidedDecodingMode +GUIDED_DECODING_MODE_EBNF_GRAMMAR: GuidedDecodingMode +GUIDED_DECODING_MODE_STRUCTURAL_TAG: GuidedDecodingMode +GUIDED_DECODING_MODE_CHOICE: GuidedDecodingMode +GUIDED_DECODING_MODE_JSON_OBJECT: GuidedDecodingMode + +class GetModelInfoRequest(_message.Message): + __slots__ = ("model",) + MODEL_FIELD_NUMBER: _ClassVar[int] + model: str + def __init__(self, model: _Optional[str] = ...) -> None: ... + +class ModelInfo(_message.Message): + __slots__ = ("model_id", "served_model_name", "served_model_aliases", "max_context_length", "max_output_tokens", "kv_block_size", "total_kv_blocks", "max_running_requests", "max_batched_tokens", "tokenizer_modes", "supports_text_input", "supports_token_ids_input", "generation", "supports_lora", "supports_multimodal", "reasoning_parser", "tool_call_parser") + MODEL_ID_FIELD_NUMBER: _ClassVar[int] + SERVED_MODEL_NAME_FIELD_NUMBER: _ClassVar[int] + SERVED_MODEL_ALIASES_FIELD_NUMBER: _ClassVar[int] + MAX_CONTEXT_LENGTH_FIELD_NUMBER: _ClassVar[int] + MAX_OUTPUT_TOKENS_FIELD_NUMBER: _ClassVar[int] + KV_BLOCK_SIZE_FIELD_NUMBER: _ClassVar[int] + TOTAL_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] + MAX_RUNNING_REQUESTS_FIELD_NUMBER: _ClassVar[int] + MAX_BATCHED_TOKENS_FIELD_NUMBER: _ClassVar[int] + TOKENIZER_MODES_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_TEXT_INPUT_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_TOKEN_IDS_INPUT_FIELD_NUMBER: _ClassVar[int] + GENERATION_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_LORA_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_MULTIMODAL_FIELD_NUMBER: _ClassVar[int] + REASONING_PARSER_FIELD_NUMBER: _ClassVar[int] + TOOL_CALL_PARSER_FIELD_NUMBER: _ClassVar[int] + model_id: str + served_model_name: str + served_model_aliases: _containers.RepeatedScalarFieldContainer[str] + max_context_length: int + max_output_tokens: int + kv_block_size: int + total_kv_blocks: int + max_running_requests: int + max_batched_tokens: int + tokenizer_modes: _containers.RepeatedScalarFieldContainer[str] + supports_text_input: bool + supports_token_ids_input: bool + generation: GenerationCapabilities + supports_lora: bool + supports_multimodal: bool + reasoning_parser: str + tool_call_parser: str + def __init__(self, model_id: _Optional[str] = ..., served_model_name: _Optional[str] = ..., served_model_aliases: _Optional[_Iterable[str]] = ..., max_context_length: _Optional[int] = ..., max_output_tokens: _Optional[int] = ..., kv_block_size: _Optional[int] = ..., total_kv_blocks: _Optional[int] = ..., max_running_requests: _Optional[int] = ..., max_batched_tokens: _Optional[int] = ..., tokenizer_modes: _Optional[_Iterable[str]] = ..., supports_text_input: _Optional[bool] = ..., supports_token_ids_input: _Optional[bool] = ..., generation: _Optional[_Union[GenerationCapabilities, _Mapping]] = ..., supports_lora: _Optional[bool] = ..., supports_multimodal: _Optional[bool] = ..., reasoning_parser: _Optional[str] = ..., tool_call_parser: _Optional[str] = ...) -> None: ... + +class GenerationCapabilities(_message.Message): + __slots__ = ("prompt_logprobs", "output_logprobs", "guided_decoding", "max_num_sequences", "supports_priority", "supports_stop_in_output", "supports_cache_salt", "supports_prefix_cache_bypass") + PROMPT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] + OUTPUT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] + GUIDED_DECODING_FIELD_NUMBER: _ClassVar[int] + MAX_NUM_SEQUENCES_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_PRIORITY_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_STOP_IN_OUTPUT_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_CACHE_SALT_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_PREFIX_CACHE_BYPASS_FIELD_NUMBER: _ClassVar[int] + prompt_logprobs: LogprobCapabilities + output_logprobs: LogprobCapabilities + guided_decoding: GuidedDecodingCapabilities + max_num_sequences: int + supports_priority: bool + supports_stop_in_output: bool + supports_cache_salt: bool + supports_prefix_cache_bypass: bool + def __init__(self, prompt_logprobs: _Optional[_Union[LogprobCapabilities, _Mapping]] = ..., output_logprobs: _Optional[_Union[LogprobCapabilities, _Mapping]] = ..., guided_decoding: _Optional[_Union[GuidedDecodingCapabilities, _Mapping]] = ..., max_num_sequences: _Optional[int] = ..., supports_priority: _Optional[bool] = ..., supports_stop_in_output: _Optional[bool] = ..., supports_cache_salt: _Optional[bool] = ..., supports_prefix_cache_bypass: _Optional[bool] = ...) -> None: ... + +class LogprobCapabilities(_message.Message): + __slots__ = ("supported", "candidate_selection_modes", "max_top_n") + SUPPORTED_FIELD_NUMBER: _ClassVar[int] + CANDIDATE_SELECTION_MODES_FIELD_NUMBER: _ClassVar[int] + MAX_TOP_N_FIELD_NUMBER: _ClassVar[int] + supported: bool + candidate_selection_modes: _containers.RepeatedScalarFieldContainer[CandidateTokenSelectionMode] + max_top_n: int + def __init__(self, supported: _Optional[bool] = ..., candidate_selection_modes: _Optional[_Iterable[_Union[CandidateTokenSelectionMode, str]]] = ..., max_top_n: _Optional[int] = ...) -> None: ... + +class GuidedDecodingCapabilities(_message.Message): + __slots__ = ("supported", "modes") + SUPPORTED_FIELD_NUMBER: _ClassVar[int] + MODES_FIELD_NUMBER: _ClassVar[int] + supported: bool + modes: _containers.RepeatedScalarFieldContainer[GuidedDecodingMode] + def __init__(self, supported: _Optional[bool] = ..., modes: _Optional[_Iterable[_Union[GuidedDecodingMode, str]]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/observability_pb2.py b/packages/python/src/openengine/v1/observability_pb2.py new file mode 100644 index 0000000..63ede5f --- /dev/null +++ b/packages/python/src/openengine/v1/observability_pb2.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/observability.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/observability.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!openengine/v1/observability.proto\x12\ropenengine.v1\x1a\x19openengine/v1/error.proto\"*\n\x0eGetLoadRequest\x12\x18\n\x10include_per_rank\x18\x01 \x01(\x08\"\xc5\x05\n\x08LoadInfo\x12\x13\n\x0binstance_id\x18\x01 \x01(\t\x12!\n\x14timestamp_unix_nanos\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x1d\n\x10running_requests\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x1c\n\x0fqueued_requests\x18\x04 \x01(\rH\x02\x88\x01\x01\x12\x1f\n\x12\x61\x63tive_kv_sessions\x18\x05 \x01(\rH\x03\x88\x01\x01\x12\x1b\n\x0eused_kv_blocks\x18\x06 \x01(\x04H\x04\x88\x01\x01\x12\x1c\n\x0ftotal_kv_blocks\x18\x07 \x01(\x04H\x05\x88\x01\x01\x12\x1b\n\x0erunning_tokens\x18\x08 \x01(\x04H\x06\x88\x01\x01\x12\x1b\n\x0ewaiting_tokens\x18\t \x01(\x04H\x07\x88\x01\x01\x12\x1f\n\x12prefill_batch_size\x18\n \x01(\rH\x08\x88\x01\x01\x12\x1e\n\x11\x64\x65\x63ode_batch_size\x18\x0b \x01(\rH\t\x88\x01\x01\x12*\n\x05ranks\x18\x14 \x03(\x0b\x32\x1b.openengine.v1.RankLoadInfo\x12;\n\nattributes\x18\x1e \x03(\x0b\x32\'.openengine.v1.LoadInfo.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x15_timestamp_unix_nanosB\x13\n\x11_running_requestsB\x12\n\x10_queued_requestsB\x15\n\x13_active_kv_sessionsB\x11\n\x0f_used_kv_blocksB\x12\n\x10_total_kv_blocksB\x11\n\x0f_running_tokensB\x11\n\x0f_waiting_tokensB\x15\n\x13_prefill_batch_sizeB\x14\n\x12_decode_batch_size\"\xfc\x02\n\x0cRankLoadInfo\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x1d\n\x10running_requests\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1c\n\x0fqueued_requests\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x1b\n\x0eused_kv_blocks\x18\x04 \x01(\x04H\x03\x88\x01\x01\x12\x1c\n\x0ftotal_kv_blocks\x18\x05 \x01(\x04H\x04\x88\x01\x01\x12\x1f\n\x12prefill_batch_size\x18\x06 \x01(\rH\x05\x88\x01\x01\x12\x1e\n\x11\x64\x65\x63ode_batch_size\x18\x07 \x01(\rH\x06\x88\x01\x01\x42\x15\n\x13_data_parallel_rankB\x13\n\x11_running_requestsB\x12\n\x10_queued_requestsB\x11\n\x0f_used_kv_blocksB\x12\n\x10_total_kv_blocksB\x15\n\x13_prefill_batch_sizeB\x14\n\x12_decode_batch_size\"O\n\x1dSubscribeRuntimeEventsRequest\x12.\n\x05types\x18\x01 \x03(\x0e\x32\x1f.openengine.v1.RuntimeEventType\"\x8c\x01\n\x1eSubscribeRuntimeEventsResponse\x12\x34\n\rruntime_event\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.RuntimeEventH\x00\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x42\x07\n\x05\x65vent\"\xe1\x01\n\x0cRuntimeEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\t\x12\x1c\n\x14timestamp_unix_nanos\x18\x02 \x01(\x04\x12-\n\x04type\x18\x03 \x01(\x0e\x32\x1f.openengine.v1.RuntimeEventType\x12?\n\nattributes\x18\x04 \x03(\x0b\x32+.openengine.v1.RuntimeEvent.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01*\xb8\x01\n\x10RuntimeEventType\x12\"\n\x1eRUNTIME_EVENT_TYPE_UNSPECIFIED\x10\x00\x12#\n\x1fRUNTIME_EVENT_TYPE_FORWARD_PASS\x10\x01\x12\x1c\n\x18RUNTIME_EVENT_TYPE_BATCH\x10\x02\x12\x1c\n\x18RUNTIME_EVENT_TYPE_QUEUE\x10\x03\x12\x1f\n\x1bRUNTIME_EVENT_TYPE_TRANSFER\x10\x04\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.observability_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_LOADINFO_ATTRIBUTESENTRY']._loaded_options = None + _globals['_LOADINFO_ATTRIBUTESENTRY']._serialized_options = b'8\001' + _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._loaded_options = None + _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._serialized_options = b'8\001' + _globals['_RUNTIMEEVENTTYPE']._serialized_start=1671 + _globals['_RUNTIMEEVENTTYPE']._serialized_end=1855 + _globals['_GETLOADREQUEST']._serialized_start=79 + _globals['_GETLOADREQUEST']._serialized_end=121 + _globals['_LOADINFO']._serialized_start=124 + _globals['_LOADINFO']._serialized_end=833 + _globals['_LOADINFO_ATTRIBUTESENTRY']._serialized_start=573 + _globals['_LOADINFO_ATTRIBUTESENTRY']._serialized_end=622 + _globals['_RANKLOADINFO']._serialized_start=836 + _globals['_RANKLOADINFO']._serialized_end=1216 + _globals['_SUBSCRIBERUNTIMEEVENTSREQUEST']._serialized_start=1218 + _globals['_SUBSCRIBERUNTIMEEVENTSREQUEST']._serialized_end=1297 + _globals['_SUBSCRIBERUNTIMEEVENTSRESPONSE']._serialized_start=1300 + _globals['_SUBSCRIBERUNTIMEEVENTSRESPONSE']._serialized_end=1440 + _globals['_RUNTIMEEVENT']._serialized_start=1443 + _globals['_RUNTIMEEVENT']._serialized_end=1668 + _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._serialized_start=573 + _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._serialized_end=622 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/observability_pb2.pyi b/packages/python/src/openengine/v1/observability_pb2.pyi new file mode 100644 index 0000000..7b4de09 --- /dev/null +++ b/packages/python/src/openengine/v1/observability_pb2.pyi @@ -0,0 +1,116 @@ +from openengine.v1 import error_pb2 as _error_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class RuntimeEventType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + RUNTIME_EVENT_TYPE_UNSPECIFIED: _ClassVar[RuntimeEventType] + RUNTIME_EVENT_TYPE_FORWARD_PASS: _ClassVar[RuntimeEventType] + RUNTIME_EVENT_TYPE_BATCH: _ClassVar[RuntimeEventType] + RUNTIME_EVENT_TYPE_QUEUE: _ClassVar[RuntimeEventType] + RUNTIME_EVENT_TYPE_TRANSFER: _ClassVar[RuntimeEventType] +RUNTIME_EVENT_TYPE_UNSPECIFIED: RuntimeEventType +RUNTIME_EVENT_TYPE_FORWARD_PASS: RuntimeEventType +RUNTIME_EVENT_TYPE_BATCH: RuntimeEventType +RUNTIME_EVENT_TYPE_QUEUE: RuntimeEventType +RUNTIME_EVENT_TYPE_TRANSFER: RuntimeEventType + +class GetLoadRequest(_message.Message): + __slots__ = ("include_per_rank",) + INCLUDE_PER_RANK_FIELD_NUMBER: _ClassVar[int] + include_per_rank: bool + def __init__(self, include_per_rank: _Optional[bool] = ...) -> None: ... + +class LoadInfo(_message.Message): + __slots__ = ("instance_id", "timestamp_unix_nanos", "running_requests", "queued_requests", "active_kv_sessions", "used_kv_blocks", "total_kv_blocks", "running_tokens", "waiting_tokens", "prefill_batch_size", "decode_batch_size", "ranks", "attributes") + class AttributesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + INSTANCE_ID_FIELD_NUMBER: _ClassVar[int] + TIMESTAMP_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] + RUNNING_REQUESTS_FIELD_NUMBER: _ClassVar[int] + QUEUED_REQUESTS_FIELD_NUMBER: _ClassVar[int] + ACTIVE_KV_SESSIONS_FIELD_NUMBER: _ClassVar[int] + USED_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] + TOTAL_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] + RUNNING_TOKENS_FIELD_NUMBER: _ClassVar[int] + WAITING_TOKENS_FIELD_NUMBER: _ClassVar[int] + PREFILL_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] + DECODE_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] + RANKS_FIELD_NUMBER: _ClassVar[int] + ATTRIBUTES_FIELD_NUMBER: _ClassVar[int] + instance_id: str + timestamp_unix_nanos: int + running_requests: int + queued_requests: int + active_kv_sessions: int + used_kv_blocks: int + total_kv_blocks: int + running_tokens: int + waiting_tokens: int + prefill_batch_size: int + decode_batch_size: int + ranks: _containers.RepeatedCompositeFieldContainer[RankLoadInfo] + attributes: _containers.ScalarMap[str, str] + def __init__(self, instance_id: _Optional[str] = ..., timestamp_unix_nanos: _Optional[int] = ..., running_requests: _Optional[int] = ..., queued_requests: _Optional[int] = ..., active_kv_sessions: _Optional[int] = ..., used_kv_blocks: _Optional[int] = ..., total_kv_blocks: _Optional[int] = ..., running_tokens: _Optional[int] = ..., waiting_tokens: _Optional[int] = ..., prefill_batch_size: _Optional[int] = ..., decode_batch_size: _Optional[int] = ..., ranks: _Optional[_Iterable[_Union[RankLoadInfo, _Mapping]]] = ..., attributes: _Optional[_Mapping[str, str]] = ...) -> None: ... + +class RankLoadInfo(_message.Message): + __slots__ = ("data_parallel_rank", "running_requests", "queued_requests", "used_kv_blocks", "total_kv_blocks", "prefill_batch_size", "decode_batch_size") + DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] + RUNNING_REQUESTS_FIELD_NUMBER: _ClassVar[int] + QUEUED_REQUESTS_FIELD_NUMBER: _ClassVar[int] + USED_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] + TOTAL_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] + PREFILL_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] + DECODE_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] + data_parallel_rank: int + running_requests: int + queued_requests: int + used_kv_blocks: int + total_kv_blocks: int + prefill_batch_size: int + decode_batch_size: int + def __init__(self, data_parallel_rank: _Optional[int] = ..., running_requests: _Optional[int] = ..., queued_requests: _Optional[int] = ..., used_kv_blocks: _Optional[int] = ..., total_kv_blocks: _Optional[int] = ..., prefill_batch_size: _Optional[int] = ..., decode_batch_size: _Optional[int] = ...) -> None: ... + +class SubscribeRuntimeEventsRequest(_message.Message): + __slots__ = ("types",) + TYPES_FIELD_NUMBER: _ClassVar[int] + types: _containers.RepeatedScalarFieldContainer[RuntimeEventType] + def __init__(self, types: _Optional[_Iterable[_Union[RuntimeEventType, str]]] = ...) -> None: ... + +class SubscribeRuntimeEventsResponse(_message.Message): + __slots__ = ("runtime_event", "error") + RUNTIME_EVENT_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + runtime_event: RuntimeEvent + error: _error_pb2.EngineError + def __init__(self, runtime_event: _Optional[_Union[RuntimeEvent, _Mapping]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ...) -> None: ... + +class RuntimeEvent(_message.Message): + __slots__ = ("event_id", "timestamp_unix_nanos", "type", "attributes") + class AttributesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + EVENT_ID_FIELD_NUMBER: _ClassVar[int] + TIMESTAMP_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] + TYPE_FIELD_NUMBER: _ClassVar[int] + ATTRIBUTES_FIELD_NUMBER: _ClassVar[int] + event_id: str + timestamp_unix_nanos: int + type: RuntimeEventType + attributes: _containers.ScalarMap[str, str] + def __init__(self, event_id: _Optional[str] = ..., timestamp_unix_nanos: _Optional[int] = ..., type: _Optional[_Union[RuntimeEventType, str]] = ..., attributes: _Optional[_Mapping[str, str]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/openengine_pb2.py b/packages/python/src/openengine/v1/openengine_pb2.py new file mode 100644 index 0000000..8fc18d7 --- /dev/null +++ b/packages/python/src/openengine/v1/openengine_pb2.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: openengine/v1/openengine.proto +# Protobuf Python Version: 6.33.5 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + '', + 'openengine/v1/openengine.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from openengine.v1 import engine_pb2 as openengine_dot_v1_dot_engine__pb2 +from openengine.v1 import generation_pb2 as openengine_dot_v1_dot_generation__pb2 +from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 +from openengine.v1 import lifecycle_pb2 as openengine_dot_v1_dot_lifecycle__pb2 +from openengine.v1 import lora_pb2 as openengine_dot_v1_dot_lora__pb2 +from openengine.v1 import model_pb2 as openengine_dot_v1_dot_model__pb2 +from openengine.v1 import observability_pb2 as openengine_dot_v1_dot_observability__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eopenengine/v1/openengine.proto\x12\ropenengine.v1\x1a\x1aopenengine/v1/engine.proto\x1a\x1eopenengine/v1/generation.proto\x1a\x16openengine/v1/kv.proto\x1a\x1dopenengine/v1/lifecycle.proto\x1a\x18openengine/v1/lora.proto\x1a\x19openengine/v1/model.proto\x1a!openengine/v1/observability.proto2\xa9\t\n\nOpenEngine\x12M\n\x08Generate\x12\x1e.openengine.v1.GenerateRequest\x1a\x1f.openengine.v1.GenerateResponse0\x01\x12O\n\rGetEngineInfo\x12#.openengine.v1.GetEngineInfoRequest\x1a\x19.openengine.v1.EngineInfo\x12L\n\x0cGetModelInfo\x12\".openengine.v1.GetModelInfoRequest\x1a\x18.openengine.v1.ModelInfo\x12\x41\n\x07GetLoad\x12\x1d.openengine.v1.GetLoadRequest\x1a\x17.openengine.v1.LoadInfo\x12\x45\n\x06Health\x12\x1c.openengine.v1.HealthRequest\x1a\x1d.openengine.v1.HealthResponse\x12\x42\n\x05\x41\x62ort\x12\x1b.openengine.v1.AbortRequest\x1a\x1c.openengine.v1.AbortResponse\x12\x44\n\x05\x44rain\x12\x1b.openengine.v1.DrainRequest\x1a\x1c.openengine.v1.DrainResponse0\x01\x12K\n\x08LoadLora\x12\x1e.openengine.v1.LoadLoraRequest\x1a\x1f.openengine.v1.LoadLoraResponse\x12Q\n\nUnloadLora\x12 .openengine.v1.UnloadLoraRequest\x1a!.openengine.v1.UnloadLoraResponse\x12N\n\tListLoras\x12\x1f.openengine.v1.ListLorasRequest\x1a .openengine.v1.ListLorasResponse\x12^\n\x12GetKvConnectorInfo\x12(.openengine.v1.GetKvConnectorInfoRequest\x1a\x1e.openengine.v1.KvConnectorInfo\x12\x66\n\x11GetKvEventSources\x12\'.openengine.v1.GetKvEventSourcesRequest\x1a(.openengine.v1.GetKvEventSourcesResponse\x12h\n\x11SubscribeKvEvents\x12\'.openengine.v1.SubscribeKvEventsRequest\x1a(.openengine.v1.SubscribeKvEventsResponse0\x01\x12w\n\x16SubscribeRuntimeEvents\x12,.openengine.v1.SubscribeRuntimeEventsRequest\x1a-.openengine.v1.SubscribeRuntimeEventsResponse0\x01\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.openengine_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_OPENENGINE']._serialized_start=253 + _globals['_OPENENGINE']._serialized_end=1446 +# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/openengine_pb2.pyi b/packages/python/src/openengine/v1/openengine_pb2.pyi new file mode 100644 index 0000000..27db98d --- /dev/null +++ b/packages/python/src/openengine/v1/openengine_pb2.pyi @@ -0,0 +1,11 @@ +from openengine.v1 import engine_pb2 as _engine_pb2 +from openengine.v1 import generation_pb2 as _generation_pb2 +from openengine.v1 import kv_pb2 as _kv_pb2 +from openengine.v1 import lifecycle_pb2 as _lifecycle_pb2 +from openengine.v1 import lora_pb2 as _lora_pb2 +from openengine.v1 import model_pb2 as _model_pb2 +from openengine.v1 import observability_pb2 as _observability_pb2 +from google.protobuf import descriptor as _descriptor +from typing import ClassVar as _ClassVar + +DESCRIPTOR: _descriptor.FileDescriptor diff --git a/packages/python/src/openengine/v1/openengine_pb2_grpc.py b/packages/python/src/openengine/v1/openengine_pb2_grpc.py new file mode 100644 index 0000000..3290cac --- /dev/null +++ b/packages/python/src/openengine/v1/openengine_pb2_grpc.py @@ -0,0 +1,668 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + +from openengine.v1 import engine_pb2 as openengine_dot_v1_dot_engine__pb2 +from openengine.v1 import generation_pb2 as openengine_dot_v1_dot_generation__pb2 +from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 +from openengine.v1 import lifecycle_pb2 as openengine_dot_v1_dot_lifecycle__pb2 +from openengine.v1 import lora_pb2 as openengine_dot_v1_dot_lora__pb2 +from openengine.v1 import model_pb2 as openengine_dot_v1_dot_model__pb2 +from openengine.v1 import observability_pb2 as openengine_dot_v1_dot_observability__pb2 + +GRPC_GENERATED_VERSION = '1.81.1' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in openengine/v1/openengine_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) + + +class OpenEngineStub: + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Generate = channel.unary_stream( + '/openengine.v1.OpenEngine/Generate', + request_serializer=openengine_dot_v1_dot_generation__pb2.GenerateRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_generation__pb2.GenerateResponse.FromString, + _registered_method=True) + self.GetEngineInfo = channel.unary_unary( + '/openengine.v1.OpenEngine/GetEngineInfo', + request_serializer=openengine_dot_v1_dot_engine__pb2.GetEngineInfoRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_engine__pb2.EngineInfo.FromString, + _registered_method=True) + self.GetModelInfo = channel.unary_unary( + '/openengine.v1.OpenEngine/GetModelInfo', + request_serializer=openengine_dot_v1_dot_model__pb2.GetModelInfoRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_model__pb2.ModelInfo.FromString, + _registered_method=True) + self.GetLoad = channel.unary_unary( + '/openengine.v1.OpenEngine/GetLoad', + request_serializer=openengine_dot_v1_dot_observability__pb2.GetLoadRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_observability__pb2.LoadInfo.FromString, + _registered_method=True) + self.Health = channel.unary_unary( + '/openengine.v1.OpenEngine/Health', + request_serializer=openengine_dot_v1_dot_lifecycle__pb2.HealthRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_lifecycle__pb2.HealthResponse.FromString, + _registered_method=True) + self.Abort = channel.unary_unary( + '/openengine.v1.OpenEngine/Abort', + request_serializer=openengine_dot_v1_dot_lifecycle__pb2.AbortRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_lifecycle__pb2.AbortResponse.FromString, + _registered_method=True) + self.Drain = channel.unary_stream( + '/openengine.v1.OpenEngine/Drain', + request_serializer=openengine_dot_v1_dot_lifecycle__pb2.DrainRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_lifecycle__pb2.DrainResponse.FromString, + _registered_method=True) + self.LoadLora = channel.unary_unary( + '/openengine.v1.OpenEngine/LoadLora', + request_serializer=openengine_dot_v1_dot_lora__pb2.LoadLoraRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_lora__pb2.LoadLoraResponse.FromString, + _registered_method=True) + self.UnloadLora = channel.unary_unary( + '/openengine.v1.OpenEngine/UnloadLora', + request_serializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraResponse.FromString, + _registered_method=True) + self.ListLoras = channel.unary_unary( + '/openengine.v1.OpenEngine/ListLoras', + request_serializer=openengine_dot_v1_dot_lora__pb2.ListLorasRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_lora__pb2.ListLorasResponse.FromString, + _registered_method=True) + self.GetKvConnectorInfo = channel.unary_unary( + '/openengine.v1.OpenEngine/GetKvConnectorInfo', + request_serializer=openengine_dot_v1_dot_kv__pb2.GetKvConnectorInfoRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_kv__pb2.KvConnectorInfo.FromString, + _registered_method=True) + self.GetKvEventSources = channel.unary_unary( + '/openengine.v1.OpenEngine/GetKvEventSources', + request_serializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesResponse.FromString, + _registered_method=True) + self.SubscribeKvEvents = channel.unary_stream( + '/openengine.v1.OpenEngine/SubscribeKvEvents', + request_serializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsResponse.FromString, + _registered_method=True) + self.SubscribeRuntimeEvents = channel.unary_stream( + '/openengine.v1.OpenEngine/SubscribeRuntimeEvents', + request_serializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsRequest.SerializeToString, + response_deserializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsResponse.FromString, + _registered_method=True) + + +class OpenEngineServicer: + """Missing associated documentation comment in .proto file.""" + + def Generate(self, request, context): + """Core inference path. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetEngineInfo(self, request, context): + """Runtime metadata and scheduling state. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetModelInfo(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetLoad(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Health(self, request, context): + """Health and lifecycle. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Abort(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Drain(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def LoadLora(self, request, context): + """LoRA lifecycle. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UnloadLora(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListLoras(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetKvConnectorInfo(self, request, context): + """Disaggregated serving / KV transfer. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetKvEventSources(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def SubscribeKvEvents(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def SubscribeRuntimeEvents(self, request, context): + """Structured runtime events for planners/controllers. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_OpenEngineServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Generate': grpc.unary_stream_rpc_method_handler( + servicer.Generate, + request_deserializer=openengine_dot_v1_dot_generation__pb2.GenerateRequest.FromString, + response_serializer=openengine_dot_v1_dot_generation__pb2.GenerateResponse.SerializeToString, + ), + 'GetEngineInfo': grpc.unary_unary_rpc_method_handler( + servicer.GetEngineInfo, + request_deserializer=openengine_dot_v1_dot_engine__pb2.GetEngineInfoRequest.FromString, + response_serializer=openengine_dot_v1_dot_engine__pb2.EngineInfo.SerializeToString, + ), + 'GetModelInfo': grpc.unary_unary_rpc_method_handler( + servicer.GetModelInfo, + request_deserializer=openengine_dot_v1_dot_model__pb2.GetModelInfoRequest.FromString, + response_serializer=openengine_dot_v1_dot_model__pb2.ModelInfo.SerializeToString, + ), + 'GetLoad': grpc.unary_unary_rpc_method_handler( + servicer.GetLoad, + request_deserializer=openengine_dot_v1_dot_observability__pb2.GetLoadRequest.FromString, + response_serializer=openengine_dot_v1_dot_observability__pb2.LoadInfo.SerializeToString, + ), + 'Health': grpc.unary_unary_rpc_method_handler( + servicer.Health, + request_deserializer=openengine_dot_v1_dot_lifecycle__pb2.HealthRequest.FromString, + response_serializer=openengine_dot_v1_dot_lifecycle__pb2.HealthResponse.SerializeToString, + ), + 'Abort': grpc.unary_unary_rpc_method_handler( + servicer.Abort, + request_deserializer=openengine_dot_v1_dot_lifecycle__pb2.AbortRequest.FromString, + response_serializer=openengine_dot_v1_dot_lifecycle__pb2.AbortResponse.SerializeToString, + ), + 'Drain': grpc.unary_stream_rpc_method_handler( + servicer.Drain, + request_deserializer=openengine_dot_v1_dot_lifecycle__pb2.DrainRequest.FromString, + response_serializer=openengine_dot_v1_dot_lifecycle__pb2.DrainResponse.SerializeToString, + ), + 'LoadLora': grpc.unary_unary_rpc_method_handler( + servicer.LoadLora, + request_deserializer=openengine_dot_v1_dot_lora__pb2.LoadLoraRequest.FromString, + response_serializer=openengine_dot_v1_dot_lora__pb2.LoadLoraResponse.SerializeToString, + ), + 'UnloadLora': grpc.unary_unary_rpc_method_handler( + servicer.UnloadLora, + request_deserializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraRequest.FromString, + response_serializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraResponse.SerializeToString, + ), + 'ListLoras': grpc.unary_unary_rpc_method_handler( + servicer.ListLoras, + request_deserializer=openengine_dot_v1_dot_lora__pb2.ListLorasRequest.FromString, + response_serializer=openengine_dot_v1_dot_lora__pb2.ListLorasResponse.SerializeToString, + ), + 'GetKvConnectorInfo': grpc.unary_unary_rpc_method_handler( + servicer.GetKvConnectorInfo, + request_deserializer=openengine_dot_v1_dot_kv__pb2.GetKvConnectorInfoRequest.FromString, + response_serializer=openengine_dot_v1_dot_kv__pb2.KvConnectorInfo.SerializeToString, + ), + 'GetKvEventSources': grpc.unary_unary_rpc_method_handler( + servicer.GetKvEventSources, + request_deserializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesRequest.FromString, + response_serializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesResponse.SerializeToString, + ), + 'SubscribeKvEvents': grpc.unary_stream_rpc_method_handler( + servicer.SubscribeKvEvents, + request_deserializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsRequest.FromString, + response_serializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsResponse.SerializeToString, + ), + 'SubscribeRuntimeEvents': grpc.unary_stream_rpc_method_handler( + servicer.SubscribeRuntimeEvents, + request_deserializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsRequest.FromString, + response_serializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'openengine.v1.OpenEngine', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('openengine.v1.OpenEngine', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class OpenEngine: + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def Generate(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/openengine.v1.OpenEngine/Generate', + openengine_dot_v1_dot_generation__pb2.GenerateRequest.SerializeToString, + openengine_dot_v1_dot_generation__pb2.GenerateResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetEngineInfo(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/GetEngineInfo', + openengine_dot_v1_dot_engine__pb2.GetEngineInfoRequest.SerializeToString, + openengine_dot_v1_dot_engine__pb2.EngineInfo.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetModelInfo(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/GetModelInfo', + openengine_dot_v1_dot_model__pb2.GetModelInfoRequest.SerializeToString, + openengine_dot_v1_dot_model__pb2.ModelInfo.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetLoad(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/GetLoad', + openengine_dot_v1_dot_observability__pb2.GetLoadRequest.SerializeToString, + openengine_dot_v1_dot_observability__pb2.LoadInfo.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Health(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/Health', + openengine_dot_v1_dot_lifecycle__pb2.HealthRequest.SerializeToString, + openengine_dot_v1_dot_lifecycle__pb2.HealthResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Abort(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/Abort', + openengine_dot_v1_dot_lifecycle__pb2.AbortRequest.SerializeToString, + openengine_dot_v1_dot_lifecycle__pb2.AbortResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Drain(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/openengine.v1.OpenEngine/Drain', + openengine_dot_v1_dot_lifecycle__pb2.DrainRequest.SerializeToString, + openengine_dot_v1_dot_lifecycle__pb2.DrainResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def LoadLora(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/LoadLora', + openengine_dot_v1_dot_lora__pb2.LoadLoraRequest.SerializeToString, + openengine_dot_v1_dot_lora__pb2.LoadLoraResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UnloadLora(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/UnloadLora', + openengine_dot_v1_dot_lora__pb2.UnloadLoraRequest.SerializeToString, + openengine_dot_v1_dot_lora__pb2.UnloadLoraResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListLoras(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/ListLoras', + openengine_dot_v1_dot_lora__pb2.ListLorasRequest.SerializeToString, + openengine_dot_v1_dot_lora__pb2.ListLorasResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetKvConnectorInfo(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/GetKvConnectorInfo', + openengine_dot_v1_dot_kv__pb2.GetKvConnectorInfoRequest.SerializeToString, + openengine_dot_v1_dot_kv__pb2.KvConnectorInfo.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetKvEventSources(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/openengine.v1.OpenEngine/GetKvEventSources', + openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesRequest.SerializeToString, + openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def SubscribeKvEvents(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/openengine.v1.OpenEngine/SubscribeKvEvents', + openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsRequest.SerializeToString, + openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def SubscribeRuntimeEvents(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/openengine.v1.OpenEngine/SubscribeRuntimeEvents', + openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsRequest.SerializeToString, + openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/packages/python/tests/test_bindings.py b/packages/python/tests/test_bindings.py new file mode 100644 index 0000000..09442db --- /dev/null +++ b/packages/python/tests/test_bindings.py @@ -0,0 +1,41 @@ +import unittest + +import grpc + +from openengine import SCHEMA_RELEASE, SCHEMA_REVISION, __version__ +from openengine.v1.generation_pb2 import GenerateRequest +from openengine.v1.openengine_pb2_grpc import OpenEngineStub + + +class BindingsTest(unittest.TestCase): + def test_request_round_trip_preserves_optional_zero(self) -> None: + request = GenerateRequest( + request_id="python-smoke", + model="test-model", + prompt="Hello", + priority=0, + ) + + decoded = GenerateRequest.FromString(request.SerializeToString()) + + self.assertEqual(decoded.request_id, "python-smoke") + self.assertEqual(decoded.WhichOneof("input"), "prompt") + self.assertTrue(decoded.HasField("priority")) + self.assertEqual(decoded.priority, 0) + + def test_client_stub_can_be_constructed(self) -> None: + channel = grpc.insecure_channel("localhost:1") + self.addCleanup(channel.close) + + stub = OpenEngineStub(channel) + + self.assertTrue(callable(stub.Generate)) + self.assertTrue(callable(stub.GetEngineInfo)) + + def test_package_metadata_matches_schema(self) -> None: + self.assertEqual(SCHEMA_REVISION, 1) + self.assertEqual(SCHEMA_RELEASE, f"v{__version__}") + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/rust/openengine-proto/Cargo.toml b/packages/rust/openengine-proto/Cargo.toml new file mode 100644 index 0000000..63f8e89 --- /dev/null +++ b/packages/rust/openengine-proto/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "openengine-proto" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true +description = "Generated Rust bindings for the OpenEngine gRPC protocol" +readme = "README.md" +keywords = ["grpc", "inference", "protobuf"] +categories = ["api-bindings", "network-programming"] + +[dependencies] +prost = "0.14.4" +prost-types = "0.14.4" +tonic = "0.14.6" +tonic-prost = "0.14.6" diff --git a/packages/rust/openengine-proto/README.md b/packages/rust/openengine-proto/README.md new file mode 100644 index 0000000..21d2706 --- /dev/null +++ b/packages/rust/openengine-proto/README.md @@ -0,0 +1,24 @@ + + +# OpenEngine Rust bindings + +Generated Prost messages and Tonic client/server bindings for the +[`openengine.v1`](https://github.com/ai-dynamo/openengine/tree/main/proto/openengine/v1) +protocol. + +```bash +cargo add openengine-proto +``` + +```rust +use openengine_proto::openengine::v1::{ + open_engine_client::OpenEngineClient, + GenerateRequest, +}; +``` + +The crate contains generated Rust source and a protobuf descriptor set. +Consumer builds do not run `protoc`. diff --git a/packages/rust/openengine-proto/examples/cross_language_fixture.rs b/packages/rust/openengine-proto/examples/cross_language_fixture.rs new file mode 100644 index 0000000..3842981 --- /dev/null +++ b/packages/rust/openengine-proto/examples/cross_language_fixture.rs @@ -0,0 +1,39 @@ +use std::env; +use std::fs; +use std::path::Path; + +use openengine_proto::openengine::v1::{generate_request, GenerateRequest}; +use prost::Message; + +fn fixture() -> GenerateRequest { + GenerateRequest { + request_id: "cross-language".into(), + model: "test-model".into(), + input: Some(generate_request::Input::Prompt("Hello".into())), + priority: Some(0), + ..Default::default() + } +} + +fn encode(path: &Path) { + fs::write(path, fixture().encode_to_vec()).unwrap(); +} + +fn decode(path: &Path) { + let bytes = fs::read(path).unwrap(); + let request = GenerateRequest::decode(bytes.as_slice()).unwrap(); + assert_eq!(request, fixture()); +} + +fn main() { + let mut args = env::args_os().skip(1); + let operation = args.next().expect("expected encode or decode"); + let path = args.next().expect("expected fixture path"); + assert!(args.next().is_none(), "unexpected additional arguments"); + + match operation.to_str() { + Some("encode") => encode(Path::new(&path)), + Some("decode") => decode(Path::new(&path)), + _ => panic!("expected encode or decode"), + } +} diff --git a/packages/rust/openengine-proto/src/generated/openengine.v1.rs b/packages/rust/openengine-proto/src/generated/openengine.v1.rs new file mode 100644 index 0000000..a7ea8bb --- /dev/null +++ b/packages/rust/openengine-proto/src/generated/openengine.v1.rs @@ -0,0 +1,2594 @@ +// This file is @generated by prost-build. +/// Accepted failures emit one terminal EngineError and close with OK. +/// Validation and transport failures use non-OK gRPC status instead. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EngineError { + #[prost(enumeration = "ErrorCode", tag = "1")] + pub code: i32, + #[prost(string, tag = "2")] + pub message: ::prost::alloc::string::String, + /// Retry may succeed without changing the request. + #[prost(bool, tag = "3")] + pub retryable: bool, + /// Zero permits immediate retry. + #[prost(uint64, optional, tag = "4")] + pub retry_after_ms: ::core::option::Option, + /// Machine-readable context. + #[prost(message, optional, tag = "5")] + pub details: ::core::option::Option<::prost_types::Struct>, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ErrorCode { + Unspecified = 0, + InvalidArgument = 1, + UnsupportedFeature = 2, + RoleMismatch = 3, + ModelNotFound = 4, + Overloaded = 5, + RequestNotFound = 6, + DuplicateRequest = 7, + KvSessionNotFound = 8, + KvTransferFailed = 9, + Cancelled = 10, + Draining = 11, + Internal = 12, +} +impl ErrorCode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ERROR_CODE_UNSPECIFIED", + Self::InvalidArgument => "ERROR_CODE_INVALID_ARGUMENT", + Self::UnsupportedFeature => "ERROR_CODE_UNSUPPORTED_FEATURE", + Self::RoleMismatch => "ERROR_CODE_ROLE_MISMATCH", + Self::ModelNotFound => "ERROR_CODE_MODEL_NOT_FOUND", + Self::Overloaded => "ERROR_CODE_OVERLOADED", + Self::RequestNotFound => "ERROR_CODE_REQUEST_NOT_FOUND", + Self::DuplicateRequest => "ERROR_CODE_DUPLICATE_REQUEST", + Self::KvSessionNotFound => "ERROR_CODE_KV_SESSION_NOT_FOUND", + Self::KvTransferFailed => "ERROR_CODE_KV_TRANSFER_FAILED", + Self::Cancelled => "ERROR_CODE_CANCELLED", + Self::Draining => "ERROR_CODE_DRAINING", + Self::Internal => "ERROR_CODE_INTERNAL", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ERROR_CODE_UNSPECIFIED" => Some(Self::Unspecified), + "ERROR_CODE_INVALID_ARGUMENT" => Some(Self::InvalidArgument), + "ERROR_CODE_UNSUPPORTED_FEATURE" => Some(Self::UnsupportedFeature), + "ERROR_CODE_ROLE_MISMATCH" => Some(Self::RoleMismatch), + "ERROR_CODE_MODEL_NOT_FOUND" => Some(Self::ModelNotFound), + "ERROR_CODE_OVERLOADED" => Some(Self::Overloaded), + "ERROR_CODE_REQUEST_NOT_FOUND" => Some(Self::RequestNotFound), + "ERROR_CODE_DUPLICATE_REQUEST" => Some(Self::DuplicateRequest), + "ERROR_CODE_KV_SESSION_NOT_FOUND" => Some(Self::KvSessionNotFound), + "ERROR_CODE_KV_TRANSFER_FAILED" => Some(Self::KvTransferFailed), + "ERROR_CODE_CANCELLED" => Some(Self::Cancelled), + "ERROR_CODE_DRAINING" => Some(Self::Draining), + "ERROR_CODE_INTERNAL" => Some(Self::Internal), + _ => None, + } + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KvSessionRef { + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub transfer_backend: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "3")] + pub endpoints: ::prost::alloc::vec::Vec, + #[prost(uint32, tag = "4")] + pub dp_rank: u32, + /// Engine-specific KV-transfer parameters (e.g. NixlConnector + /// remote_host / remote_port / tp_size / remote_block_ids / do_remote\_\*), + /// carried as a Struct so numbers, booleans, and arrays survive the wire with + /// their JSON type intact. Struct numbers are IEEE-754 doubles (exact only to + /// 2^53); carry larger integer values as strings or use a dedicated field. + #[prost(message, optional, tag = "5")] + pub attributes_struct: ::core::option::Option<::prost_types::Struct>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct KvEndpoint { + #[prost(string, tag = "1")] + pub host: ::prost::alloc::string::String, + #[prost(uint32, tag = "2")] + pub port: u32, + /// grpc, nixl, ucx, tcp, shm, etc. + #[prost(string, tag = "3")] + pub protocol: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetKvConnectorInfoRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KvConnectorInfo { + #[prost(bool, optional, tag = "1")] + pub enabled: ::core::option::Option, + #[prost(string, tag = "2")] + pub transfer_backend: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "3")] + pub local_endpoints: ::prost::alloc::vec::Vec, + #[prost(string, repeated, tag = "4")] + pub supported_protocols: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(bool, optional, tag = "5")] + pub supports_remote_prefill: ::core::option::Option, + #[prost(bool, optional, tag = "6")] + pub supports_decode_pull: ::core::option::Option, + #[prost(bool, optional, tag = "7")] + pub supports_abort_cleanup: ::core::option::Option, + #[prost(bool, optional, tag = "8")] + pub supports_drain: ::core::option::Option, + #[prost(uint32, optional, tag = "9")] + pub schema_version: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetKvEventSourcesRequest { + #[prost(uint32, repeated, tag = "1")] + pub data_parallel_ranks: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetKvEventSourcesResponse { + #[prost(message, repeated, tag = "1")] + pub sources: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct KvEventSource { + /// grpc, zmq + #[prost(string, tag = "1")] + pub transport: ::prost::alloc::string::String, + /// Connectable address. MUST use a routable host, never a bind wildcard. + #[prost(message, optional, tag = "2")] + pub endpoint_addr: ::core::option::Option, + #[prost(string, tag = "3")] + pub topic: ::prost::alloc::string::String, + /// optional, for ZMQ replay + #[prost(string, tag = "4")] + pub replay_endpoint: ::prost::alloc::string::String, + #[prost(uint32, optional, tag = "5")] + pub data_parallel_rank: ::core::option::Option, + /// protobuf, msgpack + #[prost(string, tag = "6")] + pub encoding: ::prost::alloc::string::String, + #[prost(uint32, optional, tag = "7")] + pub schema_version: ::core::option::Option, + #[prost(uint32, optional, tag = "8")] + pub buffer_steps: ::core::option::Option, + #[prost(uint32, optional, tag = "9")] + pub hwm: ::core::option::Option, + #[prost(uint32, optional, tag = "10")] + pub max_queue_size: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SubscribeKvEventsRequest { + #[prost(uint32, repeated, tag = "1")] + pub data_parallel_ranks: ::prost::alloc::vec::Vec, + #[prost(bool, tag = "2")] + pub include_snapshot: bool, + #[prost(uint64, tag = "3")] + pub start_sequence_number: u64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubscribeKvEventsResponse { + #[prost(oneof = "subscribe_kv_events_response::Event", tags = "1, 2")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `SubscribeKvEventsResponse`. +pub mod subscribe_kv_events_response { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Event { + #[prost(message, tag = "1")] + Batch(super::KvEventBatch), + /// Terminal. + #[prost(message, tag = "2")] + Error(super::EngineError), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KvEventBatch { + #[prost(uint64, tag = "1")] + pub sequence_number: u64, + #[prost(uint64, tag = "2")] + pub timestamp_unix_nanos: u64, + #[prost(uint32, tag = "3")] + pub data_parallel_rank: u32, + #[prost(message, repeated, tag = "4")] + pub events: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KvEvent { + #[prost(string, tag = "1")] + pub request_id: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub kv_session: ::core::option::Option, + #[prost(oneof = "kv_event::Event", tags = "10, 11, 12")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `KvEvent`. +pub mod kv_event { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Event { + #[prost(message, tag = "10")] + BlockStored(super::BlockStored), + #[prost(message, tag = "11")] + BlockRemoved(super::BlockRemoved), + #[prost(message, tag = "12")] + AllBlocksCleared(super::AllBlocksCleared), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockStored { + #[prost(message, repeated, tag = "1")] + pub block_hashes: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "2")] + pub parent_block_hash: ::core::option::Option, + #[prost(uint32, repeated, tag = "3")] + pub token_ids: ::prost::alloc::vec::Vec, + #[prost(uint32, tag = "4")] + pub block_size: u32, + #[prost(int64, tag = "5")] + pub lora_id: i64, + #[prost(string, tag = "6")] + pub lora_name: ::prost::alloc::string::String, + #[prost(enumeration = "StorageMedium", tag = "7")] + pub medium: i32, + /// vLLM-compatible optional metadata for reconstructing block keys. + #[prost(message, repeated, tag = "20")] + pub extra_keys: ::prost::alloc::vec::Vec, + #[prost(uint32, tag = "21")] + pub group_idx: u32, + #[prost(string, tag = "22")] + pub kv_cache_spec_kind: ::prost::alloc::string::String, + #[prost(uint32, tag = "23")] + pub kv_cache_spec_sliding_window: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockRemoved { + #[prost(message, repeated, tag = "1")] + pub block_hashes: ::prost::alloc::vec::Vec, + #[prost(enumeration = "StorageMedium", tag = "2")] + pub medium: i32, + #[prost(uint32, tag = "3")] + pub group_idx: u32, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AllBlocksCleared {} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct KvBlockHash { + #[prost(bytes = "vec", tag = "1")] + pub value: ::prost::alloc::vec::Vec, + /// int64, string, bytes, engine_specific + #[prost(string, tag = "2")] + pub encoding: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct OpaqueKeyTuple { + #[prost(string, repeated, tag = "1")] + pub values: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum StorageMedium { + Unspecified = 0, + Gpu = 1, + CpuPinned = 2, + Disk = 3, + External = 4, +} +impl StorageMedium { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "STORAGE_MEDIUM_UNSPECIFIED", + Self::Gpu => "STORAGE_MEDIUM_GPU", + Self::CpuPinned => "STORAGE_MEDIUM_CPU_PINNED", + Self::Disk => "STORAGE_MEDIUM_DISK", + Self::External => "STORAGE_MEDIUM_EXTERNAL", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "STORAGE_MEDIUM_UNSPECIFIED" => Some(Self::Unspecified), + "STORAGE_MEDIUM_GPU" => Some(Self::Gpu), + "STORAGE_MEDIUM_CPU_PINNED" => Some(Self::CpuPinned), + "STORAGE_MEDIUM_DISK" => Some(Self::Disk), + "STORAGE_MEDIUM_EXTERNAL" => Some(Self::External), + _ => None, + } + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetEngineInfoRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EngineInfo { + /// sglang, vllm, tensorrt_llm, etc. + #[prost(string, tag = "1")] + pub engine_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub engine_version: ::prost::alloc::string::String, + #[prost(enumeration = "EngineRole", tag = "3")] + pub role: i32, + #[prost(string, tag = "4")] + pub instance_id: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "5")] + pub supported_models: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(message, optional, tag = "6")] + pub parallelism: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub kv_connector: ::core::option::Option, + /// Monotonic wire contract revision; zero is invalid. + #[prost(uint32, tag = "8")] + pub schema_revision: u32, + /// Oldest compatible client revision. + #[prost(uint32, tag = "9")] + pub minimum_client_revision: u32, + /// Immutable release or source tag for this schema. + #[prost(string, tag = "10")] + pub schema_release: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ParallelismInfo { + #[prost(uint32, optional, tag = "1")] + pub tensor_parallel_size: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub pipeline_parallel_size: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub data_parallel_size: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub data_parallel_rank: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub data_parallel_start_rank: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum EngineRole { + Unspecified = 0, + Aggregated = 1, + Prefill = 2, + Decode = 3, +} +impl EngineRole { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ENGINE_ROLE_UNSPECIFIED", + Self::Aggregated => "ENGINE_ROLE_AGGREGATED", + Self::Prefill => "ENGINE_ROLE_PREFILL", + Self::Decode => "ENGINE_ROLE_DECODE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ENGINE_ROLE_UNSPECIFIED" => Some(Self::Unspecified), + "ENGINE_ROLE_AGGREGATED" => Some(Self::Aggregated), + "ENGINE_ROLE_PREFILL" => Some(Self::Prefill), + "ENGINE_ROLE_DECODE" => Some(Self::Decode), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct TokenIds { + #[prost(uint32, repeated, tag = "1")] + pub ids: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct SamplingParams { + #[prost(double, optional, tag = "1")] + pub temperature: ::core::option::Option, + #[prost(double, optional, tag = "2")] + pub top_p: ::core::option::Option, + #[prost(int32, optional, tag = "3")] + pub top_k: ::core::option::Option, + #[prost(double, optional, tag = "4")] + pub min_p: ::core::option::Option, + #[prost(double, optional, tag = "5")] + pub frequency_penalty: ::core::option::Option, + #[prost(double, optional, tag = "6")] + pub presence_penalty: ::core::option::Option, + #[prost(double, optional, tag = "7")] + pub repetition_penalty: ::core::option::Option, + #[prost(uint64, optional, tag = "8")] + pub seed: ::core::option::Option, + #[prost(uint32, optional, tag = "9")] + pub num_sequences: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StoppingOptions { + #[prost(uint32, optional, tag = "1")] + pub max_tokens: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub min_tokens: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub conditions: ::prost::alloc::vec::Vec, + #[prost(bool, optional, tag = "4")] + pub ignore_eos: ::core::option::Option, + #[prost(bool, optional, tag = "5")] + pub include_stop_in_output: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ResponseOptions { + #[prost(bool, optional, tag = "1")] + pub return_prompt_logprobs: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub prompt_candidates: ::core::option::Option, + #[prost(bool, optional, tag = "3")] + pub return_output_logprobs: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub output_candidates: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub prompt_logprob_start: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CandidateTokenSelection { + #[prost(oneof = "candidate_token_selection::Selection", tags = "1, 2, 3")] + pub selection: ::core::option::Option, +} +/// Nested message and enum types in `CandidateTokenSelection`. +pub mod candidate_token_selection { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Selection { + #[prost(uint32, tag = "1")] + TopN(u32), + #[prost(message, tag = "2")] + TokenIds(super::TokenIds), + #[prost(message, tag = "3")] + All(super::AllCandidates), + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AllCandidates {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KvOptions { + #[prost(message, optional, tag = "1")] + pub session: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub data_parallel_rank: ::core::option::Option, + #[prost(bool, optional, tag = "3")] + pub bypass_prefix_cache: ::core::option::Option, + #[prost(string, optional, tag = "4")] + pub cache_salt: ::core::option::Option<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct StopCondition { + #[prost(oneof = "stop_condition::Condition", tags = "1, 2")] + pub condition: ::core::option::Option, +} +/// Nested message and enum types in `StopCondition`. +pub mod stop_condition { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Condition { + #[prost(string, tag = "1")] + StopText(::prost::alloc::string::String), + #[prost(uint32, tag = "2")] + StopTokenId(u32), + } +} +/// Constrained / guided decoding spec. At most one of `guide` should be set. +/// The engine enforces the constraint during sampling via its grammar backend +/// (xgrammar / outlines / llguidance); clients cannot apply it post-hoc. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GuidedDecoding { + /// Optional grammar backend override (e.g. "xgrammar", "outlines", + /// "llguidance"). Empty = engine default. + #[prost(string, tag = "7")] + pub backend: ::prost::alloc::string::String, + #[prost(oneof = "guided_decoding::Guide", tags = "1, 2, 3, 4, 5, 6")] + pub guide: ::core::option::Option, +} +/// Nested message and enum types in `GuidedDecoding`. +pub mod guided_decoding { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Guide { + /// output conforms to this JSON schema + #[prost(string, tag = "1")] + JsonSchema(::prost::alloc::string::String), + /// output matches this regex + #[prost(string, tag = "2")] + Regex(::prost::alloc::string::String), + /// output follows this EBNF / context-free grammar + #[prost(string, tag = "3")] + EbnfGrammar(::prost::alloc::string::String), + /// xgrammar structural-tag constraint (JSON string) + #[prost(string, tag = "4")] + StructuralTag(::prost::alloc::string::String), + #[prost(message, tag = "5")] + Choice(super::ChoiceConstraint), + #[prost(message, tag = "6")] + JsonObject(super::JsonObjectConstraint), + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ChoiceConstraint { + #[prost(string, repeated, tag = "1")] + pub choices: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct JsonObjectConstraint {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenerateRequest { + #[prost(string, tag = "1")] + pub request_id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub model: ::prost::alloc::string::String, + #[prost(message, optional, tag = "5")] + pub sampling: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub stopping: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub response: ::core::option::Option, + #[prost(message, optional, tag = "8")] + pub kv: ::core::option::Option, + #[prost(message, optional, tag = "9")] + pub guided: ::core::option::Option, + /// Multimodal inputs. Order is significant: the i-th item aligns with the + /// i-th (un-expanded) placeholder marker carried in the prompt/token_ids. + /// The engine fetches/decodes and preprocesses each item, then expands the + /// marker into the model's replacement run. Empty for text-only requests. + #[prost(message, repeated, tag = "10")] + pub media: ::prost::alloc::vec::Vec, + /// Loaded LoRA adapter name to apply to this request. Empty = base model. + /// ModelInfo.supports_lora advertises whether lifecycle and selection are + /// available through OpenEngine. + #[prost(string, tag = "11")] + pub lora_name: ::prost::alloc::string::String, + /// Higher values receive higher scheduling priority. + #[prost(int32, optional, tag = "12")] + pub priority: ::core::option::Option, + /// Optional request metadata for tracing/admission/routing. + #[prost(map = "string, string", tag = "13")] + pub metadata: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, + #[prost(oneof = "generate_request::Input", tags = "3, 4")] + pub input: ::core::option::Option, +} +/// Nested message and enum types in `GenerateRequest`. +pub mod generate_request { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Input { + #[prost(string, tag = "3")] + Prompt(::prost::alloc::string::String), + #[prost(message, tag = "4")] + TokenIds(super::TokenIds), + } +} +/// A single multimodal input. Exactly one `source` should be set. The engine +/// owns fetch, decode, and preprocessing, so pre-decoded or RDMA media +/// descriptors are not represented here. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct MediaItem { + #[prost(enumeration = "Modality", tag = "1")] + pub modality: i32, + /// optional, hints raw_bytes decode + #[prost(string, tag = "5")] + pub mime_type: ::prost::alloc::string::String, + /// optional caller id / mm_hash + #[prost(string, tag = "6")] + pub uuid: ::prost::alloc::string::String, + #[prost(oneof = "media_item::Source", tags = "2, 3, 4")] + pub source: ::core::option::Option, +} +/// Nested message and enum types in `MediaItem`. +pub mod media_item { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Source { + /// http(s):// -- engine fetches + #[prost(string, tag = "2")] + Url(::prost::alloc::string::String), + /// data:;base64,\<...> -- engine decodes + #[prost(string, tag = "3")] + DataUri(::prost::alloc::string::String), + /// pre-fetched bytes -- engine still preprocesses + #[prost(bytes, tag = "4")] + RawBytes(::prost::alloc::vec::Vec), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenerateResponse { + #[prost(string, tag = "1")] + pub request_id: ::prost::alloc::string::String, + /// Cumulative request usage; only set on the final response. + #[prost(message, optional, tag = "10")] + pub usage: ::core::option::Option, + /// PromptOutput, PrefillReady, and EngineError are request-scoped. + /// TokenOutput and GenerationFinished are output-scoped. + #[prost(oneof = "generate_response::Event", tags = "2, 3, 4, 5, 6")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `GenerateResponse`. +pub mod generate_response { + /// PromptOutput, PrefillReady, and EngineError are request-scoped. + /// TokenOutput and GenerationFinished are output-scoped. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Event { + #[prost(message, tag = "2")] + Prompt(super::PromptOutput), + #[prost(message, tag = "3")] + Token(super::TokenOutput), + #[prost(message, tag = "4")] + PrefillReady(super::PrefillReady), + #[prost(message, tag = "5")] + Finished(super::GenerationFinished), + #[prost(message, tag = "6")] + Error(super::EngineError), + } +} +/// Request-scoped prompt token information, emitted at most once. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PromptOutput { + #[prost(message, repeated, tag = "1")] + pub tokens: ::prost::alloc::vec::Vec, +} +/// An incremental output delta. Tokens and text are never cumulative. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TokenOutput { + /// Required, including for output zero. + #[prost(uint32, optional, tag = "1")] + pub output_index: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub tokens: ::prost::alloc::vec::Vec, + #[prost(string, tag = "3")] + pub text: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TokenInfo { + #[prost(uint32, tag = "1")] + pub token_id: u32, + #[prost(string, tag = "2")] + pub token: ::prost::alloc::string::String, + #[prost(double, optional, tag = "3")] + pub logprob: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub rank: ::core::option::Option, + #[prost(message, repeated, tag = "5")] + pub candidates: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LogProb { + #[prost(uint32, tag = "1")] + pub token_id: u32, + #[prost(double, tag = "2")] + pub logprob: f64, + #[prost(string, tag = "3")] + pub token: ::prost::alloc::string::String, + #[prost(uint32, optional, tag = "4")] + pub rank: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PrefillReady { + #[prost(message, optional, tag = "1")] + pub kv_session: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GenerationFinished { + /// Required, including for output zero. + #[prost(uint32, optional, tag = "1")] + pub output_index: ::core::option::Option, + #[prost(enumeration = "FinishReason", tag = "2")] + pub reason: i32, + #[prost(string, tag = "3")] + pub message: ::prost::alloc::string::String, + #[prost(message, optional, tag = "4")] + pub stop_match: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct StopMatch { + #[prost(oneof = "stop_match::Match", tags = "1, 2, 3")] + pub r#match: ::core::option::Option, +} +/// Nested message and enum types in `StopMatch`. +pub mod stop_match { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Match { + #[prost(uint32, tag = "1")] + StopTokenId(u32), + #[prost(string, tag = "2")] + StopText(::prost::alloc::string::String), + #[prost(uint32, tag = "3")] + EosTokenId(u32), + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Usage { + #[prost(uint32, tag = "1")] + pub prompt_tokens: u32, + #[prost(uint32, tag = "2")] + pub completion_tokens: u32, + #[prost(uint32, tag = "3")] + pub total_tokens: u32, + #[prost(uint32, optional, tag = "4")] + pub cached_prompt_tokens: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub reasoning_tokens: ::core::option::Option, +} +/// Multimodal modality discriminator. 0 is treated as image for forward +/// compatibility with senders that omit the field. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Modality { + Unspecified = 0, + Image = 1, + Video = 2, + Audio = 3, +} +impl Modality { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "MODALITY_UNSPECIFIED", + Self::Image => "MODALITY_IMAGE", + Self::Video => "MODALITY_VIDEO", + Self::Audio => "MODALITY_AUDIO", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "MODALITY_UNSPECIFIED" => Some(Self::Unspecified), + "MODALITY_IMAGE" => Some(Self::Image), + "MODALITY_VIDEO" => Some(Self::Video), + "MODALITY_AUDIO" => Some(Self::Audio), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FinishReason { + Unspecified = 0, + Stop = 1, + Length = 2, + Cancelled = 3, +} +impl FinishReason { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "FINISH_REASON_UNSPECIFIED", + Self::Stop => "FINISH_REASON_STOP", + Self::Length => "FINISH_REASON_LENGTH", + Self::Cancelled => "FINISH_REASON_CANCELLED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FINISH_REASON_UNSPECIFIED" => Some(Self::Unspecified), + "FINISH_REASON_STOP" => Some(Self::Stop), + "FINISH_REASON_LENGTH" => Some(Self::Length), + "FINISH_REASON_CANCELLED" => Some(Self::Cancelled), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HealthRequest { + /// False means a lightweight readiness/liveness check. True asks the engine to + /// run a role-appropriate minimal inference probe and report it as a check. + #[prost(bool, tag = "1")] + pub include_inference_probe: bool, + /// Optional. Used when include_inference_probe is true. Empty means engine + /// default served model. + #[prost(string, tag = "2")] + pub model: ::prost::alloc::string::String, + /// Optional expected role for role-specific inference probes. + #[prost(enumeration = "EngineRole", tag = "3")] + pub role: i32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HealthResponse { + #[prost(enumeration = "HealthState", tag = "1")] + pub state: i32, + #[prost(message, repeated, tag = "2")] + pub checks: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HealthCheck { + /// grpc, scheduler, model, kv_connector, role, inference_probe + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + #[prost(enumeration = "HealthState", tag = "2")] + pub state: i32, + #[prost(string, tag = "3")] + pub message: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AbortRequest { + #[prost(oneof = "abort_request::Target", tags = "1, 2, 3")] + pub target: ::core::option::Option, +} +/// Nested message and enum types in `AbortRequest`. +pub mod abort_request { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Target { + #[prost(string, tag = "1")] + RequestId(::prost::alloc::string::String), + #[prost(message, tag = "2")] + KvSession(super::KvSessionRef), + #[prost(message, tag = "3")] + AllRequests(super::AllRequests), + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AllRequests {} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AbortResponse { + #[prost(enumeration = "AbortStatus", tag = "1")] + pub status: i32, + #[prost(string, tag = "2")] + pub message: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DrainRequest { + #[prost(bool, tag = "1")] + pub stop_accepting_new_requests: bool, + /// Absent means no deadline; zero is immediate. + #[prost(uint32, optional, tag = "2")] + pub deadline_ms: ::core::option::Option, + #[prost(bool, tag = "3")] + pub abort_after_deadline: bool, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DrainResponse { + #[prost(uint32, optional, tag = "2")] + pub in_flight_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub open_kv_sessions: ::core::option::Option, + #[prost(string, tag = "4")] + pub message: ::prost::alloc::string::String, + #[prost(oneof = "drain_response::Event", tags = "1, 5")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `DrainResponse`. +pub mod drain_response { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Event { + /// Progress or successful completion. + #[prost(enumeration = "super::DrainState", tag = "1")] + State(i32), + /// Terminal failure. + #[prost(message, tag = "5")] + Error(super::EngineError), + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum HealthState { + Unspecified = 0, + Starting = 1, + Ready = 2, + Degraded = 3, + Draining = 4, + NotReady = 5, +} +impl HealthState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "HEALTH_STATE_UNSPECIFIED", + Self::Starting => "HEALTH_STATE_STARTING", + Self::Ready => "HEALTH_STATE_READY", + Self::Degraded => "HEALTH_STATE_DEGRADED", + Self::Draining => "HEALTH_STATE_DRAINING", + Self::NotReady => "HEALTH_STATE_NOT_READY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "HEALTH_STATE_UNSPECIFIED" => Some(Self::Unspecified), + "HEALTH_STATE_STARTING" => Some(Self::Starting), + "HEALTH_STATE_READY" => Some(Self::Ready), + "HEALTH_STATE_DEGRADED" => Some(Self::Degraded), + "HEALTH_STATE_DRAINING" => Some(Self::Draining), + "HEALTH_STATE_NOT_READY" => Some(Self::NotReady), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum AbortStatus { + Unspecified = 0, + Aborted = 1, + AlreadyFinished = 2, +} +impl AbortStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ABORT_STATUS_UNSPECIFIED", + Self::Aborted => "ABORT_STATUS_ABORTED", + Self::AlreadyFinished => "ABORT_STATUS_ALREADY_FINISHED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ABORT_STATUS_UNSPECIFIED" => Some(Self::Unspecified), + "ABORT_STATUS_ABORTED" => Some(Self::Aborted), + "ABORT_STATUS_ALREADY_FINISHED" => Some(Self::AlreadyFinished), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum DrainState { + Unspecified = 0, + Started = 1, + InProgress = 2, + Complete = 3, +} +impl DrainState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "DRAIN_STATE_UNSPECIFIED", + Self::Started => "DRAIN_STATE_STARTED", + Self::InProgress => "DRAIN_STATE_IN_PROGRESS", + Self::Complete => "DRAIN_STATE_COMPLETE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "DRAIN_STATE_UNSPECIFIED" => Some(Self::Unspecified), + "DRAIN_STATE_STARTED" => Some(Self::Started), + "DRAIN_STATE_IN_PROGRESS" => Some(Self::InProgress), + "DRAIN_STATE_COMPLETE" => Some(Self::Complete), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LoraAdapter { + #[prost(int64, tag = "1")] + pub lora_id: i64, + #[prost(string, tag = "2")] + pub lora_name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub source_path: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LoadLoraRequest { + #[prost(message, optional, tag = "1")] + pub adapter: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LoadLoraResponse { + #[prost(message, optional, tag = "1")] + pub adapter: ::core::option::Option, + #[prost(bool, tag = "2")] + pub already_loaded: bool, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct UnloadLoraRequest { + #[prost(string, tag = "1")] + pub lora_name: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct UnloadLoraResponse { + #[prost(message, optional, tag = "1")] + pub adapter: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListLorasRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListLorasResponse { + #[prost(message, repeated, tag = "1")] + pub adapters: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetModelInfoRequest { + #[prost(string, tag = "1")] + pub model: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ModelInfo { + #[prost(string, tag = "1")] + pub model_id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub served_model_name: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "3")] + pub served_model_aliases: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint32, optional, tag = "4")] + pub max_context_length: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub max_output_tokens: ::core::option::Option, + #[prost(uint32, optional, tag = "6")] + pub kv_block_size: ::core::option::Option, + #[prost(uint64, optional, tag = "7")] + pub total_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "8")] + pub max_running_requests: ::core::option::Option, + #[prost(uint64, optional, tag = "9")] + pub max_batched_tokens: ::core::option::Option, + #[prost(string, repeated, tag = "10")] + pub tokenizer_modes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(bool, optional, tag = "20")] + pub supports_text_input: ::core::option::Option, + #[prost(bool, optional, tag = "21")] + pub supports_token_ids_input: ::core::option::Option, + #[prost(message, optional, tag = "22")] + pub generation: ::core::option::Option, + #[prost(bool, optional, tag = "23")] + pub supports_lora: ::core::option::Option, + #[prost(bool, optional, tag = "24")] + pub supports_multimodal: ::core::option::Option, + /// Engine-advertised response parser names. Clients can apply these to a + /// model's output stream for tool-call extraction or reasoning separation. + /// Empty means no parser is configured for this model. + #[prost(string, tag = "25")] + pub reasoning_parser: ::prost::alloc::string::String, + #[prost(string, tag = "26")] + pub tool_call_parser: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GenerationCapabilities { + #[prost(message, optional, tag = "1")] + pub prompt_logprobs: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub output_logprobs: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub guided_decoding: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub max_num_sequences: ::core::option::Option, + #[prost(bool, optional, tag = "5")] + pub supports_priority: ::core::option::Option, + #[prost(bool, optional, tag = "6")] + pub supports_stop_in_output: ::core::option::Option, + #[prost(bool, optional, tag = "7")] + pub supports_cache_salt: ::core::option::Option, + #[prost(bool, optional, tag = "8")] + pub supports_prefix_cache_bypass: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LogprobCapabilities { + #[prost(bool, optional, tag = "1")] + pub supported: ::core::option::Option, + #[prost(enumeration = "CandidateTokenSelectionMode", repeated, tag = "2")] + pub candidate_selection_modes: ::prost::alloc::vec::Vec, + #[prost(uint32, optional, tag = "3")] + pub max_top_n: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GuidedDecodingCapabilities { + #[prost(bool, optional, tag = "1")] + pub supported: ::core::option::Option, + #[prost(enumeration = "GuidedDecodingMode", repeated, tag = "2")] + pub modes: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum CandidateTokenSelectionMode { + Unspecified = 0, + TopN = 1, + TokenIds = 2, + All = 3, +} +impl CandidateTokenSelectionMode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED", + Self::TopN => "CANDIDATE_TOKEN_SELECTION_MODE_TOP_N", + Self::TokenIds => "CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS", + Self::All => "CANDIDATE_TOKEN_SELECTION_MODE_ALL", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED" => Some(Self::Unspecified), + "CANDIDATE_TOKEN_SELECTION_MODE_TOP_N" => Some(Self::TopN), + "CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS" => Some(Self::TokenIds), + "CANDIDATE_TOKEN_SELECTION_MODE_ALL" => Some(Self::All), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum GuidedDecodingMode { + Unspecified = 0, + JsonSchema = 1, + Regex = 2, + EbnfGrammar = 3, + StructuralTag = 4, + Choice = 5, + JsonObject = 6, +} +impl GuidedDecodingMode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "GUIDED_DECODING_MODE_UNSPECIFIED", + Self::JsonSchema => "GUIDED_DECODING_MODE_JSON_SCHEMA", + Self::Regex => "GUIDED_DECODING_MODE_REGEX", + Self::EbnfGrammar => "GUIDED_DECODING_MODE_EBNF_GRAMMAR", + Self::StructuralTag => "GUIDED_DECODING_MODE_STRUCTURAL_TAG", + Self::Choice => "GUIDED_DECODING_MODE_CHOICE", + Self::JsonObject => "GUIDED_DECODING_MODE_JSON_OBJECT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "GUIDED_DECODING_MODE_UNSPECIFIED" => Some(Self::Unspecified), + "GUIDED_DECODING_MODE_JSON_SCHEMA" => Some(Self::JsonSchema), + "GUIDED_DECODING_MODE_REGEX" => Some(Self::Regex), + "GUIDED_DECODING_MODE_EBNF_GRAMMAR" => Some(Self::EbnfGrammar), + "GUIDED_DECODING_MODE_STRUCTURAL_TAG" => Some(Self::StructuralTag), + "GUIDED_DECODING_MODE_CHOICE" => Some(Self::Choice), + "GUIDED_DECODING_MODE_JSON_OBJECT" => Some(Self::JsonObject), + _ => None, + } + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetLoadRequest { + #[prost(bool, tag = "1")] + pub include_per_rank: bool, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LoadInfo { + #[prost(string, tag = "1")] + pub instance_id: ::prost::alloc::string::String, + #[prost(uint64, optional, tag = "2")] + pub timestamp_unix_nanos: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub running_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub queued_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub active_kv_sessions: ::core::option::Option, + #[prost(uint64, optional, tag = "6")] + pub used_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "7")] + pub total_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "8")] + pub running_tokens: ::core::option::Option, + #[prost(uint64, optional, tag = "9")] + pub waiting_tokens: ::core::option::Option, + #[prost(uint32, optional, tag = "10")] + pub prefill_batch_size: ::core::option::Option, + #[prost(uint32, optional, tag = "11")] + pub decode_batch_size: ::core::option::Option, + #[prost(message, repeated, tag = "20")] + pub ranks: ::prost::alloc::vec::Vec, + #[prost(map = "string, string", tag = "30")] + pub attributes: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RankLoadInfo { + #[prost(uint32, optional, tag = "1")] + pub data_parallel_rank: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub running_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub queued_requests: ::core::option::Option, + #[prost(uint64, optional, tag = "4")] + pub used_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "5")] + pub total_kv_blocks: ::core::option::Option, + #[prost(uint32, optional, tag = "6")] + pub prefill_batch_size: ::core::option::Option, + #[prost(uint32, optional, tag = "7")] + pub decode_batch_size: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SubscribeRuntimeEventsRequest { + #[prost(enumeration = "RuntimeEventType", repeated, tag = "1")] + pub types: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubscribeRuntimeEventsResponse { + #[prost(oneof = "subscribe_runtime_events_response::Event", tags = "1, 2")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `SubscribeRuntimeEventsResponse`. +pub mod subscribe_runtime_events_response { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Event { + #[prost(message, tag = "1")] + RuntimeEvent(super::RuntimeEvent), + /// Terminal. + #[prost(message, tag = "2")] + Error(super::EngineError), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RuntimeEvent { + #[prost(string, tag = "1")] + pub event_id: ::prost::alloc::string::String, + #[prost(uint64, tag = "2")] + pub timestamp_unix_nanos: u64, + #[prost(enumeration = "RuntimeEventType", tag = "3")] + pub r#type: i32, + #[prost(map = "string, string", tag = "4")] + pub attributes: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RuntimeEventType { + Unspecified = 0, + ForwardPass = 1, + Batch = 2, + Queue = 3, + Transfer = 4, +} +impl RuntimeEventType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "RUNTIME_EVENT_TYPE_UNSPECIFIED", + Self::ForwardPass => "RUNTIME_EVENT_TYPE_FORWARD_PASS", + Self::Batch => "RUNTIME_EVENT_TYPE_BATCH", + Self::Queue => "RUNTIME_EVENT_TYPE_QUEUE", + Self::Transfer => "RUNTIME_EVENT_TYPE_TRANSFER", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "RUNTIME_EVENT_TYPE_UNSPECIFIED" => Some(Self::Unspecified), + "RUNTIME_EVENT_TYPE_FORWARD_PASS" => Some(Self::ForwardPass), + "RUNTIME_EVENT_TYPE_BATCH" => Some(Self::Batch), + "RUNTIME_EVENT_TYPE_QUEUE" => Some(Self::Queue), + "RUNTIME_EVENT_TYPE_TRANSFER" => Some(Self::Transfer), + _ => None, + } + } +} +/// Generated client implementations. +pub mod open_engine_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct OpenEngineClient { + inner: tonic::client::Grpc, + } + impl OpenEngineClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl OpenEngineClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> OpenEngineClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + OpenEngineClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Core inference path. + pub async fn generate( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/Generate", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Generate")); + self.inner.server_streaming(req, path, codec).await + } + /// Runtime metadata and scheduling state. + pub async fn get_engine_info( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/GetEngineInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "GetEngineInfo")); + self.inner.unary(req, path, codec).await + } + pub async fn get_model_info( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/GetModelInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "GetModelInfo")); + self.inner.unary(req, path, codec).await + } + pub async fn get_load( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/GetLoad", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "GetLoad")); + self.inner.unary(req, path, codec).await + } + /// Health and lifecycle. + pub async fn health( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/Health", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Health")); + self.inner.unary(req, path, codec).await + } + pub async fn abort( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/Abort", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Abort")); + self.inner.unary(req, path, codec).await + } + pub async fn drain( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/Drain", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Drain")); + self.inner.server_streaming(req, path, codec).await + } + /// LoRA lifecycle. + pub async fn load_lora( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/LoadLora", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "LoadLora")); + self.inner.unary(req, path, codec).await + } + pub async fn unload_lora( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/UnloadLora", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "UnloadLora")); + self.inner.unary(req, path, codec).await + } + pub async fn list_loras( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/ListLoras", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("openengine.v1.OpenEngine", "ListLoras")); + self.inner.unary(req, path, codec).await + } + /// Disaggregated serving / KV transfer. + pub async fn get_kv_connector_info( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/GetKvConnectorInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("openengine.v1.OpenEngine", "GetKvConnectorInfo"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn get_kv_event_sources( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/GetKvEventSources", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("openengine.v1.OpenEngine", "GetKvEventSources"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn subscribe_kv_events( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/SubscribeKvEvents", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("openengine.v1.OpenEngine", "SubscribeKvEvents"), + ); + self.inner.server_streaming(req, path, codec).await + } + /// Structured runtime events for planners/controllers. + pub async fn subscribe_runtime_events( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/openengine.v1.OpenEngine/SubscribeRuntimeEvents", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("openengine.v1.OpenEngine", "SubscribeRuntimeEvents"), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod open_engine_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with OpenEngineServer. + #[async_trait] + pub trait OpenEngine: std::marker::Send + std::marker::Sync + 'static { + /// Server streaming response type for the Generate method. + type GenerateStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + std::marker::Send + + 'static; + /// Core inference path. + async fn generate( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Runtime metadata and scheduling state. + async fn get_engine_info( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn get_model_info( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn get_load( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Health and lifecycle. + async fn health( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn abort( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Server streaming response type for the Drain method. + type DrainStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + std::marker::Send + + 'static; + async fn drain( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// LoRA lifecycle. + async fn load_lora( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn unload_lora( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn list_loras( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Disaggregated serving / KV transfer. + async fn get_kv_connector_info( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn get_kv_event_sources( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the SubscribeKvEvents method. + type SubscribeKvEventsStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + super::SubscribeKvEventsResponse, + tonic::Status, + >, + > + + std::marker::Send + + 'static; + async fn subscribe_kv_events( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the SubscribeRuntimeEvents method. + type SubscribeRuntimeEventsStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + super::SubscribeRuntimeEventsResponse, + tonic::Status, + >, + > + + std::marker::Send + + 'static; + /// Structured runtime events for planners/controllers. + async fn subscribe_runtime_events( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct OpenEngineServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl OpenEngineServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for OpenEngineServer + where + T: OpenEngine, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/openengine.v1.OpenEngine/Generate" => { + #[allow(non_camel_case_types)] + struct GenerateSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::ServerStreamingService + for GenerateSvc { + type Response = super::GenerateResponse; + type ResponseStream = T::GenerateStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::generate(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GenerateSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/GetEngineInfo" => { + #[allow(non_camel_case_types)] + struct GetEngineInfoSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for GetEngineInfoSvc { + type Response = super::EngineInfo; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_engine_info(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetEngineInfoSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/GetModelInfo" => { + #[allow(non_camel_case_types)] + struct GetModelInfoSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for GetModelInfoSvc { + type Response = super::ModelInfo; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_model_info(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetModelInfoSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/GetLoad" => { + #[allow(non_camel_case_types)] + struct GetLoadSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for GetLoadSvc { + type Response = super::LoadInfo; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_load(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetLoadSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/Health" => { + #[allow(non_camel_case_types)] + struct HealthSvc(pub Arc); + impl tonic::server::UnaryService + for HealthSvc { + type Response = super::HealthResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::health(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = HealthSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/Abort" => { + #[allow(non_camel_case_types)] + struct AbortSvc(pub Arc); + impl tonic::server::UnaryService + for AbortSvc { + type Response = super::AbortResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::abort(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = AbortSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/Drain" => { + #[allow(non_camel_case_types)] + struct DrainSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::ServerStreamingService + for DrainSvc { + type Response = super::DrainResponse; + type ResponseStream = T::DrainStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::drain(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = DrainSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/LoadLora" => { + #[allow(non_camel_case_types)] + struct LoadLoraSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for LoadLoraSvc { + type Response = super::LoadLoraResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::load_lora(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = LoadLoraSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/UnloadLora" => { + #[allow(non_camel_case_types)] + struct UnloadLoraSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for UnloadLoraSvc { + type Response = super::UnloadLoraResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::unload_lora(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = UnloadLoraSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/ListLoras" => { + #[allow(non_camel_case_types)] + struct ListLorasSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for ListLorasSvc { + type Response = super::ListLorasResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_loras(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ListLorasSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/GetKvConnectorInfo" => { + #[allow(non_camel_case_types)] + struct GetKvConnectorInfoSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for GetKvConnectorInfoSvc { + type Response = super::KvConnectorInfo; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_kv_connector_info(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetKvConnectorInfoSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/GetKvEventSources" => { + #[allow(non_camel_case_types)] + struct GetKvEventSourcesSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::UnaryService + for GetKvEventSourcesSvc { + type Response = super::GetKvEventSourcesResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_kv_event_sources(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetKvEventSourcesSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/SubscribeKvEvents" => { + #[allow(non_camel_case_types)] + struct SubscribeKvEventsSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::ServerStreamingService< + super::SubscribeKvEventsRequest, + > for SubscribeKvEventsSvc { + type Response = super::SubscribeKvEventsResponse; + type ResponseStream = T::SubscribeKvEventsStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::subscribe_kv_events(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = SubscribeKvEventsSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/openengine.v1.OpenEngine/SubscribeRuntimeEvents" => { + #[allow(non_camel_case_types)] + struct SubscribeRuntimeEventsSvc(pub Arc); + impl< + T: OpenEngine, + > tonic::server::ServerStreamingService< + super::SubscribeRuntimeEventsRequest, + > for SubscribeRuntimeEventsSvc { + type Response = super::SubscribeRuntimeEventsResponse; + type ResponseStream = T::SubscribeRuntimeEventsStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::subscribe_runtime_events(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = SubscribeRuntimeEventsSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + let mut response = http::Response::new( + tonic::body::Body::default(), + ); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } + } + } + } + impl Clone for OpenEngineServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "openengine.v1.OpenEngine"; + impl tonic::server::NamedService for OpenEngineServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/packages/rust/openengine-proto/src/generated/openengine_descriptor.bin b/packages/rust/openengine-proto/src/generated/openengine_descriptor.bin new file mode 100644 index 0000000000000000000000000000000000000000..f99bc0e71a92e9465b69d4cb8a317f7e98da9a1e GIT binary patch literal 51923 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 + exit 1 +fi diff --git a/scripts/check_release_version.py b/scripts/check_release_version.py new file mode 100755 index 0000000..94a506a --- /dev/null +++ b/scripts/check_release_version.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Verify that a release tag matches every published package version.""" + +from __future__ import annotations + +import re +import sys +import tomllib +from pathlib import Path + + +def read_toml(path: Path) -> dict: + with path.open("rb") as source: + return tomllib.load(source) + + +def main() -> int: + if len(sys.argv) != 2 or not re.fullmatch(r"v[0-9]+\.[0-9]+\.[0-9]+", sys.argv[1]): + print("usage: check_release_version.py vMAJOR.MINOR.PATCH", file=sys.stderr) + return 2 + + repository = Path(__file__).resolve().parent.parent + tag_version = sys.argv[1].removeprefix("v") + python_version = read_toml(repository / "packages/python/pyproject.toml")["project"]["version"] + rust_version = read_toml(repository / "Cargo.toml")["workspace"]["package"]["version"] + + versions = { + "release tag": tag_version, + "Python package": python_version, + "Rust crate": rust_version, + } + if len(set(versions.values())) != 1: + for label, version in versions.items(): + print(f"{label}: {version}", file=sys.stderr) + return 1 + + print(f"OpenEngine release versions match: {tag_version}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/cross_language_fixture.py b/scripts/cross_language_fixture.py new file mode 100755 index 0000000..2e51898 --- /dev/null +++ b/scripts/cross_language_fixture.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Encode or verify the shared Python/Rust wire fixture.""" + +from __future__ import annotations + +import sys +from pathlib import Path + +from openengine.v1.generation_pb2 import GenerateRequest + + +def fixture() -> GenerateRequest: + return GenerateRequest( + request_id="cross-language", + model="test-model", + prompt="Hello", + priority=0, + ) + + +def main() -> int: + if len(sys.argv) != 3 or sys.argv[1] not in {"encode", "decode"}: + print("usage: cross_language_fixture.py (encode|decode) PATH", file=sys.stderr) + return 2 + + operation, raw_path = sys.argv[1:] + path = Path(raw_path) + if operation == "encode": + path.write_bytes(fixture().SerializeToString()) + return 0 + + decoded = GenerateRequest.FromString(path.read_bytes()) + if decoded != fixture(): + print("decoded Rust fixture does not match the Python fixture", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/generate-python.sh b/scripts/generate-python.sh new file mode 100755 index 0000000..6986245 --- /dev/null +++ b/scripts/generate-python.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +python=${PYTHON:-python3} +output="${repository}/packages/python/src" +export LC_ALL=C + +if ! "${python}" -c "import grpc_tools.protoc" 2>/dev/null; then + echo "grpcio-tools is required; install grpcio-tools==1.81.1" >&2 + exit 1 +fi + +protos=("${repository}"/proto/openengine/v1/*.proto) + +for generated in \ + "${output}"/openengine/v1/*_pb2.py \ + "${output}"/openengine/v1/*_pb2.pyi \ + "${output}"/openengine/v1/*_pb2_grpc.py; do + if [[ -e "${generated}" ]]; then + rm -- "${generated}" + fi +done + +"${python}" -m grpc_tools.protoc \ + -I "${repository}/proto" \ + --python_out="${output}" \ + --pyi_out="${output}" \ + "${protos[@]}" + +"${python}" -m grpc_tools.protoc \ + -I "${repository}/proto" \ + --grpc_python_out="${output}" \ + "${repository}/proto/openengine/v1/openengine.proto" diff --git a/scripts/generate-rust.sh b/scripts/generate-rust.sh new file mode 100755 index 0000000..1b4e2d7 --- /dev/null +++ b/scripts/generate-rust.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +cargo run \ + --locked \ + --manifest-path "${repository}/Cargo.toml" \ + --package openengine-rust-codegen \ + -- "${repository}" diff --git a/scripts/test-cross-language.sh b/scripts/test-cross-language.sh new file mode 100755 index 0000000..5269f56 --- /dev/null +++ b/scripts/test-cross-language.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +temporary_directory=$(mktemp -d) +python=${PYTHON:-python3} +trap 'rm -rf "${temporary_directory}"' EXIT + +export PYTHONPATH="${repository}/packages/python/src${PYTHONPATH:+:${PYTHONPATH}}" + +"${python}" "${repository}/scripts/cross_language_fixture.py" \ + encode "${temporary_directory}/python.bin" +cargo run --quiet \ + --manifest-path "${repository}/Cargo.toml" \ + --package openengine-proto \ + --example cross_language_fixture \ + -- decode "${temporary_directory}/python.bin" + +cargo run --quiet \ + --manifest-path "${repository}/Cargo.toml" \ + --package openengine-proto \ + --example cross_language_fixture \ + -- encode "${temporary_directory}/rust.bin" +"${python}" "${repository}/scripts/cross_language_fixture.py" \ + decode "${temporary_directory}/rust.bin" diff --git a/tools/rust-codegen/Cargo.toml b/tools/rust-codegen/Cargo.toml new file mode 100644 index 0000000..8c24a5d --- /dev/null +++ b/tools/rust-codegen/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "openengine-rust-codegen" +version = "0.0.0" +edition.workspace = true +rust-version.workspace = true +license.workspace = true +publish = false + +[dependencies] +protoc-bin-vendored = "=3.2.0" +tonic-prost-build = "=0.14.6" diff --git a/tools/rust-codegen/src/main.rs b/tools/rust-codegen/src/main.rs new file mode 100644 index 0000000..665b664 --- /dev/null +++ b/tools/rust-codegen/src/main.rs @@ -0,0 +1,39 @@ +use std::env; +use std::error::Error; +use std::fs; +use std::path::PathBuf; + +fn main() -> Result<(), Box> { + let repository = env::args_os() + .nth(1) + .map(PathBuf::from) + .unwrap_or(env::current_dir()?); + let proto_root = repository.join("proto"); + let package_root = proto_root.join("openengine/v1"); + let output = repository.join("packages/rust/openengine-proto/src/generated"); + + fs::create_dir_all(&output)?; + + let mut protos = fs::read_dir(&package_root)? + .filter_map(Result::ok) + .map(|entry| entry.path()) + .filter(|path| { + path.extension() + .is_some_and(|extension| extension == "proto") + }) + .collect::>(); + protos.sort(); + + let protoc = protoc_bin_vendored::protoc_bin_path()?; + let protobuf_include = protoc_bin_vendored::include_path()?; + env::set_var("PROTOC", protoc); + + tonic_prost_build::configure() + .build_client(true) + .build_server(true) + .file_descriptor_set_path(output.join("openengine_descriptor.bin")) + .out_dir(&output) + .compile_protos(&protos, &[proto_root, protobuf_include])?; + + Ok(()) +} From a90ced5d2707d20cc99ef2a13a807d1cd31f3f4a Mon Sep 17 00:00:00 2001 From: Connor Carpenter Date: Fri, 10 Jul 2026 12:27:01 -0700 Subject: [PATCH 2/6] ci: use allowlisted Rust toolchain action Signed-off-by: Connor Carpenter --- .github/workflows/packages.yml | 8 ++++++-- .github/workflows/release.yml | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index ecb48ec..a58faf7 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -41,7 +41,9 @@ jobs: python-version: "3.14" - name: Set up Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable - name: Install Python generator run: python -m pip install grpcio-tools==1.81.1 @@ -118,7 +120,9 @@ jobs: python-version: "3.14" - name: Set up Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable - name: Install Python package run: python -m pip install ./packages/python diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6dbe5cc..fb4bdc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,9 @@ jobs: python-version: "3.14" - name: Set up Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable - name: Check release versions run: python scripts/check_release_version.py "${GITHUB_REF_NAME}" @@ -120,7 +122,9 @@ jobs: uses: actions/checkout@v6 - name: Set up Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable - name: Publish to crates.io env: From 8e434793732d02c8b742bfd0f16ab5071820a6f6 Mon Sep 17 00:00:00 2001 From: Connor Carpenter Date: Thu, 3 Sep 2026 13:01:31 -0700 Subject: [PATCH 3/6] feat(rust): add OpenEngine bindings crate Signed-off-by: Connor Carpenter --- .github/workflows/packages.yml | 131 -- .github/workflows/release.yml | 155 -- .github/workflows/rust-release.yml | 99 ++ .github/workflows/rust.yml | 97 ++ CHANGELOG.md | 9 +- CONTRIBUTING.md | 18 +- Cargo.lock | 170 +- Cargo.toml | 2 +- README.md | 20 +- RELEASING.md | 48 +- packages/python/README.md | 28 - packages/python/pyproject.toml | 39 - packages/python/src/openengine/__init__.py | 15 - packages/python/src/openengine/py.typed | 1 - packages/python/src/openengine/v1/__init__.py | 1 - .../python/src/openengine/v1/engine_pb2.py | 43 - .../python/src/openengine/v1/engine_pb2.pyi | 62 - .../python/src/openengine/v1/error_pb2.py | 39 - .../python/src/openengine/v1/error_pb2.pyi | 51 - .../openengine/v1/generation_params_pb2.py | 57 - .../openengine/v1/generation_params_pb2.pyi | 126 -- .../src/openengine/v1/generation_pb2.py | 67 - .../src/openengine/v1/generation_pb2.pyi | 188 --- packages/python/src/openengine/v1/kv_pb2.py | 70 - packages/python/src/openengine/v1/kv_pb2.pyi | 207 --- .../python/src/openengine/v1/lifecycle_pb2.py | 59 - .../src/openengine/v1/lifecycle_pb2.pyi | 120 -- packages/python/src/openengine/v1/lora_pb2.py | 48 - .../python/src/openengine/v1/lora_pb2.pyi | 53 - .../python/src/openengine/v1/model_pb2.py | 48 - .../python/src/openengine/v1/model_pb2.pyi | 118 -- .../src/openengine/v1/observability_pb2.py | 57 - .../src/openengine/v1/observability_pb2.pyi | 116 -- .../src/openengine/v1/openengine_pb2.py | 43 - .../src/openengine/v1/openengine_pb2.pyi | 11 - .../src/openengine/v1/openengine_pb2_grpc.py | 668 -------- packages/python/tests/test_bindings.py | 41 - .../examples/cross_language_fixture.rs | 39 - packages/rust/openengine-proto/src/lib.rs | 18 - .../rust/openengine-proto/tests/bindings.rs | 45 - .../Cargo.toml | 5 +- packages/rust/openengine/LICENSE | 201 +++ .../README.md | 7 +- .../src/generated/openengine.v1.rs | 1451 ++++++++--------- .../src/generated/openengine_descriptor.bin | Bin 51923 -> 49440 bytes packages/rust/openengine/src/lib.rs | 19 + proto/buf.md | 2 +- proto/openengine/v1/README.md | 4 +- scripts/check-generated.sh | 10 +- scripts/check-release-version.sh | 25 + scripts/check_release_version.py | 42 - scripts/cross_language_fixture.py | 40 - scripts/generate-python.sh | 34 - scripts/test-cross-language.sh | 25 - tools/rust-codegen/src/main.rs | 2 +- 55 files changed, 1260 insertions(+), 3834 deletions(-) delete mode 100644 .github/workflows/packages.yml delete mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/rust-release.yml create mode 100644 .github/workflows/rust.yml delete mode 100644 packages/python/README.md delete mode 100644 packages/python/pyproject.toml delete mode 100644 packages/python/src/openengine/__init__.py delete mode 100644 packages/python/src/openengine/py.typed delete mode 100644 packages/python/src/openengine/v1/__init__.py delete mode 100644 packages/python/src/openengine/v1/engine_pb2.py delete mode 100644 packages/python/src/openengine/v1/engine_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/error_pb2.py delete mode 100644 packages/python/src/openengine/v1/error_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/generation_params_pb2.py delete mode 100644 packages/python/src/openengine/v1/generation_params_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/generation_pb2.py delete mode 100644 packages/python/src/openengine/v1/generation_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/kv_pb2.py delete mode 100644 packages/python/src/openengine/v1/kv_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/lifecycle_pb2.py delete mode 100644 packages/python/src/openengine/v1/lifecycle_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/lora_pb2.py delete mode 100644 packages/python/src/openengine/v1/lora_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/model_pb2.py delete mode 100644 packages/python/src/openengine/v1/model_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/observability_pb2.py delete mode 100644 packages/python/src/openengine/v1/observability_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/openengine_pb2.py delete mode 100644 packages/python/src/openengine/v1/openengine_pb2.pyi delete mode 100644 packages/python/src/openengine/v1/openengine_pb2_grpc.py delete mode 100644 packages/python/tests/test_bindings.py delete mode 100644 packages/rust/openengine-proto/examples/cross_language_fixture.rs delete mode 100644 packages/rust/openengine-proto/src/lib.rs delete mode 100644 packages/rust/openengine-proto/tests/bindings.rs rename packages/rust/{openengine-proto => openengine}/Cargo.toml (75%) create mode 100644 packages/rust/openengine/LICENSE rename packages/rust/{openengine-proto => openengine}/README.md (78%) rename packages/rust/{openengine-proto => openengine}/src/generated/openengine.v1.rs (77%) rename packages/rust/{openengine-proto => openengine}/src/generated/openengine_descriptor.bin (50%) create mode 100644 packages/rust/openengine/src/lib.rs create mode 100755 scripts/check-release-version.sh delete mode 100755 scripts/check_release_version.py delete mode 100755 scripts/cross_language_fixture.py delete mode 100755 scripts/generate-python.sh delete mode 100755 scripts/test-cross-language.sh diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml deleted file mode 100644 index a58faf7..0000000 --- a/.github/workflows/packages.yml +++ /dev/null @@ -1,131 +0,0 @@ -name: Packages - -on: - push: - branches: - - main - paths: - - "proto/**" - - "packages/**" - - "tools/rust-codegen/**" - - "scripts/**" - - "Cargo.toml" - - "Cargo.lock" - - ".github/workflows/packages.yml" - - ".github/workflows/release.yml" - pull_request: - paths: - - "proto/**" - - "packages/**" - - "tools/rust-codegen/**" - - "scripts/**" - - "Cargo.toml" - - "Cargo.lock" - - ".github/workflows/packages.yml" - - ".github/workflows/release.yml" - -permissions: - contents: read - -jobs: - generated: - name: Generated bindings - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v6 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - - name: Install Python generator - run: python -m pip install grpcio-tools==1.81.1 - - - name: Check generated bindings - run: ./scripts/check-generated.sh - - python: - name: Python ${{ matrix.python-version }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.10", "3.14"] - steps: - - name: Check out repository - uses: actions/checkout@v6 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} - - - name: Install build tools - run: python -m pip install build==1.3.0 twine==6.2.0 - - - name: Build distributions - run: python -m build packages/python --outdir dist/python - - - name: Check distribution metadata - run: python -m twine check dist/python/* - - - name: Install wheel - run: python -m pip install dist/python/*.whl - - - name: Test installed bindings - run: python -m unittest discover --start-directory packages/python/tests - - rust: - name: Rust ${{ matrix.toolchain }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - toolchain: ["1.88.0", "stable"] - steps: - - name: Check out repository - uses: actions/checkout@v6 - - - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.toolchain }} - - - name: Test crate - run: cargo test --locked --package openengine-proto - - - name: Build publishable crate - run: cargo package --locked --package openengine-proto - - - name: List packaged files - run: cargo package --locked --package openengine-proto --list - - interoperability: - name: Python and Rust interoperability - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v6 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - - name: Install Python package - run: python -m pip install ./packages/python - - - name: Test both serialization directions - run: ./scripts/test-cross-language.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index fb4bdc3..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,155 +0,0 @@ -name: Release - -on: - push: - tags: - - "v[0-9]+.[0-9]+.[0-9]+" - -permissions: - contents: read - -jobs: - build: - name: Build and verify release - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v6 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - - name: Check release versions - run: python scripts/check_release_version.py "${GITHUB_REF_NAME}" - - - name: Lint schema - uses: bufbuild/buf-action@v1 - with: - version: "1.71.0" - lint: true - format: false - breaking: false - push: false - archive: false - pr_comment: false - - - name: Install Python tools - run: >- - python -m pip install - build==1.3.0 - grpcio-tools==1.81.1 - twine==6.2.0 - - - name: Check generated bindings - run: ./scripts/check-generated.sh - - - name: Test Rust crate - run: cargo test --locked --package openengine-proto - - - name: Build Rust crate - run: cargo package --locked --package openengine-proto - - - name: Build Python distributions - run: python -m build packages/python --outdir dist/python - - - name: Check Python distributions - run: python -m twine check dist/python/* - - - name: Install and test Python wheel - run: | - python -m pip install dist/python/*.whl - python -m unittest discover --start-directory packages/python/tests - - - name: Test cross-language serialization - run: ./scripts/test-cross-language.sh - - - name: Assemble release artifacts - run: | - mkdir -p dist/release - cp dist/python/* dist/release/ - cp target/package/openengine-proto-*.crate dist/release/ - cp packages/rust/openengine-proto/src/generated/openengine_descriptor.bin \ - "dist/release/openengine-${GITHUB_REF_NAME}-descriptor.bin" - tar --create --gzip \ - --file "dist/release/openengine-${GITHUB_REF_NAME}-proto.tar.gz" \ - --directory proto \ - openengine - cd dist/release - sha256sum openengine* > SHA256SUMS - - - name: Upload release artifacts - uses: actions/upload-artifact@v4 - with: - name: openengine-${{ github.ref_name }} - path: dist - if-no-files-found: error - - publish-python: - name: Publish Python package - needs: build - runs-on: ubuntu-latest - environment: release - permissions: - actions: read - contents: read - id-token: write - steps: - - name: Download release artifacts - uses: actions/download-artifact@v4 - with: - name: openengine-${{ github.ref_name }} - path: dist - - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: dist/python - - publish-rust: - name: Publish Rust crate - needs: build - runs-on: ubuntu-latest - environment: release - steps: - - name: Check out repository - uses: actions/checkout@v6 - - - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - - name: Publish to crates.io - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - run: cargo publish --locked --package openengine-proto - - github-release: - name: Create GitHub release - needs: [publish-python, publish-rust] - runs-on: ubuntu-latest - permissions: - actions: read - contents: write - steps: - - name: Download release artifacts - uses: actions/download-artifact@v4 - with: - name: openengine-${{ github.ref_name }} - path: dist - - - name: Create release - env: - GH_TOKEN: ${{ github.token }} - run: >- - gh release create "${GITHUB_REF_NAME}" - dist/release/* - --generate-notes - --title "OpenEngine ${GITHUB_REF_NAME}" diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml new file mode 100644 index 0000000..853d383 --- /dev/null +++ b/.github/workflows/rust-release.yml @@ -0,0 +1,99 @@ +name: Rust crate release + +on: + push: + tags: + - "openengine-v*" + +permissions: + contents: read + +jobs: + validate: + name: Validate release + runs-on: ubuntu-latest + outputs: + published: ${{ steps.registry.outputs.published }} + steps: + - name: Check out repository + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 + with: + fetch-depth: 0 + + - name: Verify release tag points to main + shell: bash + run: | + git fetch --no-tags origin main + if ! git merge-base --is-ancestor HEAD origin/main; then + echo "::error::Release tags must point to commits on main" + exit 1 + fi + + - name: Set up Rust + uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + with: + toolchain: stable + + - name: Check release version + run: ./scripts/check-release-version.sh "${GITHUB_REF_NAME}" + + - name: Check generated bindings + run: ./scripts/check-generated.sh + + - name: Build publishable crate + run: cargo package --locked --package openengine + + - name: Check for an existing publication + id: registry + env: + VERSION: ${{ github.ref_name }} + shell: bash + run: | + version="${VERSION#openengine-v}" + url="https://crates.io/api/v1/crates/openengine/${version}" + status="$(curl --silent --output /dev/null --write-out '%{http_code}' "${url}")" + case "${status}" in + 200) + remote_checksum="$(curl --fail --silent --show-error "${url}" | jq --raw-output '.version.checksum')" + local_checksum="$(sha256sum "target/package/openengine-${version}.crate" | cut --delimiter=' ' --fields=1)" + if [[ "${local_checksum}" != "${remote_checksum}" ]]; then + echo "::error::crates.io already has openengine ${version} with different contents" + exit 1 + fi + echo "published=true" >> "${GITHUB_OUTPUT}" + ;; + 404) + echo "published=false" >> "${GITHUB_OUTPUT}" + ;; + *) + echo "::error::crates.io returned HTTP ${status}" + exit 1 + ;; + esac + + publish: + name: Publish crate + needs: validate + if: needs.validate.outputs.published != 'true' + runs-on: ubuntu-latest + environment: release + permissions: + contents: read + id-token: write + steps: + - name: Check out repository + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + with: + toolchain: stable + + - name: Authenticate with crates.io + id: auth + uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5 + + - name: Publish to crates.io + env: + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} + run: cargo publish --locked --package openengine diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..14a037a --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,97 @@ +name: Rust + +on: + push: + branches: + - main + paths: + - "proto/**" + - "packages/rust/**" + - "tools/rust-codegen/**" + - "scripts/check-generated.sh" + - "scripts/check-release-version.sh" + - "scripts/generate-rust.sh" + - "Cargo.toml" + - "Cargo.lock" + - ".github/workflows/rust.yml" + - ".github/workflows/rust-release.yml" + pull_request: + paths: + - "proto/**" + - "packages/rust/**" + - "tools/rust-codegen/**" + - "scripts/check-generated.sh" + - "scripts/check-release-version.sh" + - "scripts/generate-rust.sh" + - "Cargo.toml" + - "Cargo.lock" + - ".github/workflows/rust.yml" + - ".github/workflows/rust-release.yml" + +permissions: + contents: read + +jobs: + generated: + name: Generated bindings + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + with: + toolchain: stable + + - name: Check generated bindings + run: ./scripts/check-generated.sh + + check: + name: Rust ${{ matrix.toolchain }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + toolchain: ["1.88.0", "stable"] + steps: + - name: Check out repository + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + with: + toolchain: ${{ matrix.toolchain }} + + - name: Check workspace + run: cargo check --locked --workspace --all-targets + + quality: + name: Rust quality + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + with: + toolchain: stable + components: clippy,rustfmt + + - name: Check formatting + run: cargo fmt --all --check + + - name: Run Clippy + run: cargo clippy --locked --workspace --all-targets -- -D warnings + + - name: Build documentation + env: + RUSTDOCFLAGS: "-D warnings" + run: cargo doc --locked --no-deps --package openengine + + - name: Build publishable crate + run: cargo package --locked --package openengine + + - name: List packaged files + run: cargo package --locked --package openengine --list diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d01c76..a88093b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,16 +5,13 @@ SPDX-License-Identifier: Apache-2.0 # Changelog -All notable changes to the OpenEngine schema and generated packages are -documented here. OpenEngine uses the same version for its Git tag, Python -distribution, and Rust crate. +All notable changes to the generated OpenEngine Rust crate are documented here. ## [Unreleased] ### Added -- Generated Python protobuf and gRPC bindings. -- Generated Rust Prost and Tonic client/server bindings. -- Reproducible code generation, package CI, and tag-driven releases. +- Generated `openengine` Prost messages and Tonic client/server bindings. +- Reproducible Rust code generation, package CI, and tag-driven crates.io releases. [Unreleased]: https://github.com/ai-dynamo/openengine/commits/main diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e07ee80..ae2dc0f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,28 +32,22 @@ sending a PR. ## Development checks -The schema under `proto/openengine/v1/` is the source of truth. Generated Python -and Rust bindings are checked in for package consumers and must be updated in -the same pull request as a schema change. +The schema under `proto/openengine/v1/` is the source of truth. Generated Rust bindings are checked in for crate consumers and must be updated in the same pull request as a schema change. ```bash buf build buf lint -python -m pip install grpcio-tools==1.81.1 -./scripts/generate-python.sh ./scripts/generate-rust.sh ./scripts/check-generated.sh -cargo test --locked --package openengine-proto -cargo package --locked --package openengine-proto -python -m build packages/python --outdir dist/python -python -m twine check dist/python/* -./scripts/test-cross-language.sh +cargo check --locked --workspace --all-targets +cargo clippy --locked --workspace --all-targets -- -D warnings +cargo doc --locked --no-deps --package openengine +cargo package --locked --package openengine ``` -The Python generator and Rust code-generation toolchain are pinned. Do not edit -generated files by hand; update the schema or generator and regenerate them. +The Rust code-generation toolchain is pinned. Do not edit generated files by hand; update the schema or generator and regenerate them. ## Signing your work diff --git a/Cargo.lock b/Cargo.lock index 51c63bc..e30c5d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,28 +4,28 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] @@ -85,9 +85,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "bytes" @@ -103,9 +103,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "either" -version = "1.16.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" [[package]] name = "equivalent" @@ -125,9 +125,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "fixedbitset" @@ -149,36 +149,36 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-core", "futures-task", @@ -199,9 +199,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.15" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", @@ -239,9 +239,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", "itoa", @@ -249,9 +249,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -259,9 +259,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", @@ -284,9 +284,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", @@ -339,9 +339,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -364,9 +364,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "linux-raw-sys" @@ -376,9 +376,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "matchit" @@ -400,9 +400,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mio" -version = "1.2.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "wasi", @@ -422,7 +422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] -name = "openengine-proto" +name = "openengine" version = "0.1.0" dependencies = [ "prost", @@ -473,7 +473,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -489,14 +489,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.119", ] [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] @@ -528,7 +528,7 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn", + "syn 2.0.119", "tempfile", ] @@ -542,7 +542,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -631,18 +631,18 @@ dependencies = [ [[package]] name = "pulldown-cmark-to-cmark" -version = "22.0.0" +version = "22.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" +checksum = "ab1ad36992cead65f02aa399a373a42730922f1525d988172634fdefdecb8a60" dependencies = [ "pulldown-cmark", ] [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -655,9 +655,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "regex" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -667,9 +667,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.15" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -697,22 +697,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] @@ -723,15 +723,15 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys", @@ -739,9 +739,20 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.118" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", @@ -769,9 +780,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ "bytes", "libc", @@ -784,20 +795,20 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "tokio-stream" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" dependencies = [ "futures-core", "pin-project-lite", @@ -806,13 +817,14 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", "futures-sink", + "libc", "pin-project-lite", "tokio", ] @@ -855,7 +867,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -880,7 +892,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn", + "syn 2.0.119", "tempfile", "tonic-build", ] @@ -935,7 +947,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index eb92e3c..e2d59f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ - "packages/rust/openengine-proto", + "packages/rust/openengine", "tools/rust-codegen", ] resolver = "2" diff --git a/README.md b/README.md index 6b501b4..7de2739 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ SPDX-License-Identifier: Apache-2.0 · Canonical schema · Release v0.1.0 · Consume from Buf + · Rust crate · Contributing

@@ -40,6 +41,7 @@ SPDX-License-Identifier: Apache-2.0 - [Getting started](#getting-started) - [Release v0.1.0](#release-v010) - [Consume from Buf](#consume-from-buf) +- [Rust crate](#rust-crate) - [Project status](#project-status) - [Contributing](#contributing) - [Security](#security) @@ -150,7 +152,7 @@ Use the immutable BSR commit as the dependency identifier. The `v0.1.0` and `mai ## Consume from Buf -OpenEngine is distributed as the [`buf.build/openengine/openengine`](https://buf.build/openengine/openengine) module. Consumers can use [BSR-generated SDKs](https://buf.build/docs/bsr/generated-sdks/) or generate bindings with their own version-pinned plugins. OpenEngine does not currently maintain first-party language packages. +OpenEngine is distributed as the [`buf.build/openengine/openengine`](https://buf.build/openengine/openengine) module. Consumers can use [BSR-generated SDKs](https://buf.build/docs/bsr/generated-sdks/) or generate bindings with their own version-pinned plugins. Rust users can instead install the first-party crate described below. Generate bindings for v0.1.0 from the immutable module input with the consumer's language-specific `buf.gen.yaml`: @@ -167,6 +169,20 @@ OpenEngine source commit instead. See [`RELEASING.md`](RELEASING.md) for BSR publication. +## Rust crate + +The `openengine` crate provides generated Prost messages and Tonic client/server bindings for `openengine.v1`: + +```bash +cargo add openengine +``` + +```rust +use openengine::v1::{control_client::ControlClient, inference_client::InferenceClient}; +``` + +The crate contains checked-in generated source and a complete protobuf descriptor set. Consumer builds do not run Buf or `protoc`. The crate also exposes the schema revision and immutable BSR commit corresponding to its bindings. + ## Project status OpenEngine v0.1.0 is an experimental, pre-adoption release. The current focus is making the contract coherent across inference engines before implementations depend on it. Expect direct schema refinement during this phase. @@ -194,7 +210,7 @@ git commit --signoff -m "docs: describe the change" Please validate protobuf changes with Buf and keep [`proto/openengine/v1/`](proto/openengine/v1/) and [`docs/api.md`](docs/api.md) -synchronized. +synchronized. Schema changes must also regenerate and commit the Rust bindings. ## Security diff --git a/RELEASING.md b/RELEASING.md index 586c331..fe5910b 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -5,7 +5,7 @@ SPDX-License-Identifier: Apache-2.0 # Releasing OpenEngine -OpenEngine publishes its canonical Protobuf schema as `buf.build/openengine/openengine`. The project does not currently maintain first-party language packages. Consumers may use BSR-generated SDKs or generate bindings with their own version-pinned plugins from an immutable BSR module commit. +OpenEngine publishes its canonical Protobuf schema as `buf.build/openengine/openengine` and generated Rust bindings as the `openengine` crate on crates.io. Schema releases use `vMAJOR.MINOR.PATCH` tags; crate releases use separate `openengine-vMAJOR.MINOR.PATCH` tags so each crate can identify an already-published immutable BSR commit. ## Prepare a release @@ -59,3 +59,49 @@ Maintainers may also run the workflow manually from `main`. A manual publication 8. Update `README.md` and `proto/openengine/v1/README.md` on `main` with the immutable BSR commit assigned during publication. Consumers may use release labels for discovery, but must not use a moving label as their production dependency. + +## Release the Rust crate + +### One-time registry configuration + +The crate must exist before crates.io allows a Trusted Publisher to be configured. Bootstrap the first release as follows: + +1. Create the `release` GitHub environment and protect it with the desired approval policy. +2. Prepare and merge the crate release commit using the process below. +3. Create the signed `openengine-vMAJOR.MINOR.PATCH` tag locally, but do not push it yet. +4. Create a short-lived crates.io token authorized to publish a new crate, publish from the tagged commit with `CARGO_REGISTRY_TOKEN=... cargo publish --locked --package openengine`, and immediately revoke the token. +5. Add the project maintainers or an `ai-dynamo` GitHub team as crate owners. +6. Configure a crates.io Trusted Publisher for GitHub owner `ai-dynamo`, repository `openengine`, workflow `rust-release.yml`, and environment `release`. +7. Push the signed tag. The workflow verifies that the existing crates.io archive matches the tagged source and skips a duplicate publication. + +Subsequent releases use crates.io Trusted Publishing and do not require a stored registry token. + +### Prepare a crate release + +1. Identify the published schema release for the bindings. If the schema changed, publish and verify it through the BSR process above first. +2. Update the workspace package version in `Cargo.toml` and set `SCHEMA_RELEASE` in `packages/rust/openengine/src/lib.rs` to the immutable BSR module commit. +3. Regenerate and validate the package: + + ```bash + ./scripts/generate-rust.sh + ./scripts/check-generated.sh + cargo check --locked --workspace --all-targets + cargo clippy --locked --workspace --all-targets -- -D warnings + cargo doc --locked --no-deps --package openengine + cargo package --locked --package openengine + ``` + +4. Update `CHANGELOG.md`, then open and merge the release-preparation pull request. + +### Publish a crate release + +Create and push a signed tag from the merged release commit: + +```bash +VERSION=0.2.0 +./scripts/check-release-version.sh "openengine-v${VERSION}" +git tag --sign "openengine-v${VERSION}" -m "OpenEngine Rust crate ${VERSION}" +git push origin "openengine-v${VERSION}" +``` + +The `Rust crate release` workflow verifies the tag, generated bindings, and packaged archive before obtaining a short-lived crates.io token through OpenID Connect and publishing the crate. Published crate versions cannot be replaced; yank a broken release and prepare a new patch version. diff --git a/packages/python/README.md b/packages/python/README.md deleted file mode 100644 index 6d6a089..0000000 --- a/packages/python/README.md +++ /dev/null @@ -1,28 +0,0 @@ - - -# OpenEngine Python bindings - -Generated protobuf messages and gRPC client/server bindings for the -[`openengine.v1`](https://github.com/ai-dynamo/openengine/tree/main/proto/openengine/v1) -protocol. - -```bash -pip install openengine-proto -``` - -```python -import grpc - -from openengine.v1.generation_pb2 import GenerateRequest -from openengine.v1.openengine_pb2_grpc import OpenEngineStub - -channel = grpc.aio.insecure_channel("localhost:50051") -engine = OpenEngineStub(channel) -request = GenerateRequest(request_id="example", model="model", prompt="Hello") -``` - -The package contains generated code. Applications do not need Buf, `protoc`, -or `grpcio-tools`. diff --git a/packages/python/pyproject.toml b/packages/python/pyproject.toml deleted file mode 100644 index 830f4cb..0000000 --- a/packages/python/pyproject.toml +++ /dev/null @@ -1,39 +0,0 @@ -[build-system] -requires = ["hatchling>=1.27,<2"] -build-backend = "hatchling.build" - -[project] -name = "openengine-proto" -version = "0.1.0" -description = "Generated Python bindings for the OpenEngine gRPC protocol" -readme = "README.md" -requires-python = ">=3.10" -license = "Apache-2.0" -authors = [{ name = "OpenEngine contributors" }] -classifiers = [ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Topic :: Software Development :: Libraries", - "Topic :: System :: Distributed Computing", -] -dependencies = [ - "grpcio>=1.81.1,<2", - "protobuf>=6.33.5,<8", -] - -[project.urls] -Documentation = "https://github.com/ai-dynamo/openengine/tree/main/docs" -Issues = "https://github.com/ai-dynamo/openengine/issues" -Repository = "https://github.com/ai-dynamo/openengine" - -[tool.hatch.build.targets.sdist] -include = [ - "/README.md", - "/pyproject.toml", - "/src", -] - -[tool.hatch.build.targets.wheel] -packages = ["src/openengine"] diff --git a/packages/python/src/openengine/__init__.py b/packages/python/src/openengine/__init__.py deleted file mode 100644 index 3dc6063..0000000 --- a/packages/python/src/openengine/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Generated Python bindings for the OpenEngine protocol.""" - -from importlib.metadata import PackageNotFoundError, version - -try: - __version__ = version("openengine-proto") -except PackageNotFoundError: - __version__ = "0.0.0+local" - -SCHEMA_REVISION = 1 -SCHEMA_RELEASE = ( - "unreleased" if __version__ == "0.0.0+local" else f"v{__version__}" -) - -__all__ = ["SCHEMA_RELEASE", "SCHEMA_REVISION", "__version__"] diff --git a/packages/python/src/openengine/py.typed b/packages/python/src/openengine/py.typed deleted file mode 100644 index 8b13789..0000000 --- a/packages/python/src/openengine/py.typed +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/python/src/openengine/v1/__init__.py b/packages/python/src/openengine/v1/__init__.py deleted file mode 100644 index 32b0339..0000000 --- a/packages/python/src/openengine/v1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""The generated ``openengine.v1`` protobuf package.""" diff --git a/packages/python/src/openengine/v1/engine_pb2.py b/packages/python/src/openengine/v1/engine_pb2.py deleted file mode 100644 index 30df65b..0000000 --- a/packages/python/src/openengine/v1/engine_pb2.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/engine.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/engine.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aopenengine/v1/engine.proto\x12\ropenengine.v1\x1a\x16openengine/v1/kv.proto\"\x16\n\x14GetEngineInfoRequest\"\xce\x02\n\nEngineInfo\x12\x13\n\x0b\x65ngine_name\x18\x01 \x01(\t\x12\x16\n\x0e\x65ngine_version\x18\x02 \x01(\t\x12\'\n\x04role\x18\x03 \x01(\x0e\x32\x19.openengine.v1.EngineRole\x12\x13\n\x0binstance_id\x18\x04 \x01(\t\x12\x18\n\x10supported_models\x18\x05 \x03(\t\x12\x33\n\x0bparallelism\x18\x06 \x01(\x0b\x32\x1e.openengine.v1.ParallelismInfo\x12\x34\n\x0ckv_connector\x18\x07 \x01(\x0b\x32\x1e.openengine.v1.KvConnectorInfo\x12\x17\n\x0fschema_revision\x18\x08 \x01(\r\x12\x1f\n\x17minimum_client_revision\x18\t \x01(\r\x12\x16\n\x0eschema_release\x18\n \x01(\t\"\xc1\x02\n\x0fParallelismInfo\x12!\n\x14tensor_parallel_size\x18\x01 \x01(\rH\x00\x88\x01\x01\x12#\n\x16pipeline_parallel_size\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1f\n\x12\x64\x61ta_parallel_size\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x04 \x01(\rH\x03\x88\x01\x01\x12%\n\x18\x64\x61ta_parallel_start_rank\x18\x05 \x01(\rH\x04\x88\x01\x01\x42\x17\n\x15_tensor_parallel_sizeB\x19\n\x17_pipeline_parallel_sizeB\x15\n\x13_data_parallel_sizeB\x15\n\x13_data_parallel_rankB\x1b\n\x19_data_parallel_start_rank*v\n\nEngineRole\x12\x1b\n\x17\x45NGINE_ROLE_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x45NGINE_ROLE_AGGREGATED\x10\x01\x12\x17\n\x13\x45NGINE_ROLE_PREFILL\x10\x02\x12\x16\n\x12\x45NGINE_ROLE_DECODE\x10\x03\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.engine_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_ENGINEROLE']._serialized_start=754 - _globals['_ENGINEROLE']._serialized_end=872 - _globals['_GETENGINEINFOREQUEST']._serialized_start=69 - _globals['_GETENGINEINFOREQUEST']._serialized_end=91 - _globals['_ENGINEINFO']._serialized_start=94 - _globals['_ENGINEINFO']._serialized_end=428 - _globals['_PARALLELISMINFO']._serialized_start=431 - _globals['_PARALLELISMINFO']._serialized_end=752 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/engine_pb2.pyi b/packages/python/src/openengine/v1/engine_pb2.pyi deleted file mode 100644 index e07e53b..0000000 --- a/packages/python/src/openengine/v1/engine_pb2.pyi +++ /dev/null @@ -1,62 +0,0 @@ -from openengine.v1 import kv_pb2 as _kv_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class EngineRole(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - ENGINE_ROLE_UNSPECIFIED: _ClassVar[EngineRole] - ENGINE_ROLE_AGGREGATED: _ClassVar[EngineRole] - ENGINE_ROLE_PREFILL: _ClassVar[EngineRole] - ENGINE_ROLE_DECODE: _ClassVar[EngineRole] -ENGINE_ROLE_UNSPECIFIED: EngineRole -ENGINE_ROLE_AGGREGATED: EngineRole -ENGINE_ROLE_PREFILL: EngineRole -ENGINE_ROLE_DECODE: EngineRole - -class GetEngineInfoRequest(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class EngineInfo(_message.Message): - __slots__ = ("engine_name", "engine_version", "role", "instance_id", "supported_models", "parallelism", "kv_connector", "schema_revision", "minimum_client_revision", "schema_release") - ENGINE_NAME_FIELD_NUMBER: _ClassVar[int] - ENGINE_VERSION_FIELD_NUMBER: _ClassVar[int] - ROLE_FIELD_NUMBER: _ClassVar[int] - INSTANCE_ID_FIELD_NUMBER: _ClassVar[int] - SUPPORTED_MODELS_FIELD_NUMBER: _ClassVar[int] - PARALLELISM_FIELD_NUMBER: _ClassVar[int] - KV_CONNECTOR_FIELD_NUMBER: _ClassVar[int] - SCHEMA_REVISION_FIELD_NUMBER: _ClassVar[int] - MINIMUM_CLIENT_REVISION_FIELD_NUMBER: _ClassVar[int] - SCHEMA_RELEASE_FIELD_NUMBER: _ClassVar[int] - engine_name: str - engine_version: str - role: EngineRole - instance_id: str - supported_models: _containers.RepeatedScalarFieldContainer[str] - parallelism: ParallelismInfo - kv_connector: _kv_pb2.KvConnectorInfo - schema_revision: int - minimum_client_revision: int - schema_release: str - def __init__(self, engine_name: _Optional[str] = ..., engine_version: _Optional[str] = ..., role: _Optional[_Union[EngineRole, str]] = ..., instance_id: _Optional[str] = ..., supported_models: _Optional[_Iterable[str]] = ..., parallelism: _Optional[_Union[ParallelismInfo, _Mapping]] = ..., kv_connector: _Optional[_Union[_kv_pb2.KvConnectorInfo, _Mapping]] = ..., schema_revision: _Optional[int] = ..., minimum_client_revision: _Optional[int] = ..., schema_release: _Optional[str] = ...) -> None: ... - -class ParallelismInfo(_message.Message): - __slots__ = ("tensor_parallel_size", "pipeline_parallel_size", "data_parallel_size", "data_parallel_rank", "data_parallel_start_rank") - TENSOR_PARALLEL_SIZE_FIELD_NUMBER: _ClassVar[int] - PIPELINE_PARALLEL_SIZE_FIELD_NUMBER: _ClassVar[int] - DATA_PARALLEL_SIZE_FIELD_NUMBER: _ClassVar[int] - DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] - DATA_PARALLEL_START_RANK_FIELD_NUMBER: _ClassVar[int] - tensor_parallel_size: int - pipeline_parallel_size: int - data_parallel_size: int - data_parallel_rank: int - data_parallel_start_rank: int - def __init__(self, tensor_parallel_size: _Optional[int] = ..., pipeline_parallel_size: _Optional[int] = ..., data_parallel_size: _Optional[int] = ..., data_parallel_rank: _Optional[int] = ..., data_parallel_start_rank: _Optional[int] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/error_pb2.py b/packages/python/src/openengine/v1/error_pb2.py deleted file mode 100644 index 907d15a..0000000 --- a/packages/python/src/openengine/v1/error_pb2.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/error.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/error.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19openengine/v1/error.proto\x12\ropenengine.v1\x1a\x1cgoogle/protobuf/struct.proto\"\xb3\x01\n\x0b\x45ngineError\x12&\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x18.openengine.v1.ErrorCode\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\tretryable\x18\x03 \x01(\x08\x12\x1b\n\x0eretry_after_ms\x18\x04 \x01(\x04H\x00\x88\x01\x01\x12(\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructB\x11\n\x0f_retry_after_ms*\x9d\x03\n\tErrorCode\x12\x1a\n\x16\x45RROR_CODE_UNSPECIFIED\x10\x00\x12\x1f\n\x1b\x45RROR_CODE_INVALID_ARGUMENT\x10\x01\x12\"\n\x1e\x45RROR_CODE_UNSUPPORTED_FEATURE\x10\x02\x12\x1c\n\x18\x45RROR_CODE_ROLE_MISMATCH\x10\x03\x12\x1e\n\x1a\x45RROR_CODE_MODEL_NOT_FOUND\x10\x04\x12\x19\n\x15\x45RROR_CODE_OVERLOADED\x10\x05\x12 \n\x1c\x45RROR_CODE_REQUEST_NOT_FOUND\x10\x06\x12 \n\x1c\x45RROR_CODE_DUPLICATE_REQUEST\x10\x07\x12#\n\x1f\x45RROR_CODE_KV_SESSION_NOT_FOUND\x10\x08\x12!\n\x1d\x45RROR_CODE_KV_TRANSFER_FAILED\x10\t\x12\x18\n\x14\x45RROR_CODE_CANCELLED\x10\n\x12\x17\n\x13\x45RROR_CODE_DRAINING\x10\x0b\x12\x17\n\x13\x45RROR_CODE_INTERNAL\x10\x0c\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.error_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_ERRORCODE']._serialized_start=257 - _globals['_ERRORCODE']._serialized_end=670 - _globals['_ENGINEERROR']._serialized_start=75 - _globals['_ENGINEERROR']._serialized_end=254 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/error_pb2.pyi b/packages/python/src/openengine/v1/error_pb2.pyi deleted file mode 100644 index 4933b85..0000000 --- a/packages/python/src/openengine/v1/error_pb2.pyi +++ /dev/null @@ -1,51 +0,0 @@ -from google.protobuf import struct_pb2 as _struct_pb2 -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class ErrorCode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - ERROR_CODE_UNSPECIFIED: _ClassVar[ErrorCode] - ERROR_CODE_INVALID_ARGUMENT: _ClassVar[ErrorCode] - ERROR_CODE_UNSUPPORTED_FEATURE: _ClassVar[ErrorCode] - ERROR_CODE_ROLE_MISMATCH: _ClassVar[ErrorCode] - ERROR_CODE_MODEL_NOT_FOUND: _ClassVar[ErrorCode] - ERROR_CODE_OVERLOADED: _ClassVar[ErrorCode] - ERROR_CODE_REQUEST_NOT_FOUND: _ClassVar[ErrorCode] - ERROR_CODE_DUPLICATE_REQUEST: _ClassVar[ErrorCode] - ERROR_CODE_KV_SESSION_NOT_FOUND: _ClassVar[ErrorCode] - ERROR_CODE_KV_TRANSFER_FAILED: _ClassVar[ErrorCode] - ERROR_CODE_CANCELLED: _ClassVar[ErrorCode] - ERROR_CODE_DRAINING: _ClassVar[ErrorCode] - ERROR_CODE_INTERNAL: _ClassVar[ErrorCode] -ERROR_CODE_UNSPECIFIED: ErrorCode -ERROR_CODE_INVALID_ARGUMENT: ErrorCode -ERROR_CODE_UNSUPPORTED_FEATURE: ErrorCode -ERROR_CODE_ROLE_MISMATCH: ErrorCode -ERROR_CODE_MODEL_NOT_FOUND: ErrorCode -ERROR_CODE_OVERLOADED: ErrorCode -ERROR_CODE_REQUEST_NOT_FOUND: ErrorCode -ERROR_CODE_DUPLICATE_REQUEST: ErrorCode -ERROR_CODE_KV_SESSION_NOT_FOUND: ErrorCode -ERROR_CODE_KV_TRANSFER_FAILED: ErrorCode -ERROR_CODE_CANCELLED: ErrorCode -ERROR_CODE_DRAINING: ErrorCode -ERROR_CODE_INTERNAL: ErrorCode - -class EngineError(_message.Message): - __slots__ = ("code", "message", "retryable", "retry_after_ms", "details") - CODE_FIELD_NUMBER: _ClassVar[int] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - RETRYABLE_FIELD_NUMBER: _ClassVar[int] - RETRY_AFTER_MS_FIELD_NUMBER: _ClassVar[int] - DETAILS_FIELD_NUMBER: _ClassVar[int] - code: ErrorCode - message: str - retryable: bool - retry_after_ms: int - details: _struct_pb2.Struct - def __init__(self, code: _Optional[_Union[ErrorCode, str]] = ..., message: _Optional[str] = ..., retryable: _Optional[bool] = ..., retry_after_ms: _Optional[int] = ..., details: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/generation_params_pb2.py b/packages/python/src/openengine/v1/generation_params_pb2.py deleted file mode 100644 index c0ac8c6..0000000 --- a/packages/python/src/openengine/v1/generation_params_pb2.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/generation_params.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/generation_params.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%openengine/v1/generation_params.proto\x12\ropenengine.v1\x1a\x16openengine/v1/kv.proto\"\x17\n\x08TokenIds\x12\x0b\n\x03ids\x18\x01 \x03(\r\"\x80\x03\n\x0eSamplingParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x01H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x12\n\x05min_p\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x1e\n\x11\x66requency_penalty\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x1d\n\x10presence_penalty\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12\x1f\n\x12repetition_penalty\x18\x07 \x01(\x01H\x06\x88\x01\x01\x12\x11\n\x04seed\x18\x08 \x01(\x04H\x07\x88\x01\x01\x12\x1a\n\rnum_sequences\x18\t \x01(\rH\x08\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\x08\n\x06_min_pB\x14\n\x12_frequency_penaltyB\x13\n\x11_presence_penaltyB\x15\n\x13_repetition_penaltyB\x07\n\x05_seedB\x10\n\x0e_num_sequences\"\xfb\x01\n\x0fStoppingOptions\x12\x17\n\nmax_tokens\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x17\n\nmin_tokens\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x30\n\nconditions\x18\x03 \x03(\x0b\x32\x1c.openengine.v1.StopCondition\x12\x17\n\nignore_eos\x18\x04 \x01(\x08H\x02\x88\x01\x01\x12#\n\x16include_stop_in_output\x18\x05 \x01(\x08H\x03\x88\x01\x01\x42\r\n\x0b_max_tokensB\r\n\x0b_min_tokensB\r\n\x0b_ignore_eosB\x19\n\x17_include_stop_in_output\"\xd3\x02\n\x0fResponseOptions\x12#\n\x16return_prompt_logprobs\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x41\n\x11prompt_candidates\x18\x02 \x01(\x0b\x32&.openengine.v1.CandidateTokenSelection\x12#\n\x16return_output_logprobs\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x41\n\x11output_candidates\x18\x04 \x01(\x0b\x32&.openengine.v1.CandidateTokenSelection\x12!\n\x14prompt_logprob_start\x18\x05 \x01(\rH\x02\x88\x01\x01\x42\x19\n\x17_return_prompt_logprobsB\x19\n\x17_return_output_logprobsB\x17\n\x15_prompt_logprob_start\"\x92\x01\n\x17\x43\x61ndidateTokenSelection\x12\x0f\n\x05top_n\x18\x01 \x01(\rH\x00\x12,\n\ttoken_ids\x18\x02 \x01(\x0b\x32\x17.openengine.v1.TokenIdsH\x00\x12+\n\x03\x61ll\x18\x03 \x01(\x0b\x32\x1c.openengine.v1.AllCandidatesH\x00\x42\x0b\n\tselection\"\x0f\n\rAllCandidates\"\xd3\x01\n\tKvOptions\x12,\n\x07session\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRef\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x02 \x01(\rH\x00\x88\x01\x01\x12 \n\x13\x62ypass_prefix_cache\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x17\n\ncache_salt\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\x15\n\x13_data_parallel_rankB\x16\n\x14_bypass_prefix_cacheB\r\n\x0b_cache_salt\"J\n\rStopCondition\x12\x13\n\tstop_text\x18\x01 \x01(\tH\x00\x12\x17\n\rstop_token_id\x18\x02 \x01(\rH\x00\x42\x0b\n\tcondition\"\xf3\x01\n\x0eGuidedDecoding\x12\x15\n\x0bjson_schema\x18\x01 \x01(\tH\x00\x12\x0f\n\x05regex\x18\x02 \x01(\tH\x00\x12\x16\n\x0c\x65\x62nf_grammar\x18\x03 \x01(\tH\x00\x12\x18\n\x0estructural_tag\x18\x04 \x01(\tH\x00\x12\x31\n\x06\x63hoice\x18\x05 \x01(\x0b\x32\x1f.openengine.v1.ChoiceConstraintH\x00\x12:\n\x0bjson_object\x18\x06 \x01(\x0b\x32#.openengine.v1.JsonObjectConstraintH\x00\x12\x0f\n\x07\x62\x61\x63kend\x18\x07 \x01(\tB\x07\n\x05guide\"#\n\x10\x43hoiceConstraint\x12\x0f\n\x07\x63hoices\x18\x01 \x03(\t\"\x16\n\x14JsonObjectConstraintb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.generation_params_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_TOKENIDS']._serialized_start=80 - _globals['_TOKENIDS']._serialized_end=103 - _globals['_SAMPLINGPARAMS']._serialized_start=106 - _globals['_SAMPLINGPARAMS']._serialized_end=490 - _globals['_STOPPINGOPTIONS']._serialized_start=493 - _globals['_STOPPINGOPTIONS']._serialized_end=744 - _globals['_RESPONSEOPTIONS']._serialized_start=747 - _globals['_RESPONSEOPTIONS']._serialized_end=1086 - _globals['_CANDIDATETOKENSELECTION']._serialized_start=1089 - _globals['_CANDIDATETOKENSELECTION']._serialized_end=1235 - _globals['_ALLCANDIDATES']._serialized_start=1237 - _globals['_ALLCANDIDATES']._serialized_end=1252 - _globals['_KVOPTIONS']._serialized_start=1255 - _globals['_KVOPTIONS']._serialized_end=1466 - _globals['_STOPCONDITION']._serialized_start=1468 - _globals['_STOPCONDITION']._serialized_end=1542 - _globals['_GUIDEDDECODING']._serialized_start=1545 - _globals['_GUIDEDDECODING']._serialized_end=1788 - _globals['_CHOICECONSTRAINT']._serialized_start=1790 - _globals['_CHOICECONSTRAINT']._serialized_end=1825 - _globals['_JSONOBJECTCONSTRAINT']._serialized_start=1827 - _globals['_JSONOBJECTCONSTRAINT']._serialized_end=1849 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/generation_params_pb2.pyi b/packages/python/src/openengine/v1/generation_params_pb2.pyi deleted file mode 100644 index 79dc46e..0000000 --- a/packages/python/src/openengine/v1/generation_params_pb2.pyi +++ /dev/null @@ -1,126 +0,0 @@ -from openengine.v1 import kv_pb2 as _kv_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class TokenIds(_message.Message): - __slots__ = ("ids",) - IDS_FIELD_NUMBER: _ClassVar[int] - ids: _containers.RepeatedScalarFieldContainer[int] - def __init__(self, ids: _Optional[_Iterable[int]] = ...) -> None: ... - -class SamplingParams(_message.Message): - __slots__ = ("temperature", "top_p", "top_k", "min_p", "frequency_penalty", "presence_penalty", "repetition_penalty", "seed", "num_sequences") - TEMPERATURE_FIELD_NUMBER: _ClassVar[int] - TOP_P_FIELD_NUMBER: _ClassVar[int] - TOP_K_FIELD_NUMBER: _ClassVar[int] - MIN_P_FIELD_NUMBER: _ClassVar[int] - FREQUENCY_PENALTY_FIELD_NUMBER: _ClassVar[int] - PRESENCE_PENALTY_FIELD_NUMBER: _ClassVar[int] - REPETITION_PENALTY_FIELD_NUMBER: _ClassVar[int] - SEED_FIELD_NUMBER: _ClassVar[int] - NUM_SEQUENCES_FIELD_NUMBER: _ClassVar[int] - temperature: float - top_p: float - top_k: int - min_p: float - frequency_penalty: float - presence_penalty: float - repetition_penalty: float - seed: int - num_sequences: int - def __init__(self, temperature: _Optional[float] = ..., top_p: _Optional[float] = ..., top_k: _Optional[int] = ..., min_p: _Optional[float] = ..., frequency_penalty: _Optional[float] = ..., presence_penalty: _Optional[float] = ..., repetition_penalty: _Optional[float] = ..., seed: _Optional[int] = ..., num_sequences: _Optional[int] = ...) -> None: ... - -class StoppingOptions(_message.Message): - __slots__ = ("max_tokens", "min_tokens", "conditions", "ignore_eos", "include_stop_in_output") - MAX_TOKENS_FIELD_NUMBER: _ClassVar[int] - MIN_TOKENS_FIELD_NUMBER: _ClassVar[int] - CONDITIONS_FIELD_NUMBER: _ClassVar[int] - IGNORE_EOS_FIELD_NUMBER: _ClassVar[int] - INCLUDE_STOP_IN_OUTPUT_FIELD_NUMBER: _ClassVar[int] - max_tokens: int - min_tokens: int - conditions: _containers.RepeatedCompositeFieldContainer[StopCondition] - ignore_eos: bool - include_stop_in_output: bool - def __init__(self, max_tokens: _Optional[int] = ..., min_tokens: _Optional[int] = ..., conditions: _Optional[_Iterable[_Union[StopCondition, _Mapping]]] = ..., ignore_eos: _Optional[bool] = ..., include_stop_in_output: _Optional[bool] = ...) -> None: ... - -class ResponseOptions(_message.Message): - __slots__ = ("return_prompt_logprobs", "prompt_candidates", "return_output_logprobs", "output_candidates", "prompt_logprob_start") - RETURN_PROMPT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] - PROMPT_CANDIDATES_FIELD_NUMBER: _ClassVar[int] - RETURN_OUTPUT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] - OUTPUT_CANDIDATES_FIELD_NUMBER: _ClassVar[int] - PROMPT_LOGPROB_START_FIELD_NUMBER: _ClassVar[int] - return_prompt_logprobs: bool - prompt_candidates: CandidateTokenSelection - return_output_logprobs: bool - output_candidates: CandidateTokenSelection - prompt_logprob_start: int - def __init__(self, return_prompt_logprobs: _Optional[bool] = ..., prompt_candidates: _Optional[_Union[CandidateTokenSelection, _Mapping]] = ..., return_output_logprobs: _Optional[bool] = ..., output_candidates: _Optional[_Union[CandidateTokenSelection, _Mapping]] = ..., prompt_logprob_start: _Optional[int] = ...) -> None: ... - -class CandidateTokenSelection(_message.Message): - __slots__ = ("top_n", "token_ids", "all") - TOP_N_FIELD_NUMBER: _ClassVar[int] - TOKEN_IDS_FIELD_NUMBER: _ClassVar[int] - ALL_FIELD_NUMBER: _ClassVar[int] - top_n: int - token_ids: TokenIds - all: AllCandidates - def __init__(self, top_n: _Optional[int] = ..., token_ids: _Optional[_Union[TokenIds, _Mapping]] = ..., all: _Optional[_Union[AllCandidates, _Mapping]] = ...) -> None: ... - -class AllCandidates(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class KvOptions(_message.Message): - __slots__ = ("session", "data_parallel_rank", "bypass_prefix_cache", "cache_salt") - SESSION_FIELD_NUMBER: _ClassVar[int] - DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] - BYPASS_PREFIX_CACHE_FIELD_NUMBER: _ClassVar[int] - CACHE_SALT_FIELD_NUMBER: _ClassVar[int] - session: _kv_pb2.KvSessionRef - data_parallel_rank: int - bypass_prefix_cache: bool - cache_salt: str - def __init__(self, session: _Optional[_Union[_kv_pb2.KvSessionRef, _Mapping]] = ..., data_parallel_rank: _Optional[int] = ..., bypass_prefix_cache: _Optional[bool] = ..., cache_salt: _Optional[str] = ...) -> None: ... - -class StopCondition(_message.Message): - __slots__ = ("stop_text", "stop_token_id") - STOP_TEXT_FIELD_NUMBER: _ClassVar[int] - STOP_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] - stop_text: str - stop_token_id: int - def __init__(self, stop_text: _Optional[str] = ..., stop_token_id: _Optional[int] = ...) -> None: ... - -class GuidedDecoding(_message.Message): - __slots__ = ("json_schema", "regex", "ebnf_grammar", "structural_tag", "choice", "json_object", "backend") - JSON_SCHEMA_FIELD_NUMBER: _ClassVar[int] - REGEX_FIELD_NUMBER: _ClassVar[int] - EBNF_GRAMMAR_FIELD_NUMBER: _ClassVar[int] - STRUCTURAL_TAG_FIELD_NUMBER: _ClassVar[int] - CHOICE_FIELD_NUMBER: _ClassVar[int] - JSON_OBJECT_FIELD_NUMBER: _ClassVar[int] - BACKEND_FIELD_NUMBER: _ClassVar[int] - json_schema: str - regex: str - ebnf_grammar: str - structural_tag: str - choice: ChoiceConstraint - json_object: JsonObjectConstraint - backend: str - def __init__(self, json_schema: _Optional[str] = ..., regex: _Optional[str] = ..., ebnf_grammar: _Optional[str] = ..., structural_tag: _Optional[str] = ..., choice: _Optional[_Union[ChoiceConstraint, _Mapping]] = ..., json_object: _Optional[_Union[JsonObjectConstraint, _Mapping]] = ..., backend: _Optional[str] = ...) -> None: ... - -class ChoiceConstraint(_message.Message): - __slots__ = ("choices",) - CHOICES_FIELD_NUMBER: _ClassVar[int] - choices: _containers.RepeatedScalarFieldContainer[str] - def __init__(self, choices: _Optional[_Iterable[str]] = ...) -> None: ... - -class JsonObjectConstraint(_message.Message): - __slots__ = () - def __init__(self) -> None: ... diff --git a/packages/python/src/openengine/v1/generation_pb2.py b/packages/python/src/openengine/v1/generation_pb2.py deleted file mode 100644 index 0f16498..0000000 --- a/packages/python/src/openengine/v1/generation_pb2.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/generation.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/generation.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 -from openengine.v1 import generation_params_pb2 as openengine_dot_v1_dot_generation__params__pb2 -from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eopenengine/v1/generation.proto\x12\ropenengine.v1\x1a\x19openengine/v1/error.proto\x1a%openengine/v1/generation_params.proto\x1a\x16openengine/v1/kv.proto\"\xb8\x04\n\x0fGenerateRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\x10\n\x06prompt\x18\x03 \x01(\tH\x00\x12,\n\ttoken_ids\x18\x04 \x01(\x0b\x32\x17.openengine.v1.TokenIdsH\x00\x12/\n\x08sampling\x18\x05 \x01(\x0b\x32\x1d.openengine.v1.SamplingParams\x12\x30\n\x08stopping\x18\x06 \x01(\x0b\x32\x1e.openengine.v1.StoppingOptions\x12\x30\n\x08response\x18\x07 \x01(\x0b\x32\x1e.openengine.v1.ResponseOptions\x12$\n\x02kv\x18\x08 \x01(\x0b\x32\x18.openengine.v1.KvOptions\x12-\n\x06guided\x18\t \x01(\x0b\x32\x1d.openengine.v1.GuidedDecoding\x12\'\n\x05media\x18\n \x03(\x0b\x32\x18.openengine.v1.MediaItem\x12\x11\n\tlora_name\x18\x0b \x01(\t\x12\x15\n\x08priority\x18\x0c \x01(\x05H\x01\x88\x01\x01\x12>\n\x08metadata\x18\r \x03(\x0b\x32,.openengine.v1.GenerateRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x07\n\x05inputB\x0b\n\t_priority\"\x99\x01\n\tMediaItem\x12)\n\x08modality\x18\x01 \x01(\x0e\x32\x17.openengine.v1.Modality\x12\r\n\x03url\x18\x02 \x01(\tH\x00\x12\x12\n\x08\x64\x61ta_uri\x18\x03 \x01(\tH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x12\x11\n\tmime_type\x18\x05 \x01(\t\x12\x0c\n\x04uuid\x18\x06 \x01(\tB\x08\n\x06source\"\xca\x02\n\x10GenerateResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12-\n\x06prompt\x18\x02 \x01(\x0b\x32\x1b.openengine.v1.PromptOutputH\x00\x12+\n\x05token\x18\x03 \x01(\x0b\x32\x1a.openengine.v1.TokenOutputH\x00\x12\x34\n\rprefill_ready\x18\x04 \x01(\x0b\x32\x1b.openengine.v1.PrefillReadyH\x00\x12\x35\n\x08\x66inished\x18\x05 \x01(\x0b\x32!.openengine.v1.GenerationFinishedH\x00\x12+\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x12#\n\x05usage\x18\n \x01(\x0b\x32\x14.openengine.v1.UsageB\x07\n\x05\x65vent\"8\n\x0cPromptOutput\x12(\n\x06tokens\x18\x01 \x03(\x0b\x32\x18.openengine.v1.TokenInfo\"q\n\x0bTokenOutput\x12\x19\n\x0coutput_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12(\n\x06tokens\x18\x02 \x03(\x0b\x32\x18.openengine.v1.TokenInfo\x12\x0c\n\x04text\x18\x03 \x01(\tB\x0f\n\r_output_index\"\x96\x01\n\tTokenInfo\x12\x10\n\x08token_id\x18\x01 \x01(\r\x12\r\n\x05token\x18\x02 \x01(\t\x12\x14\n\x07logprob\x18\x03 \x01(\x01H\x00\x88\x01\x01\x12\x11\n\x04rank\x18\x04 \x01(\rH\x01\x88\x01\x01\x12*\n\ncandidates\x18\x05 \x03(\x0b\x32\x16.openengine.v1.LogProbB\n\n\x08_logprobB\x07\n\x05_rank\"W\n\x07LogProb\x12\x10\n\x08token_id\x18\x01 \x01(\r\x12\x0f\n\x07logprob\x18\x02 \x01(\x01\x12\r\n\x05token\x18\x03 \x01(\t\x12\x11\n\x04rank\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x07\n\x05_rank\"?\n\x0cPrefillReady\x12/\n\nkv_session\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRef\"\xac\x01\n\x12GenerationFinished\x12\x19\n\x0coutput_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12+\n\x06reason\x18\x02 \x01(\x0e\x32\x1b.openengine.v1.FinishReason\x12\x0f\n\x07message\x18\x03 \x01(\t\x12,\n\nstop_match\x18\x04 \x01(\x0b\x32\x18.openengine.v1.StopMatchB\x0f\n\r_output_index\"Z\n\tStopMatch\x12\x17\n\rstop_token_id\x18\x01 \x01(\rH\x00\x12\x13\n\tstop_text\x18\x02 \x01(\tH\x00\x12\x16\n\x0c\x65os_token_id\x18\x03 \x01(\rH\x00\x42\x07\n\x05match\"\xbf\x01\n\x05Usage\x12\x15\n\rprompt_tokens\x18\x01 \x01(\r\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\r\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\r\x12!\n\x14\x63\x61\x63hed_prompt_tokens\x18\x04 \x01(\rH\x00\x88\x01\x01\x12\x1d\n\x10reasoning_tokens\x18\x05 \x01(\rH\x01\x88\x01\x01\x42\x17\n\x15_cached_prompt_tokensB\x13\n\x11_reasoning_tokens*`\n\x08Modality\x12\x18\n\x14MODALITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eMODALITY_IMAGE\x10\x01\x12\x12\n\x0eMODALITY_VIDEO\x10\x02\x12\x12\n\x0eMODALITY_AUDIO\x10\x03*|\n\x0c\x46inishReason\x12\x1d\n\x19\x46INISH_REASON_UNSPECIFIED\x10\x00\x12\x16\n\x12\x46INISH_REASON_STOP\x10\x01\x12\x18\n\x14\x46INISH_REASON_LENGTH\x10\x02\x12\x1b\n\x17\x46INISH_REASON_CANCELLED\x10\x03\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.generation_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_GENERATEREQUEST_METADATAENTRY']._loaded_options = None - _globals['_GENERATEREQUEST_METADATAENTRY']._serialized_options = b'8\001' - _globals['_MODALITY']._serialized_start=2140 - _globals['_MODALITY']._serialized_end=2236 - _globals['_FINISHREASON']._serialized_start=2238 - _globals['_FINISHREASON']._serialized_end=2362 - _globals['_GENERATEREQUEST']._serialized_start=140 - _globals['_GENERATEREQUEST']._serialized_end=708 - _globals['_GENERATEREQUEST_METADATAENTRY']._serialized_start=639 - _globals['_GENERATEREQUEST_METADATAENTRY']._serialized_end=686 - _globals['_MEDIAITEM']._serialized_start=711 - _globals['_MEDIAITEM']._serialized_end=864 - _globals['_GENERATERESPONSE']._serialized_start=867 - _globals['_GENERATERESPONSE']._serialized_end=1197 - _globals['_PROMPTOUTPUT']._serialized_start=1199 - _globals['_PROMPTOUTPUT']._serialized_end=1255 - _globals['_TOKENOUTPUT']._serialized_start=1257 - _globals['_TOKENOUTPUT']._serialized_end=1370 - _globals['_TOKENINFO']._serialized_start=1373 - _globals['_TOKENINFO']._serialized_end=1523 - _globals['_LOGPROB']._serialized_start=1525 - _globals['_LOGPROB']._serialized_end=1612 - _globals['_PREFILLREADY']._serialized_start=1614 - _globals['_PREFILLREADY']._serialized_end=1677 - _globals['_GENERATIONFINISHED']._serialized_start=1680 - _globals['_GENERATIONFINISHED']._serialized_end=1852 - _globals['_STOPMATCH']._serialized_start=1854 - _globals['_STOPMATCH']._serialized_end=1944 - _globals['_USAGE']._serialized_start=1947 - _globals['_USAGE']._serialized_end=2138 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/generation_pb2.pyi b/packages/python/src/openengine/v1/generation_pb2.pyi deleted file mode 100644 index 8340f78..0000000 --- a/packages/python/src/openengine/v1/generation_pb2.pyi +++ /dev/null @@ -1,188 +0,0 @@ -from openengine.v1 import error_pb2 as _error_pb2 -from openengine.v1 import generation_params_pb2 as _generation_params_pb2 -from openengine.v1 import kv_pb2 as _kv_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class Modality(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - MODALITY_UNSPECIFIED: _ClassVar[Modality] - MODALITY_IMAGE: _ClassVar[Modality] - MODALITY_VIDEO: _ClassVar[Modality] - MODALITY_AUDIO: _ClassVar[Modality] - -class FinishReason(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - FINISH_REASON_UNSPECIFIED: _ClassVar[FinishReason] - FINISH_REASON_STOP: _ClassVar[FinishReason] - FINISH_REASON_LENGTH: _ClassVar[FinishReason] - FINISH_REASON_CANCELLED: _ClassVar[FinishReason] -MODALITY_UNSPECIFIED: Modality -MODALITY_IMAGE: Modality -MODALITY_VIDEO: Modality -MODALITY_AUDIO: Modality -FINISH_REASON_UNSPECIFIED: FinishReason -FINISH_REASON_STOP: FinishReason -FINISH_REASON_LENGTH: FinishReason -FINISH_REASON_CANCELLED: FinishReason - -class GenerateRequest(_message.Message): - __slots__ = ("request_id", "model", "prompt", "token_ids", "sampling", "stopping", "response", "kv", "guided", "media", "lora_name", "priority", "metadata") - class MetadataEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... - REQUEST_ID_FIELD_NUMBER: _ClassVar[int] - MODEL_FIELD_NUMBER: _ClassVar[int] - PROMPT_FIELD_NUMBER: _ClassVar[int] - TOKEN_IDS_FIELD_NUMBER: _ClassVar[int] - SAMPLING_FIELD_NUMBER: _ClassVar[int] - STOPPING_FIELD_NUMBER: _ClassVar[int] - RESPONSE_FIELD_NUMBER: _ClassVar[int] - KV_FIELD_NUMBER: _ClassVar[int] - GUIDED_FIELD_NUMBER: _ClassVar[int] - MEDIA_FIELD_NUMBER: _ClassVar[int] - LORA_NAME_FIELD_NUMBER: _ClassVar[int] - PRIORITY_FIELD_NUMBER: _ClassVar[int] - METADATA_FIELD_NUMBER: _ClassVar[int] - request_id: str - model: str - prompt: str - token_ids: _generation_params_pb2.TokenIds - sampling: _generation_params_pb2.SamplingParams - stopping: _generation_params_pb2.StoppingOptions - response: _generation_params_pb2.ResponseOptions - kv: _generation_params_pb2.KvOptions - guided: _generation_params_pb2.GuidedDecoding - media: _containers.RepeatedCompositeFieldContainer[MediaItem] - lora_name: str - priority: int - metadata: _containers.ScalarMap[str, str] - def __init__(self, request_id: _Optional[str] = ..., model: _Optional[str] = ..., prompt: _Optional[str] = ..., token_ids: _Optional[_Union[_generation_params_pb2.TokenIds, _Mapping]] = ..., sampling: _Optional[_Union[_generation_params_pb2.SamplingParams, _Mapping]] = ..., stopping: _Optional[_Union[_generation_params_pb2.StoppingOptions, _Mapping]] = ..., response: _Optional[_Union[_generation_params_pb2.ResponseOptions, _Mapping]] = ..., kv: _Optional[_Union[_generation_params_pb2.KvOptions, _Mapping]] = ..., guided: _Optional[_Union[_generation_params_pb2.GuidedDecoding, _Mapping]] = ..., media: _Optional[_Iterable[_Union[MediaItem, _Mapping]]] = ..., lora_name: _Optional[str] = ..., priority: _Optional[int] = ..., metadata: _Optional[_Mapping[str, str]] = ...) -> None: ... - -class MediaItem(_message.Message): - __slots__ = ("modality", "url", "data_uri", "raw_bytes", "mime_type", "uuid") - MODALITY_FIELD_NUMBER: _ClassVar[int] - URL_FIELD_NUMBER: _ClassVar[int] - DATA_URI_FIELD_NUMBER: _ClassVar[int] - RAW_BYTES_FIELD_NUMBER: _ClassVar[int] - MIME_TYPE_FIELD_NUMBER: _ClassVar[int] - UUID_FIELD_NUMBER: _ClassVar[int] - modality: Modality - url: str - data_uri: str - raw_bytes: bytes - mime_type: str - uuid: str - def __init__(self, modality: _Optional[_Union[Modality, str]] = ..., url: _Optional[str] = ..., data_uri: _Optional[str] = ..., raw_bytes: _Optional[bytes] = ..., mime_type: _Optional[str] = ..., uuid: _Optional[str] = ...) -> None: ... - -class GenerateResponse(_message.Message): - __slots__ = ("request_id", "prompt", "token", "prefill_ready", "finished", "error", "usage") - REQUEST_ID_FIELD_NUMBER: _ClassVar[int] - PROMPT_FIELD_NUMBER: _ClassVar[int] - TOKEN_FIELD_NUMBER: _ClassVar[int] - PREFILL_READY_FIELD_NUMBER: _ClassVar[int] - FINISHED_FIELD_NUMBER: _ClassVar[int] - ERROR_FIELD_NUMBER: _ClassVar[int] - USAGE_FIELD_NUMBER: _ClassVar[int] - request_id: str - prompt: PromptOutput - token: TokenOutput - prefill_ready: PrefillReady - finished: GenerationFinished - error: _error_pb2.EngineError - usage: Usage - def __init__(self, request_id: _Optional[str] = ..., prompt: _Optional[_Union[PromptOutput, _Mapping]] = ..., token: _Optional[_Union[TokenOutput, _Mapping]] = ..., prefill_ready: _Optional[_Union[PrefillReady, _Mapping]] = ..., finished: _Optional[_Union[GenerationFinished, _Mapping]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ..., usage: _Optional[_Union[Usage, _Mapping]] = ...) -> None: ... - -class PromptOutput(_message.Message): - __slots__ = ("tokens",) - TOKENS_FIELD_NUMBER: _ClassVar[int] - tokens: _containers.RepeatedCompositeFieldContainer[TokenInfo] - def __init__(self, tokens: _Optional[_Iterable[_Union[TokenInfo, _Mapping]]] = ...) -> None: ... - -class TokenOutput(_message.Message): - __slots__ = ("output_index", "tokens", "text") - OUTPUT_INDEX_FIELD_NUMBER: _ClassVar[int] - TOKENS_FIELD_NUMBER: _ClassVar[int] - TEXT_FIELD_NUMBER: _ClassVar[int] - output_index: int - tokens: _containers.RepeatedCompositeFieldContainer[TokenInfo] - text: str - def __init__(self, output_index: _Optional[int] = ..., tokens: _Optional[_Iterable[_Union[TokenInfo, _Mapping]]] = ..., text: _Optional[str] = ...) -> None: ... - -class TokenInfo(_message.Message): - __slots__ = ("token_id", "token", "logprob", "rank", "candidates") - TOKEN_ID_FIELD_NUMBER: _ClassVar[int] - TOKEN_FIELD_NUMBER: _ClassVar[int] - LOGPROB_FIELD_NUMBER: _ClassVar[int] - RANK_FIELD_NUMBER: _ClassVar[int] - CANDIDATES_FIELD_NUMBER: _ClassVar[int] - token_id: int - token: str - logprob: float - rank: int - candidates: _containers.RepeatedCompositeFieldContainer[LogProb] - def __init__(self, token_id: _Optional[int] = ..., token: _Optional[str] = ..., logprob: _Optional[float] = ..., rank: _Optional[int] = ..., candidates: _Optional[_Iterable[_Union[LogProb, _Mapping]]] = ...) -> None: ... - -class LogProb(_message.Message): - __slots__ = ("token_id", "logprob", "token", "rank") - TOKEN_ID_FIELD_NUMBER: _ClassVar[int] - LOGPROB_FIELD_NUMBER: _ClassVar[int] - TOKEN_FIELD_NUMBER: _ClassVar[int] - RANK_FIELD_NUMBER: _ClassVar[int] - token_id: int - logprob: float - token: str - rank: int - def __init__(self, token_id: _Optional[int] = ..., logprob: _Optional[float] = ..., token: _Optional[str] = ..., rank: _Optional[int] = ...) -> None: ... - -class PrefillReady(_message.Message): - __slots__ = ("kv_session",) - KV_SESSION_FIELD_NUMBER: _ClassVar[int] - kv_session: _kv_pb2.KvSessionRef - def __init__(self, kv_session: _Optional[_Union[_kv_pb2.KvSessionRef, _Mapping]] = ...) -> None: ... - -class GenerationFinished(_message.Message): - __slots__ = ("output_index", "reason", "message", "stop_match") - OUTPUT_INDEX_FIELD_NUMBER: _ClassVar[int] - REASON_FIELD_NUMBER: _ClassVar[int] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - STOP_MATCH_FIELD_NUMBER: _ClassVar[int] - output_index: int - reason: FinishReason - message: str - stop_match: StopMatch - def __init__(self, output_index: _Optional[int] = ..., reason: _Optional[_Union[FinishReason, str]] = ..., message: _Optional[str] = ..., stop_match: _Optional[_Union[StopMatch, _Mapping]] = ...) -> None: ... - -class StopMatch(_message.Message): - __slots__ = ("stop_token_id", "stop_text", "eos_token_id") - STOP_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] - STOP_TEXT_FIELD_NUMBER: _ClassVar[int] - EOS_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] - stop_token_id: int - stop_text: str - eos_token_id: int - def __init__(self, stop_token_id: _Optional[int] = ..., stop_text: _Optional[str] = ..., eos_token_id: _Optional[int] = ...) -> None: ... - -class Usage(_message.Message): - __slots__ = ("prompt_tokens", "completion_tokens", "total_tokens", "cached_prompt_tokens", "reasoning_tokens") - PROMPT_TOKENS_FIELD_NUMBER: _ClassVar[int] - COMPLETION_TOKENS_FIELD_NUMBER: _ClassVar[int] - TOTAL_TOKENS_FIELD_NUMBER: _ClassVar[int] - CACHED_PROMPT_TOKENS_FIELD_NUMBER: _ClassVar[int] - REASONING_TOKENS_FIELD_NUMBER: _ClassVar[int] - prompt_tokens: int - completion_tokens: int - total_tokens: int - cached_prompt_tokens: int - reasoning_tokens: int - def __init__(self, prompt_tokens: _Optional[int] = ..., completion_tokens: _Optional[int] = ..., total_tokens: _Optional[int] = ..., cached_prompt_tokens: _Optional[int] = ..., reasoning_tokens: _Optional[int] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/kv_pb2.py b/packages/python/src/openengine/v1/kv_pb2.py deleted file mode 100644 index 7bab09d..0000000 --- a/packages/python/src/openengine/v1/kv_pb2.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/kv.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/kv.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16openengine/v1/kv.proto\x12\ropenengine.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x19openengine/v1/error.proto\"\xaf\x01\n\x0cKvSessionRef\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10transfer_backend\x18\x02 \x01(\t\x12,\n\tendpoints\x18\x03 \x03(\x0b\x32\x19.openengine.v1.KvEndpoint\x12\x0f\n\x07\x64p_rank\x18\x04 \x01(\r\x12\x32\n\x11\x61ttributes_struct\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\":\n\nKvEndpoint\x12\x0c\n\x04host\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x10\n\x08protocol\x18\x03 \x01(\t\"\x1b\n\x19GetKvConnectorInfoRequest\"\xbc\x03\n\x0fKvConnectorInfo\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x18\n\x10transfer_backend\x18\x02 \x01(\t\x12\x32\n\x0flocal_endpoints\x18\x03 \x03(\x0b\x32\x19.openengine.v1.KvEndpoint\x12\x1b\n\x13supported_protocols\x18\x04 \x03(\t\x12$\n\x17supports_remote_prefill\x18\x05 \x01(\x08H\x01\x88\x01\x01\x12!\n\x14supports_decode_pull\x18\x06 \x01(\x08H\x02\x88\x01\x01\x12#\n\x16supports_abort_cleanup\x18\x07 \x01(\x08H\x03\x88\x01\x01\x12\x1b\n\x0esupports_drain\x18\x08 \x01(\x08H\x04\x88\x01\x01\x12\x1b\n\x0eschema_version\x18\t \x01(\rH\x05\x88\x01\x01\x42\n\n\x08_enabledB\x1a\n\x18_supports_remote_prefillB\x17\n\x15_supports_decode_pullB\x19\n\x17_supports_abort_cleanupB\x11\n\x0f_supports_drainB\x11\n\x0f_schema_version\"7\n\x18GetKvEventSourcesRequest\x12\x1b\n\x13\x64\x61ta_parallel_ranks\x18\x01 \x03(\r\"J\n\x19GetKvEventSourcesResponse\x12-\n\x07sources\x18\x01 \x03(\x0b\x32\x1c.openengine.v1.KvEventSource\"\xec\x02\n\rKvEventSource\x12\x11\n\ttransport\x18\x01 \x01(\t\x12\x30\n\rendpoint_addr\x18\x02 \x01(\x0b\x32\x19.openengine.v1.KvEndpoint\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x17\n\x0freplay_endpoint\x18\x04 \x01(\t\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x05 \x01(\rH\x00\x88\x01\x01\x12\x10\n\x08\x65ncoding\x18\x06 \x01(\t\x12\x1b\n\x0eschema_version\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x19\n\x0c\x62uffer_steps\x18\x08 \x01(\rH\x02\x88\x01\x01\x12\x10\n\x03hwm\x18\t \x01(\rH\x03\x88\x01\x01\x12\x1b\n\x0emax_queue_size\x18\n \x01(\rH\x04\x88\x01\x01\x42\x15\n\x13_data_parallel_rankB\x11\n\x0f_schema_versionB\x0f\n\r_buffer_stepsB\x06\n\x04_hwmB\x11\n\x0f_max_queue_size\"p\n\x18SubscribeKvEventsRequest\x12\x1b\n\x13\x64\x61ta_parallel_ranks\x18\x01 \x03(\r\x12\x18\n\x10include_snapshot\x18\x02 \x01(\x08\x12\x1d\n\x15start_sequence_number\x18\x03 \x01(\x04\"\x7f\n\x19SubscribeKvEventsResponse\x12,\n\x05\x62\x61tch\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.KvEventBatchH\x00\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x42\x07\n\x05\x65vent\"\x89\x01\n\x0cKvEventBatch\x12\x17\n\x0fsequence_number\x18\x01 \x01(\x04\x12\x1c\n\x14timestamp_unix_nanos\x18\x02 \x01(\x04\x12\x1a\n\x12\x64\x61ta_parallel_rank\x18\x03 \x01(\r\x12&\n\x06\x65vents\x18\x04 \x03(\x0b\x32\x16.openengine.v1.KvEvent\"\x80\x02\n\x07KvEvent\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12/\n\nkv_session\x18\x02 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRef\x12\x32\n\x0c\x62lock_stored\x18\n \x01(\x0b\x32\x1a.openengine.v1.BlockStoredH\x00\x12\x34\n\rblock_removed\x18\x0b \x01(\x0b\x32\x1b.openengine.v1.BlockRemovedH\x00\x12=\n\x12\x61ll_blocks_cleared\x18\x0c \x01(\x0b\x32\x1f.openengine.v1.AllBlocksClearedH\x00\x42\x07\n\x05\x65vent\"\xf7\x02\n\x0b\x42lockStored\x12\x30\n\x0c\x62lock_hashes\x18\x01 \x03(\x0b\x32\x1a.openengine.v1.KvBlockHash\x12\x35\n\x11parent_block_hash\x18\x02 \x01(\x0b\x32\x1a.openengine.v1.KvBlockHash\x12\x11\n\ttoken_ids\x18\x03 \x03(\r\x12\x12\n\nblock_size\x18\x04 \x01(\r\x12\x0f\n\x07lora_id\x18\x05 \x01(\x03\x12\x11\n\tlora_name\x18\x06 \x01(\t\x12,\n\x06medium\x18\x07 \x01(\x0e\x32\x1c.openengine.v1.StorageMedium\x12\x31\n\nextra_keys\x18\x14 \x03(\x0b\x32\x1d.openengine.v1.OpaqueKeyTuple\x12\x11\n\tgroup_idx\x18\x15 \x01(\r\x12\x1a\n\x12kv_cache_spec_kind\x18\x16 \x01(\t\x12$\n\x1ckv_cache_spec_sliding_window\x18\x17 \x01(\r\"\x81\x01\n\x0c\x42lockRemoved\x12\x30\n\x0c\x62lock_hashes\x18\x01 \x03(\x0b\x32\x1a.openengine.v1.KvBlockHash\x12,\n\x06medium\x18\x02 \x01(\x0e\x32\x1c.openengine.v1.StorageMedium\x12\x11\n\tgroup_idx\x18\x03 \x01(\r\"\x12\n\x10\x41llBlocksCleared\".\n\x0bKvBlockHash\x12\r\n\x05value\x18\x01 \x01(\x0c\x12\x10\n\x08\x65ncoding\x18\x02 \x01(\t\" \n\x0eOpaqueKeyTuple\x12\x0e\n\x06values\x18\x01 \x03(\t*\x9c\x01\n\rStorageMedium\x12\x1e\n\x1aSTORAGE_MEDIUM_UNSPECIFIED\x10\x00\x12\x16\n\x12STORAGE_MEDIUM_GPU\x10\x01\x12\x1d\n\x19STORAGE_MEDIUM_CPU_PINNED\x10\x02\x12\x17\n\x13STORAGE_MEDIUM_DISK\x10\x03\x12\x1b\n\x17STORAGE_MEDIUM_EXTERNAL\x10\x04\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.kv_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_STORAGEMEDIUM']._serialized_start=2567 - _globals['_STORAGEMEDIUM']._serialized_end=2723 - _globals['_KVSESSIONREF']._serialized_start=99 - _globals['_KVSESSIONREF']._serialized_end=274 - _globals['_KVENDPOINT']._serialized_start=276 - _globals['_KVENDPOINT']._serialized_end=334 - _globals['_GETKVCONNECTORINFOREQUEST']._serialized_start=336 - _globals['_GETKVCONNECTORINFOREQUEST']._serialized_end=363 - _globals['_KVCONNECTORINFO']._serialized_start=366 - _globals['_KVCONNECTORINFO']._serialized_end=810 - _globals['_GETKVEVENTSOURCESREQUEST']._serialized_start=812 - _globals['_GETKVEVENTSOURCESREQUEST']._serialized_end=867 - _globals['_GETKVEVENTSOURCESRESPONSE']._serialized_start=869 - _globals['_GETKVEVENTSOURCESRESPONSE']._serialized_end=943 - _globals['_KVEVENTSOURCE']._serialized_start=946 - _globals['_KVEVENTSOURCE']._serialized_end=1310 - _globals['_SUBSCRIBEKVEVENTSREQUEST']._serialized_start=1312 - _globals['_SUBSCRIBEKVEVENTSREQUEST']._serialized_end=1424 - _globals['_SUBSCRIBEKVEVENTSRESPONSE']._serialized_start=1426 - _globals['_SUBSCRIBEKVEVENTSRESPONSE']._serialized_end=1553 - _globals['_KVEVENTBATCH']._serialized_start=1556 - _globals['_KVEVENTBATCH']._serialized_end=1693 - _globals['_KVEVENT']._serialized_start=1696 - _globals['_KVEVENT']._serialized_end=1952 - _globals['_BLOCKSTORED']._serialized_start=1955 - _globals['_BLOCKSTORED']._serialized_end=2330 - _globals['_BLOCKREMOVED']._serialized_start=2333 - _globals['_BLOCKREMOVED']._serialized_end=2462 - _globals['_ALLBLOCKSCLEARED']._serialized_start=2464 - _globals['_ALLBLOCKSCLEARED']._serialized_end=2482 - _globals['_KVBLOCKHASH']._serialized_start=2484 - _globals['_KVBLOCKHASH']._serialized_end=2530 - _globals['_OPAQUEKEYTUPLE']._serialized_start=2532 - _globals['_OPAQUEKEYTUPLE']._serialized_end=2564 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/kv_pb2.pyi b/packages/python/src/openengine/v1/kv_pb2.pyi deleted file mode 100644 index ee42789..0000000 --- a/packages/python/src/openengine/v1/kv_pb2.pyi +++ /dev/null @@ -1,207 +0,0 @@ -from google.protobuf import struct_pb2 as _struct_pb2 -from openengine.v1 import error_pb2 as _error_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class StorageMedium(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - STORAGE_MEDIUM_UNSPECIFIED: _ClassVar[StorageMedium] - STORAGE_MEDIUM_GPU: _ClassVar[StorageMedium] - STORAGE_MEDIUM_CPU_PINNED: _ClassVar[StorageMedium] - STORAGE_MEDIUM_DISK: _ClassVar[StorageMedium] - STORAGE_MEDIUM_EXTERNAL: _ClassVar[StorageMedium] -STORAGE_MEDIUM_UNSPECIFIED: StorageMedium -STORAGE_MEDIUM_GPU: StorageMedium -STORAGE_MEDIUM_CPU_PINNED: StorageMedium -STORAGE_MEDIUM_DISK: StorageMedium -STORAGE_MEDIUM_EXTERNAL: StorageMedium - -class KvSessionRef(_message.Message): - __slots__ = ("session_id", "transfer_backend", "endpoints", "dp_rank", "attributes_struct") - SESSION_ID_FIELD_NUMBER: _ClassVar[int] - TRANSFER_BACKEND_FIELD_NUMBER: _ClassVar[int] - ENDPOINTS_FIELD_NUMBER: _ClassVar[int] - DP_RANK_FIELD_NUMBER: _ClassVar[int] - ATTRIBUTES_STRUCT_FIELD_NUMBER: _ClassVar[int] - session_id: str - transfer_backend: str - endpoints: _containers.RepeatedCompositeFieldContainer[KvEndpoint] - dp_rank: int - attributes_struct: _struct_pb2.Struct - def __init__(self, session_id: _Optional[str] = ..., transfer_backend: _Optional[str] = ..., endpoints: _Optional[_Iterable[_Union[KvEndpoint, _Mapping]]] = ..., dp_rank: _Optional[int] = ..., attributes_struct: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... - -class KvEndpoint(_message.Message): - __slots__ = ("host", "port", "protocol") - HOST_FIELD_NUMBER: _ClassVar[int] - PORT_FIELD_NUMBER: _ClassVar[int] - PROTOCOL_FIELD_NUMBER: _ClassVar[int] - host: str - port: int - protocol: str - def __init__(self, host: _Optional[str] = ..., port: _Optional[int] = ..., protocol: _Optional[str] = ...) -> None: ... - -class GetKvConnectorInfoRequest(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class KvConnectorInfo(_message.Message): - __slots__ = ("enabled", "transfer_backend", "local_endpoints", "supported_protocols", "supports_remote_prefill", "supports_decode_pull", "supports_abort_cleanup", "supports_drain", "schema_version") - ENABLED_FIELD_NUMBER: _ClassVar[int] - TRANSFER_BACKEND_FIELD_NUMBER: _ClassVar[int] - LOCAL_ENDPOINTS_FIELD_NUMBER: _ClassVar[int] - SUPPORTED_PROTOCOLS_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_REMOTE_PREFILL_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_DECODE_PULL_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_ABORT_CLEANUP_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_DRAIN_FIELD_NUMBER: _ClassVar[int] - SCHEMA_VERSION_FIELD_NUMBER: _ClassVar[int] - enabled: bool - transfer_backend: str - local_endpoints: _containers.RepeatedCompositeFieldContainer[KvEndpoint] - supported_protocols: _containers.RepeatedScalarFieldContainer[str] - supports_remote_prefill: bool - supports_decode_pull: bool - supports_abort_cleanup: bool - supports_drain: bool - schema_version: int - def __init__(self, enabled: _Optional[bool] = ..., transfer_backend: _Optional[str] = ..., local_endpoints: _Optional[_Iterable[_Union[KvEndpoint, _Mapping]]] = ..., supported_protocols: _Optional[_Iterable[str]] = ..., supports_remote_prefill: _Optional[bool] = ..., supports_decode_pull: _Optional[bool] = ..., supports_abort_cleanup: _Optional[bool] = ..., supports_drain: _Optional[bool] = ..., schema_version: _Optional[int] = ...) -> None: ... - -class GetKvEventSourcesRequest(_message.Message): - __slots__ = ("data_parallel_ranks",) - DATA_PARALLEL_RANKS_FIELD_NUMBER: _ClassVar[int] - data_parallel_ranks: _containers.RepeatedScalarFieldContainer[int] - def __init__(self, data_parallel_ranks: _Optional[_Iterable[int]] = ...) -> None: ... - -class GetKvEventSourcesResponse(_message.Message): - __slots__ = ("sources",) - SOURCES_FIELD_NUMBER: _ClassVar[int] - sources: _containers.RepeatedCompositeFieldContainer[KvEventSource] - def __init__(self, sources: _Optional[_Iterable[_Union[KvEventSource, _Mapping]]] = ...) -> None: ... - -class KvEventSource(_message.Message): - __slots__ = ("transport", "endpoint_addr", "topic", "replay_endpoint", "data_parallel_rank", "encoding", "schema_version", "buffer_steps", "hwm", "max_queue_size") - TRANSPORT_FIELD_NUMBER: _ClassVar[int] - ENDPOINT_ADDR_FIELD_NUMBER: _ClassVar[int] - TOPIC_FIELD_NUMBER: _ClassVar[int] - REPLAY_ENDPOINT_FIELD_NUMBER: _ClassVar[int] - DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] - ENCODING_FIELD_NUMBER: _ClassVar[int] - SCHEMA_VERSION_FIELD_NUMBER: _ClassVar[int] - BUFFER_STEPS_FIELD_NUMBER: _ClassVar[int] - HWM_FIELD_NUMBER: _ClassVar[int] - MAX_QUEUE_SIZE_FIELD_NUMBER: _ClassVar[int] - transport: str - endpoint_addr: KvEndpoint - topic: str - replay_endpoint: str - data_parallel_rank: int - encoding: str - schema_version: int - buffer_steps: int - hwm: int - max_queue_size: int - def __init__(self, transport: _Optional[str] = ..., endpoint_addr: _Optional[_Union[KvEndpoint, _Mapping]] = ..., topic: _Optional[str] = ..., replay_endpoint: _Optional[str] = ..., data_parallel_rank: _Optional[int] = ..., encoding: _Optional[str] = ..., schema_version: _Optional[int] = ..., buffer_steps: _Optional[int] = ..., hwm: _Optional[int] = ..., max_queue_size: _Optional[int] = ...) -> None: ... - -class SubscribeKvEventsRequest(_message.Message): - __slots__ = ("data_parallel_ranks", "include_snapshot", "start_sequence_number") - DATA_PARALLEL_RANKS_FIELD_NUMBER: _ClassVar[int] - INCLUDE_SNAPSHOT_FIELD_NUMBER: _ClassVar[int] - START_SEQUENCE_NUMBER_FIELD_NUMBER: _ClassVar[int] - data_parallel_ranks: _containers.RepeatedScalarFieldContainer[int] - include_snapshot: bool - start_sequence_number: int - def __init__(self, data_parallel_ranks: _Optional[_Iterable[int]] = ..., include_snapshot: _Optional[bool] = ..., start_sequence_number: _Optional[int] = ...) -> None: ... - -class SubscribeKvEventsResponse(_message.Message): - __slots__ = ("batch", "error") - BATCH_FIELD_NUMBER: _ClassVar[int] - ERROR_FIELD_NUMBER: _ClassVar[int] - batch: KvEventBatch - error: _error_pb2.EngineError - def __init__(self, batch: _Optional[_Union[KvEventBatch, _Mapping]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ...) -> None: ... - -class KvEventBatch(_message.Message): - __slots__ = ("sequence_number", "timestamp_unix_nanos", "data_parallel_rank", "events") - SEQUENCE_NUMBER_FIELD_NUMBER: _ClassVar[int] - TIMESTAMP_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] - DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] - EVENTS_FIELD_NUMBER: _ClassVar[int] - sequence_number: int - timestamp_unix_nanos: int - data_parallel_rank: int - events: _containers.RepeatedCompositeFieldContainer[KvEvent] - def __init__(self, sequence_number: _Optional[int] = ..., timestamp_unix_nanos: _Optional[int] = ..., data_parallel_rank: _Optional[int] = ..., events: _Optional[_Iterable[_Union[KvEvent, _Mapping]]] = ...) -> None: ... - -class KvEvent(_message.Message): - __slots__ = ("request_id", "kv_session", "block_stored", "block_removed", "all_blocks_cleared") - REQUEST_ID_FIELD_NUMBER: _ClassVar[int] - KV_SESSION_FIELD_NUMBER: _ClassVar[int] - BLOCK_STORED_FIELD_NUMBER: _ClassVar[int] - BLOCK_REMOVED_FIELD_NUMBER: _ClassVar[int] - ALL_BLOCKS_CLEARED_FIELD_NUMBER: _ClassVar[int] - request_id: str - kv_session: KvSessionRef - block_stored: BlockStored - block_removed: BlockRemoved - all_blocks_cleared: AllBlocksCleared - def __init__(self, request_id: _Optional[str] = ..., kv_session: _Optional[_Union[KvSessionRef, _Mapping]] = ..., block_stored: _Optional[_Union[BlockStored, _Mapping]] = ..., block_removed: _Optional[_Union[BlockRemoved, _Mapping]] = ..., all_blocks_cleared: _Optional[_Union[AllBlocksCleared, _Mapping]] = ...) -> None: ... - -class BlockStored(_message.Message): - __slots__ = ("block_hashes", "parent_block_hash", "token_ids", "block_size", "lora_id", "lora_name", "medium", "extra_keys", "group_idx", "kv_cache_spec_kind", "kv_cache_spec_sliding_window") - BLOCK_HASHES_FIELD_NUMBER: _ClassVar[int] - PARENT_BLOCK_HASH_FIELD_NUMBER: _ClassVar[int] - TOKEN_IDS_FIELD_NUMBER: _ClassVar[int] - BLOCK_SIZE_FIELD_NUMBER: _ClassVar[int] - LORA_ID_FIELD_NUMBER: _ClassVar[int] - LORA_NAME_FIELD_NUMBER: _ClassVar[int] - MEDIUM_FIELD_NUMBER: _ClassVar[int] - EXTRA_KEYS_FIELD_NUMBER: _ClassVar[int] - GROUP_IDX_FIELD_NUMBER: _ClassVar[int] - KV_CACHE_SPEC_KIND_FIELD_NUMBER: _ClassVar[int] - KV_CACHE_SPEC_SLIDING_WINDOW_FIELD_NUMBER: _ClassVar[int] - block_hashes: _containers.RepeatedCompositeFieldContainer[KvBlockHash] - parent_block_hash: KvBlockHash - token_ids: _containers.RepeatedScalarFieldContainer[int] - block_size: int - lora_id: int - lora_name: str - medium: StorageMedium - extra_keys: _containers.RepeatedCompositeFieldContainer[OpaqueKeyTuple] - group_idx: int - kv_cache_spec_kind: str - kv_cache_spec_sliding_window: int - def __init__(self, block_hashes: _Optional[_Iterable[_Union[KvBlockHash, _Mapping]]] = ..., parent_block_hash: _Optional[_Union[KvBlockHash, _Mapping]] = ..., token_ids: _Optional[_Iterable[int]] = ..., block_size: _Optional[int] = ..., lora_id: _Optional[int] = ..., lora_name: _Optional[str] = ..., medium: _Optional[_Union[StorageMedium, str]] = ..., extra_keys: _Optional[_Iterable[_Union[OpaqueKeyTuple, _Mapping]]] = ..., group_idx: _Optional[int] = ..., kv_cache_spec_kind: _Optional[str] = ..., kv_cache_spec_sliding_window: _Optional[int] = ...) -> None: ... - -class BlockRemoved(_message.Message): - __slots__ = ("block_hashes", "medium", "group_idx") - BLOCK_HASHES_FIELD_NUMBER: _ClassVar[int] - MEDIUM_FIELD_NUMBER: _ClassVar[int] - GROUP_IDX_FIELD_NUMBER: _ClassVar[int] - block_hashes: _containers.RepeatedCompositeFieldContainer[KvBlockHash] - medium: StorageMedium - group_idx: int - def __init__(self, block_hashes: _Optional[_Iterable[_Union[KvBlockHash, _Mapping]]] = ..., medium: _Optional[_Union[StorageMedium, str]] = ..., group_idx: _Optional[int] = ...) -> None: ... - -class AllBlocksCleared(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class KvBlockHash(_message.Message): - __slots__ = ("value", "encoding") - VALUE_FIELD_NUMBER: _ClassVar[int] - ENCODING_FIELD_NUMBER: _ClassVar[int] - value: bytes - encoding: str - def __init__(self, value: _Optional[bytes] = ..., encoding: _Optional[str] = ...) -> None: ... - -class OpaqueKeyTuple(_message.Message): - __slots__ = ("values",) - VALUES_FIELD_NUMBER: _ClassVar[int] - values: _containers.RepeatedScalarFieldContainer[str] - def __init__(self, values: _Optional[_Iterable[str]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/lifecycle_pb2.py b/packages/python/src/openengine/v1/lifecycle_pb2.py deleted file mode 100644 index 69a44ca..0000000 --- a/packages/python/src/openengine/v1/lifecycle_pb2.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/lifecycle.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/lifecycle.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from openengine.v1 import engine_pb2 as openengine_dot_v1_dot_engine__pb2 -from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 -from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dopenengine/v1/lifecycle.proto\x12\ropenengine.v1\x1a\x1aopenengine/v1/engine.proto\x1a\x19openengine/v1/error.proto\x1a\x16openengine/v1/kv.proto\"h\n\rHealthRequest\x12\x1f\n\x17include_inference_probe\x18\x01 \x01(\x08\x12\r\n\x05model\x18\x02 \x01(\t\x12\'\n\x04role\x18\x03 \x01(\x0e\x32\x19.openengine.v1.EngineRole\"g\n\x0eHealthResponse\x12)\n\x05state\x18\x01 \x01(\x0e\x32\x1a.openengine.v1.HealthState\x12*\n\x06\x63hecks\x18\x02 \x03(\x0b\x32\x1a.openengine.v1.HealthCheck\"W\n\x0bHealthCheck\x12\x0c\n\x04name\x18\x01 \x01(\t\x12)\n\x05state\x18\x02 \x01(\x0e\x32\x1a.openengine.v1.HealthState\x12\x0f\n\x07message\x18\x03 \x01(\t\"\x95\x01\n\x0c\x41\x62ortRequest\x12\x14\n\nrequest_id\x18\x01 \x01(\tH\x00\x12\x31\n\nkv_session\x18\x02 \x01(\x0b\x32\x1b.openengine.v1.KvSessionRefH\x00\x12\x32\n\x0c\x61ll_requests\x18\x03 \x01(\x0b\x32\x1a.openengine.v1.AllRequestsH\x00\x42\x08\n\x06target\"\r\n\x0b\x41llRequests\"L\n\rAbortResponse\x12*\n\x06status\x18\x01 \x01(\x0e\x32\x1a.openengine.v1.AbortStatus\x12\x0f\n\x07message\x18\x02 \x01(\t\"{\n\x0c\x44rainRequest\x12#\n\x1bstop_accepting_new_requests\x18\x01 \x01(\x08\x12\x18\n\x0b\x64\x65\x61\x64line_ms\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x14\x61\x62ort_after_deadline\x18\x03 \x01(\x08\x42\x0e\n\x0c_deadline_ms\"\xee\x01\n\rDrainResponse\x12*\n\x05state\x18\x01 \x01(\x0e\x32\x19.openengine.v1.DrainStateH\x00\x12+\n\x05\x65rror\x18\x05 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x12\x1f\n\x12in_flight_requests\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1d\n\x10open_kv_sessions\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x0f\n\x07message\x18\x04 \x01(\tB\x07\n\x05\x65ventB\x15\n\x13_in_flight_requestsB\x13\n\x11_open_kv_sessions*\xb0\x01\n\x0bHealthState\x12\x1c\n\x18HEALTH_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15HEALTH_STATE_STARTING\x10\x01\x12\x16\n\x12HEALTH_STATE_READY\x10\x02\x12\x19\n\x15HEALTH_STATE_DEGRADED\x10\x03\x12\x19\n\x15HEALTH_STATE_DRAINING\x10\x04\x12\x1a\n\x16HEALTH_STATE_NOT_READY\x10\x05*h\n\x0b\x41\x62ortStatus\x12\x1c\n\x18\x41\x42ORT_STATUS_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41\x42ORT_STATUS_ABORTED\x10\x01\x12!\n\x1d\x41\x42ORT_STATUS_ALREADY_FINISHED\x10\x02*y\n\nDrainState\x12\x1b\n\x17\x44RAIN_STATE_UNSPECIFIED\x10\x00\x12\x17\n\x13\x44RAIN_STATE_STARTED\x10\x01\x12\x1b\n\x17\x44RAIN_STATE_IN_PROGRESS\x10\x02\x12\x18\n\x14\x44RAIN_STATE_COMPLETE\x10\x03\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.lifecycle_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_HEALTHSTATE']._serialized_start=1039 - _globals['_HEALTHSTATE']._serialized_end=1215 - _globals['_ABORTSTATUS']._serialized_start=1217 - _globals['_ABORTSTATUS']._serialized_end=1321 - _globals['_DRAINSTATE']._serialized_start=1323 - _globals['_DRAINSTATE']._serialized_end=1444 - _globals['_HEALTHREQUEST']._serialized_start=127 - _globals['_HEALTHREQUEST']._serialized_end=231 - _globals['_HEALTHRESPONSE']._serialized_start=233 - _globals['_HEALTHRESPONSE']._serialized_end=336 - _globals['_HEALTHCHECK']._serialized_start=338 - _globals['_HEALTHCHECK']._serialized_end=425 - _globals['_ABORTREQUEST']._serialized_start=428 - _globals['_ABORTREQUEST']._serialized_end=577 - _globals['_ALLREQUESTS']._serialized_start=579 - _globals['_ALLREQUESTS']._serialized_end=592 - _globals['_ABORTRESPONSE']._serialized_start=594 - _globals['_ABORTRESPONSE']._serialized_end=670 - _globals['_DRAINREQUEST']._serialized_start=672 - _globals['_DRAINREQUEST']._serialized_end=795 - _globals['_DRAINRESPONSE']._serialized_start=798 - _globals['_DRAINRESPONSE']._serialized_end=1036 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/lifecycle_pb2.pyi b/packages/python/src/openengine/v1/lifecycle_pb2.pyi deleted file mode 100644 index 329d52d..0000000 --- a/packages/python/src/openengine/v1/lifecycle_pb2.pyi +++ /dev/null @@ -1,120 +0,0 @@ -from openengine.v1 import engine_pb2 as _engine_pb2 -from openengine.v1 import error_pb2 as _error_pb2 -from openengine.v1 import kv_pb2 as _kv_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class HealthState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - HEALTH_STATE_UNSPECIFIED: _ClassVar[HealthState] - HEALTH_STATE_STARTING: _ClassVar[HealthState] - HEALTH_STATE_READY: _ClassVar[HealthState] - HEALTH_STATE_DEGRADED: _ClassVar[HealthState] - HEALTH_STATE_DRAINING: _ClassVar[HealthState] - HEALTH_STATE_NOT_READY: _ClassVar[HealthState] - -class AbortStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - ABORT_STATUS_UNSPECIFIED: _ClassVar[AbortStatus] - ABORT_STATUS_ABORTED: _ClassVar[AbortStatus] - ABORT_STATUS_ALREADY_FINISHED: _ClassVar[AbortStatus] - -class DrainState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - DRAIN_STATE_UNSPECIFIED: _ClassVar[DrainState] - DRAIN_STATE_STARTED: _ClassVar[DrainState] - DRAIN_STATE_IN_PROGRESS: _ClassVar[DrainState] - DRAIN_STATE_COMPLETE: _ClassVar[DrainState] -HEALTH_STATE_UNSPECIFIED: HealthState -HEALTH_STATE_STARTING: HealthState -HEALTH_STATE_READY: HealthState -HEALTH_STATE_DEGRADED: HealthState -HEALTH_STATE_DRAINING: HealthState -HEALTH_STATE_NOT_READY: HealthState -ABORT_STATUS_UNSPECIFIED: AbortStatus -ABORT_STATUS_ABORTED: AbortStatus -ABORT_STATUS_ALREADY_FINISHED: AbortStatus -DRAIN_STATE_UNSPECIFIED: DrainState -DRAIN_STATE_STARTED: DrainState -DRAIN_STATE_IN_PROGRESS: DrainState -DRAIN_STATE_COMPLETE: DrainState - -class HealthRequest(_message.Message): - __slots__ = ("include_inference_probe", "model", "role") - INCLUDE_INFERENCE_PROBE_FIELD_NUMBER: _ClassVar[int] - MODEL_FIELD_NUMBER: _ClassVar[int] - ROLE_FIELD_NUMBER: _ClassVar[int] - include_inference_probe: bool - model: str - role: _engine_pb2.EngineRole - def __init__(self, include_inference_probe: _Optional[bool] = ..., model: _Optional[str] = ..., role: _Optional[_Union[_engine_pb2.EngineRole, str]] = ...) -> None: ... - -class HealthResponse(_message.Message): - __slots__ = ("state", "checks") - STATE_FIELD_NUMBER: _ClassVar[int] - CHECKS_FIELD_NUMBER: _ClassVar[int] - state: HealthState - checks: _containers.RepeatedCompositeFieldContainer[HealthCheck] - def __init__(self, state: _Optional[_Union[HealthState, str]] = ..., checks: _Optional[_Iterable[_Union[HealthCheck, _Mapping]]] = ...) -> None: ... - -class HealthCheck(_message.Message): - __slots__ = ("name", "state", "message") - NAME_FIELD_NUMBER: _ClassVar[int] - STATE_FIELD_NUMBER: _ClassVar[int] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - name: str - state: HealthState - message: str - def __init__(self, name: _Optional[str] = ..., state: _Optional[_Union[HealthState, str]] = ..., message: _Optional[str] = ...) -> None: ... - -class AbortRequest(_message.Message): - __slots__ = ("request_id", "kv_session", "all_requests") - REQUEST_ID_FIELD_NUMBER: _ClassVar[int] - KV_SESSION_FIELD_NUMBER: _ClassVar[int] - ALL_REQUESTS_FIELD_NUMBER: _ClassVar[int] - request_id: str - kv_session: _kv_pb2.KvSessionRef - all_requests: AllRequests - def __init__(self, request_id: _Optional[str] = ..., kv_session: _Optional[_Union[_kv_pb2.KvSessionRef, _Mapping]] = ..., all_requests: _Optional[_Union[AllRequests, _Mapping]] = ...) -> None: ... - -class AllRequests(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class AbortResponse(_message.Message): - __slots__ = ("status", "message") - STATUS_FIELD_NUMBER: _ClassVar[int] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - status: AbortStatus - message: str - def __init__(self, status: _Optional[_Union[AbortStatus, str]] = ..., message: _Optional[str] = ...) -> None: ... - -class DrainRequest(_message.Message): - __slots__ = ("stop_accepting_new_requests", "deadline_ms", "abort_after_deadline") - STOP_ACCEPTING_NEW_REQUESTS_FIELD_NUMBER: _ClassVar[int] - DEADLINE_MS_FIELD_NUMBER: _ClassVar[int] - ABORT_AFTER_DEADLINE_FIELD_NUMBER: _ClassVar[int] - stop_accepting_new_requests: bool - deadline_ms: int - abort_after_deadline: bool - def __init__(self, stop_accepting_new_requests: _Optional[bool] = ..., deadline_ms: _Optional[int] = ..., abort_after_deadline: _Optional[bool] = ...) -> None: ... - -class DrainResponse(_message.Message): - __slots__ = ("state", "error", "in_flight_requests", "open_kv_sessions", "message") - STATE_FIELD_NUMBER: _ClassVar[int] - ERROR_FIELD_NUMBER: _ClassVar[int] - IN_FLIGHT_REQUESTS_FIELD_NUMBER: _ClassVar[int] - OPEN_KV_SESSIONS_FIELD_NUMBER: _ClassVar[int] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - state: DrainState - error: _error_pb2.EngineError - in_flight_requests: int - open_kv_sessions: int - message: str - def __init__(self, state: _Optional[_Union[DrainState, str]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ..., in_flight_requests: _Optional[int] = ..., open_kv_sessions: _Optional[int] = ..., message: _Optional[str] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/lora_pb2.py b/packages/python/src/openengine/v1/lora_pb2.py deleted file mode 100644 index a53d2a8..0000000 --- a/packages/python/src/openengine/v1/lora_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/lora.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/lora.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18openengine/v1/lora.proto\x12\ropenengine.v1\"F\n\x0bLoraAdapter\x12\x0f\n\x07lora_id\x18\x01 \x01(\x03\x12\x11\n\tlora_name\x18\x02 \x01(\t\x12\x13\n\x0bsource_path\x18\x03 \x01(\t\">\n\x0fLoadLoraRequest\x12+\n\x07\x61\x64\x61pter\x18\x01 \x01(\x0b\x32\x1a.openengine.v1.LoraAdapter\"W\n\x10LoadLoraResponse\x12+\n\x07\x61\x64\x61pter\x18\x01 \x01(\x0b\x32\x1a.openengine.v1.LoraAdapter\x12\x16\n\x0e\x61lready_loaded\x18\x02 \x01(\x08\"&\n\x11UnloadLoraRequest\x12\x11\n\tlora_name\x18\x01 \x01(\t\"A\n\x12UnloadLoraResponse\x12+\n\x07\x61\x64\x61pter\x18\x01 \x01(\x0b\x32\x1a.openengine.v1.LoraAdapter\"\x12\n\x10ListLorasRequest\"A\n\x11ListLorasResponse\x12,\n\x08\x61\x64\x61pters\x18\x01 \x03(\x0b\x32\x1a.openengine.v1.LoraAdapterb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.lora_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_LORAADAPTER']._serialized_start=43 - _globals['_LORAADAPTER']._serialized_end=113 - _globals['_LOADLORAREQUEST']._serialized_start=115 - _globals['_LOADLORAREQUEST']._serialized_end=177 - _globals['_LOADLORARESPONSE']._serialized_start=179 - _globals['_LOADLORARESPONSE']._serialized_end=266 - _globals['_UNLOADLORAREQUEST']._serialized_start=268 - _globals['_UNLOADLORAREQUEST']._serialized_end=306 - _globals['_UNLOADLORARESPONSE']._serialized_start=308 - _globals['_UNLOADLORARESPONSE']._serialized_end=373 - _globals['_LISTLORASREQUEST']._serialized_start=375 - _globals['_LISTLORASREQUEST']._serialized_end=393 - _globals['_LISTLORASRESPONSE']._serialized_start=395 - _globals['_LISTLORASRESPONSE']._serialized_end=460 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/lora_pb2.pyi b/packages/python/src/openengine/v1/lora_pb2.pyi deleted file mode 100644 index e5a6064..0000000 --- a/packages/python/src/openengine/v1/lora_pb2.pyi +++ /dev/null @@ -1,53 +0,0 @@ -from google.protobuf.internal import containers as _containers -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class LoraAdapter(_message.Message): - __slots__ = ("lora_id", "lora_name", "source_path") - LORA_ID_FIELD_NUMBER: _ClassVar[int] - LORA_NAME_FIELD_NUMBER: _ClassVar[int] - SOURCE_PATH_FIELD_NUMBER: _ClassVar[int] - lora_id: int - lora_name: str - source_path: str - def __init__(self, lora_id: _Optional[int] = ..., lora_name: _Optional[str] = ..., source_path: _Optional[str] = ...) -> None: ... - -class LoadLoraRequest(_message.Message): - __slots__ = ("adapter",) - ADAPTER_FIELD_NUMBER: _ClassVar[int] - adapter: LoraAdapter - def __init__(self, adapter: _Optional[_Union[LoraAdapter, _Mapping]] = ...) -> None: ... - -class LoadLoraResponse(_message.Message): - __slots__ = ("adapter", "already_loaded") - ADAPTER_FIELD_NUMBER: _ClassVar[int] - ALREADY_LOADED_FIELD_NUMBER: _ClassVar[int] - adapter: LoraAdapter - already_loaded: bool - def __init__(self, adapter: _Optional[_Union[LoraAdapter, _Mapping]] = ..., already_loaded: _Optional[bool] = ...) -> None: ... - -class UnloadLoraRequest(_message.Message): - __slots__ = ("lora_name",) - LORA_NAME_FIELD_NUMBER: _ClassVar[int] - lora_name: str - def __init__(self, lora_name: _Optional[str] = ...) -> None: ... - -class UnloadLoraResponse(_message.Message): - __slots__ = ("adapter",) - ADAPTER_FIELD_NUMBER: _ClassVar[int] - adapter: LoraAdapter - def __init__(self, adapter: _Optional[_Union[LoraAdapter, _Mapping]] = ...) -> None: ... - -class ListLorasRequest(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class ListLorasResponse(_message.Message): - __slots__ = ("adapters",) - ADAPTERS_FIELD_NUMBER: _ClassVar[int] - adapters: _containers.RepeatedCompositeFieldContainer[LoraAdapter] - def __init__(self, adapters: _Optional[_Iterable[_Union[LoraAdapter, _Mapping]]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/model_pb2.py b/packages/python/src/openengine/v1/model_pb2.py deleted file mode 100644 index dab46f0..0000000 --- a/packages/python/src/openengine/v1/model_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/model.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/model.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19openengine/v1/model.proto\x12\ropenengine.v1\"$\n\x13GetModelInfoRequest\x12\r\n\x05model\x18\x01 \x01(\t\"\x86\x06\n\tModelInfo\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12\x19\n\x11served_model_name\x18\x02 \x01(\t\x12\x1c\n\x14served_model_aliases\x18\x03 \x03(\t\x12\x1f\n\x12max_context_length\x18\x04 \x01(\rH\x00\x88\x01\x01\x12\x1e\n\x11max_output_tokens\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\x1a\n\rkv_block_size\x18\x06 \x01(\rH\x02\x88\x01\x01\x12\x1c\n\x0ftotal_kv_blocks\x18\x07 \x01(\x04H\x03\x88\x01\x01\x12!\n\x14max_running_requests\x18\x08 \x01(\x04H\x04\x88\x01\x01\x12\x1f\n\x12max_batched_tokens\x18\t \x01(\x04H\x05\x88\x01\x01\x12\x17\n\x0ftokenizer_modes\x18\n \x03(\t\x12 \n\x13supports_text_input\x18\x14 \x01(\x08H\x06\x88\x01\x01\x12%\n\x18supports_token_ids_input\x18\x15 \x01(\x08H\x07\x88\x01\x01\x12\x39\n\ngeneration\x18\x16 \x01(\x0b\x32%.openengine.v1.GenerationCapabilities\x12\x1a\n\rsupports_lora\x18\x17 \x01(\x08H\x08\x88\x01\x01\x12 \n\x13supports_multimodal\x18\x18 \x01(\x08H\t\x88\x01\x01\x12\x18\n\x10reasoning_parser\x18\x19 \x01(\t\x12\x18\n\x10tool_call_parser\x18\x1a \x01(\tB\x15\n\x13_max_context_lengthB\x14\n\x12_max_output_tokensB\x10\n\x0e_kv_block_sizeB\x12\n\x10_total_kv_blocksB\x17\n\x15_max_running_requestsB\x15\n\x13_max_batched_tokensB\x16\n\x14_supports_text_inputB\x1b\n\x19_supports_token_ids_inputB\x10\n\x0e_supports_loraB\x16\n\x14_supports_multimodal\"\x8a\x04\n\x16GenerationCapabilities\x12;\n\x0fprompt_logprobs\x18\x01 \x01(\x0b\x32\".openengine.v1.LogprobCapabilities\x12;\n\x0foutput_logprobs\x18\x02 \x01(\x0b\x32\".openengine.v1.LogprobCapabilities\x12\x42\n\x0fguided_decoding\x18\x03 \x01(\x0b\x32).openengine.v1.GuidedDecodingCapabilities\x12\x1e\n\x11max_num_sequences\x18\x04 \x01(\rH\x00\x88\x01\x01\x12\x1e\n\x11supports_priority\x18\x05 \x01(\x08H\x01\x88\x01\x01\x12$\n\x17supports_stop_in_output\x18\x06 \x01(\x08H\x02\x88\x01\x01\x12 \n\x13supports_cache_salt\x18\x07 \x01(\x08H\x03\x88\x01\x01\x12)\n\x1csupports_prefix_cache_bypass\x18\x08 \x01(\x08H\x04\x88\x01\x01\x42\x14\n\x12_max_num_sequencesB\x14\n\x12_supports_priorityB\x1a\n\x18_supports_stop_in_outputB\x16\n\x14_supports_cache_saltB\x1f\n\x1d_supports_prefix_cache_bypass\"\xb0\x01\n\x13LogprobCapabilities\x12\x16\n\tsupported\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12M\n\x19\x63\x61ndidate_selection_modes\x18\x02 \x03(\x0e\x32*.openengine.v1.CandidateTokenSelectionMode\x12\x16\n\tmax_top_n\x18\x03 \x01(\rH\x01\x88\x01\x01\x42\x0c\n\n_supportedB\x0c\n\n_max_top_n\"t\n\x1aGuidedDecodingCapabilities\x12\x16\n\tsupported\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x30\n\x05modes\x18\x02 \x03(\x0e\x32!.openengine.v1.GuidedDecodingModeB\x0c\n\n_supported*\xcd\x01\n\x1b\x43\x61ndidateTokenSelectionMode\x12.\n*CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED\x10\x00\x12(\n$CANDIDATE_TOKEN_SELECTION_MODE_TOP_N\x10\x01\x12,\n(CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS\x10\x02\x12&\n\"CANDIDATE_TOKEN_SELECTION_MODE_ALL\x10\x03*\x97\x02\n\x12GuidedDecodingMode\x12$\n GUIDED_DECODING_MODE_UNSPECIFIED\x10\x00\x12$\n GUIDED_DECODING_MODE_JSON_SCHEMA\x10\x01\x12\x1e\n\x1aGUIDED_DECODING_MODE_REGEX\x10\x02\x12%\n!GUIDED_DECODING_MODE_EBNF_GRAMMAR\x10\x03\x12\'\n#GUIDED_DECODING_MODE_STRUCTURAL_TAG\x10\x04\x12\x1f\n\x1bGUIDED_DECODING_MODE_CHOICE\x10\x05\x12$\n GUIDED_DECODING_MODE_JSON_OBJECT\x10\x06\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.model_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_CANDIDATETOKENSELECTIONMODE']._serialized_start=1682 - _globals['_CANDIDATETOKENSELECTIONMODE']._serialized_end=1887 - _globals['_GUIDEDDECODINGMODE']._serialized_start=1890 - _globals['_GUIDEDDECODINGMODE']._serialized_end=2169 - _globals['_GETMODELINFOREQUEST']._serialized_start=44 - _globals['_GETMODELINFOREQUEST']._serialized_end=80 - _globals['_MODELINFO']._serialized_start=83 - _globals['_MODELINFO']._serialized_end=857 - _globals['_GENERATIONCAPABILITIES']._serialized_start=860 - _globals['_GENERATIONCAPABILITIES']._serialized_end=1382 - _globals['_LOGPROBCAPABILITIES']._serialized_start=1385 - _globals['_LOGPROBCAPABILITIES']._serialized_end=1561 - _globals['_GUIDEDDECODINGCAPABILITIES']._serialized_start=1563 - _globals['_GUIDEDDECODINGCAPABILITIES']._serialized_end=1679 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/model_pb2.pyi b/packages/python/src/openengine/v1/model_pb2.pyi deleted file mode 100644 index 27779fc..0000000 --- a/packages/python/src/openengine/v1/model_pb2.pyi +++ /dev/null @@ -1,118 +0,0 @@ -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class CandidateTokenSelectionMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED: _ClassVar[CandidateTokenSelectionMode] - CANDIDATE_TOKEN_SELECTION_MODE_TOP_N: _ClassVar[CandidateTokenSelectionMode] - CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS: _ClassVar[CandidateTokenSelectionMode] - CANDIDATE_TOKEN_SELECTION_MODE_ALL: _ClassVar[CandidateTokenSelectionMode] - -class GuidedDecodingMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - GUIDED_DECODING_MODE_UNSPECIFIED: _ClassVar[GuidedDecodingMode] - GUIDED_DECODING_MODE_JSON_SCHEMA: _ClassVar[GuidedDecodingMode] - GUIDED_DECODING_MODE_REGEX: _ClassVar[GuidedDecodingMode] - GUIDED_DECODING_MODE_EBNF_GRAMMAR: _ClassVar[GuidedDecodingMode] - GUIDED_DECODING_MODE_STRUCTURAL_TAG: _ClassVar[GuidedDecodingMode] - GUIDED_DECODING_MODE_CHOICE: _ClassVar[GuidedDecodingMode] - GUIDED_DECODING_MODE_JSON_OBJECT: _ClassVar[GuidedDecodingMode] -CANDIDATE_TOKEN_SELECTION_MODE_UNSPECIFIED: CandidateTokenSelectionMode -CANDIDATE_TOKEN_SELECTION_MODE_TOP_N: CandidateTokenSelectionMode -CANDIDATE_TOKEN_SELECTION_MODE_TOKEN_IDS: CandidateTokenSelectionMode -CANDIDATE_TOKEN_SELECTION_MODE_ALL: CandidateTokenSelectionMode -GUIDED_DECODING_MODE_UNSPECIFIED: GuidedDecodingMode -GUIDED_DECODING_MODE_JSON_SCHEMA: GuidedDecodingMode -GUIDED_DECODING_MODE_REGEX: GuidedDecodingMode -GUIDED_DECODING_MODE_EBNF_GRAMMAR: GuidedDecodingMode -GUIDED_DECODING_MODE_STRUCTURAL_TAG: GuidedDecodingMode -GUIDED_DECODING_MODE_CHOICE: GuidedDecodingMode -GUIDED_DECODING_MODE_JSON_OBJECT: GuidedDecodingMode - -class GetModelInfoRequest(_message.Message): - __slots__ = ("model",) - MODEL_FIELD_NUMBER: _ClassVar[int] - model: str - def __init__(self, model: _Optional[str] = ...) -> None: ... - -class ModelInfo(_message.Message): - __slots__ = ("model_id", "served_model_name", "served_model_aliases", "max_context_length", "max_output_tokens", "kv_block_size", "total_kv_blocks", "max_running_requests", "max_batched_tokens", "tokenizer_modes", "supports_text_input", "supports_token_ids_input", "generation", "supports_lora", "supports_multimodal", "reasoning_parser", "tool_call_parser") - MODEL_ID_FIELD_NUMBER: _ClassVar[int] - SERVED_MODEL_NAME_FIELD_NUMBER: _ClassVar[int] - SERVED_MODEL_ALIASES_FIELD_NUMBER: _ClassVar[int] - MAX_CONTEXT_LENGTH_FIELD_NUMBER: _ClassVar[int] - MAX_OUTPUT_TOKENS_FIELD_NUMBER: _ClassVar[int] - KV_BLOCK_SIZE_FIELD_NUMBER: _ClassVar[int] - TOTAL_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] - MAX_RUNNING_REQUESTS_FIELD_NUMBER: _ClassVar[int] - MAX_BATCHED_TOKENS_FIELD_NUMBER: _ClassVar[int] - TOKENIZER_MODES_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_TEXT_INPUT_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_TOKEN_IDS_INPUT_FIELD_NUMBER: _ClassVar[int] - GENERATION_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_LORA_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_MULTIMODAL_FIELD_NUMBER: _ClassVar[int] - REASONING_PARSER_FIELD_NUMBER: _ClassVar[int] - TOOL_CALL_PARSER_FIELD_NUMBER: _ClassVar[int] - model_id: str - served_model_name: str - served_model_aliases: _containers.RepeatedScalarFieldContainer[str] - max_context_length: int - max_output_tokens: int - kv_block_size: int - total_kv_blocks: int - max_running_requests: int - max_batched_tokens: int - tokenizer_modes: _containers.RepeatedScalarFieldContainer[str] - supports_text_input: bool - supports_token_ids_input: bool - generation: GenerationCapabilities - supports_lora: bool - supports_multimodal: bool - reasoning_parser: str - tool_call_parser: str - def __init__(self, model_id: _Optional[str] = ..., served_model_name: _Optional[str] = ..., served_model_aliases: _Optional[_Iterable[str]] = ..., max_context_length: _Optional[int] = ..., max_output_tokens: _Optional[int] = ..., kv_block_size: _Optional[int] = ..., total_kv_blocks: _Optional[int] = ..., max_running_requests: _Optional[int] = ..., max_batched_tokens: _Optional[int] = ..., tokenizer_modes: _Optional[_Iterable[str]] = ..., supports_text_input: _Optional[bool] = ..., supports_token_ids_input: _Optional[bool] = ..., generation: _Optional[_Union[GenerationCapabilities, _Mapping]] = ..., supports_lora: _Optional[bool] = ..., supports_multimodal: _Optional[bool] = ..., reasoning_parser: _Optional[str] = ..., tool_call_parser: _Optional[str] = ...) -> None: ... - -class GenerationCapabilities(_message.Message): - __slots__ = ("prompt_logprobs", "output_logprobs", "guided_decoding", "max_num_sequences", "supports_priority", "supports_stop_in_output", "supports_cache_salt", "supports_prefix_cache_bypass") - PROMPT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] - OUTPUT_LOGPROBS_FIELD_NUMBER: _ClassVar[int] - GUIDED_DECODING_FIELD_NUMBER: _ClassVar[int] - MAX_NUM_SEQUENCES_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_PRIORITY_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_STOP_IN_OUTPUT_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_CACHE_SALT_FIELD_NUMBER: _ClassVar[int] - SUPPORTS_PREFIX_CACHE_BYPASS_FIELD_NUMBER: _ClassVar[int] - prompt_logprobs: LogprobCapabilities - output_logprobs: LogprobCapabilities - guided_decoding: GuidedDecodingCapabilities - max_num_sequences: int - supports_priority: bool - supports_stop_in_output: bool - supports_cache_salt: bool - supports_prefix_cache_bypass: bool - def __init__(self, prompt_logprobs: _Optional[_Union[LogprobCapabilities, _Mapping]] = ..., output_logprobs: _Optional[_Union[LogprobCapabilities, _Mapping]] = ..., guided_decoding: _Optional[_Union[GuidedDecodingCapabilities, _Mapping]] = ..., max_num_sequences: _Optional[int] = ..., supports_priority: _Optional[bool] = ..., supports_stop_in_output: _Optional[bool] = ..., supports_cache_salt: _Optional[bool] = ..., supports_prefix_cache_bypass: _Optional[bool] = ...) -> None: ... - -class LogprobCapabilities(_message.Message): - __slots__ = ("supported", "candidate_selection_modes", "max_top_n") - SUPPORTED_FIELD_NUMBER: _ClassVar[int] - CANDIDATE_SELECTION_MODES_FIELD_NUMBER: _ClassVar[int] - MAX_TOP_N_FIELD_NUMBER: _ClassVar[int] - supported: bool - candidate_selection_modes: _containers.RepeatedScalarFieldContainer[CandidateTokenSelectionMode] - max_top_n: int - def __init__(self, supported: _Optional[bool] = ..., candidate_selection_modes: _Optional[_Iterable[_Union[CandidateTokenSelectionMode, str]]] = ..., max_top_n: _Optional[int] = ...) -> None: ... - -class GuidedDecodingCapabilities(_message.Message): - __slots__ = ("supported", "modes") - SUPPORTED_FIELD_NUMBER: _ClassVar[int] - MODES_FIELD_NUMBER: _ClassVar[int] - supported: bool - modes: _containers.RepeatedScalarFieldContainer[GuidedDecodingMode] - def __init__(self, supported: _Optional[bool] = ..., modes: _Optional[_Iterable[_Union[GuidedDecodingMode, str]]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/observability_pb2.py b/packages/python/src/openengine/v1/observability_pb2.py deleted file mode 100644 index 63ede5f..0000000 --- a/packages/python/src/openengine/v1/observability_pb2.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/observability.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/observability.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from openengine.v1 import error_pb2 as openengine_dot_v1_dot_error__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!openengine/v1/observability.proto\x12\ropenengine.v1\x1a\x19openengine/v1/error.proto\"*\n\x0eGetLoadRequest\x12\x18\n\x10include_per_rank\x18\x01 \x01(\x08\"\xc5\x05\n\x08LoadInfo\x12\x13\n\x0binstance_id\x18\x01 \x01(\t\x12!\n\x14timestamp_unix_nanos\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x1d\n\x10running_requests\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x1c\n\x0fqueued_requests\x18\x04 \x01(\rH\x02\x88\x01\x01\x12\x1f\n\x12\x61\x63tive_kv_sessions\x18\x05 \x01(\rH\x03\x88\x01\x01\x12\x1b\n\x0eused_kv_blocks\x18\x06 \x01(\x04H\x04\x88\x01\x01\x12\x1c\n\x0ftotal_kv_blocks\x18\x07 \x01(\x04H\x05\x88\x01\x01\x12\x1b\n\x0erunning_tokens\x18\x08 \x01(\x04H\x06\x88\x01\x01\x12\x1b\n\x0ewaiting_tokens\x18\t \x01(\x04H\x07\x88\x01\x01\x12\x1f\n\x12prefill_batch_size\x18\n \x01(\rH\x08\x88\x01\x01\x12\x1e\n\x11\x64\x65\x63ode_batch_size\x18\x0b \x01(\rH\t\x88\x01\x01\x12*\n\x05ranks\x18\x14 \x03(\x0b\x32\x1b.openengine.v1.RankLoadInfo\x12;\n\nattributes\x18\x1e \x03(\x0b\x32\'.openengine.v1.LoadInfo.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x15_timestamp_unix_nanosB\x13\n\x11_running_requestsB\x12\n\x10_queued_requestsB\x15\n\x13_active_kv_sessionsB\x11\n\x0f_used_kv_blocksB\x12\n\x10_total_kv_blocksB\x11\n\x0f_running_tokensB\x11\n\x0f_waiting_tokensB\x15\n\x13_prefill_batch_sizeB\x14\n\x12_decode_batch_size\"\xfc\x02\n\x0cRankLoadInfo\x12\x1f\n\x12\x64\x61ta_parallel_rank\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x1d\n\x10running_requests\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1c\n\x0fqueued_requests\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x1b\n\x0eused_kv_blocks\x18\x04 \x01(\x04H\x03\x88\x01\x01\x12\x1c\n\x0ftotal_kv_blocks\x18\x05 \x01(\x04H\x04\x88\x01\x01\x12\x1f\n\x12prefill_batch_size\x18\x06 \x01(\rH\x05\x88\x01\x01\x12\x1e\n\x11\x64\x65\x63ode_batch_size\x18\x07 \x01(\rH\x06\x88\x01\x01\x42\x15\n\x13_data_parallel_rankB\x13\n\x11_running_requestsB\x12\n\x10_queued_requestsB\x11\n\x0f_used_kv_blocksB\x12\n\x10_total_kv_blocksB\x15\n\x13_prefill_batch_sizeB\x14\n\x12_decode_batch_size\"O\n\x1dSubscribeRuntimeEventsRequest\x12.\n\x05types\x18\x01 \x03(\x0e\x32\x1f.openengine.v1.RuntimeEventType\"\x8c\x01\n\x1eSubscribeRuntimeEventsResponse\x12\x34\n\rruntime_event\x18\x01 \x01(\x0b\x32\x1b.openengine.v1.RuntimeEventH\x00\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1a.openengine.v1.EngineErrorH\x00\x42\x07\n\x05\x65vent\"\xe1\x01\n\x0cRuntimeEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\t\x12\x1c\n\x14timestamp_unix_nanos\x18\x02 \x01(\x04\x12-\n\x04type\x18\x03 \x01(\x0e\x32\x1f.openengine.v1.RuntimeEventType\x12?\n\nattributes\x18\x04 \x03(\x0b\x32+.openengine.v1.RuntimeEvent.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01*\xb8\x01\n\x10RuntimeEventType\x12\"\n\x1eRUNTIME_EVENT_TYPE_UNSPECIFIED\x10\x00\x12#\n\x1fRUNTIME_EVENT_TYPE_FORWARD_PASS\x10\x01\x12\x1c\n\x18RUNTIME_EVENT_TYPE_BATCH\x10\x02\x12\x1c\n\x18RUNTIME_EVENT_TYPE_QUEUE\x10\x03\x12\x1f\n\x1bRUNTIME_EVENT_TYPE_TRANSFER\x10\x04\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.observability_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_LOADINFO_ATTRIBUTESENTRY']._loaded_options = None - _globals['_LOADINFO_ATTRIBUTESENTRY']._serialized_options = b'8\001' - _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._loaded_options = None - _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._serialized_options = b'8\001' - _globals['_RUNTIMEEVENTTYPE']._serialized_start=1671 - _globals['_RUNTIMEEVENTTYPE']._serialized_end=1855 - _globals['_GETLOADREQUEST']._serialized_start=79 - _globals['_GETLOADREQUEST']._serialized_end=121 - _globals['_LOADINFO']._serialized_start=124 - _globals['_LOADINFO']._serialized_end=833 - _globals['_LOADINFO_ATTRIBUTESENTRY']._serialized_start=573 - _globals['_LOADINFO_ATTRIBUTESENTRY']._serialized_end=622 - _globals['_RANKLOADINFO']._serialized_start=836 - _globals['_RANKLOADINFO']._serialized_end=1216 - _globals['_SUBSCRIBERUNTIMEEVENTSREQUEST']._serialized_start=1218 - _globals['_SUBSCRIBERUNTIMEEVENTSREQUEST']._serialized_end=1297 - _globals['_SUBSCRIBERUNTIMEEVENTSRESPONSE']._serialized_start=1300 - _globals['_SUBSCRIBERUNTIMEEVENTSRESPONSE']._serialized_end=1440 - _globals['_RUNTIMEEVENT']._serialized_start=1443 - _globals['_RUNTIMEEVENT']._serialized_end=1668 - _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._serialized_start=573 - _globals['_RUNTIMEEVENT_ATTRIBUTESENTRY']._serialized_end=622 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/observability_pb2.pyi b/packages/python/src/openengine/v1/observability_pb2.pyi deleted file mode 100644 index 7b4de09..0000000 --- a/packages/python/src/openengine/v1/observability_pb2.pyi +++ /dev/null @@ -1,116 +0,0 @@ -from openengine.v1 import error_pb2 as _error_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Iterable as _Iterable, Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class RuntimeEventType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - RUNTIME_EVENT_TYPE_UNSPECIFIED: _ClassVar[RuntimeEventType] - RUNTIME_EVENT_TYPE_FORWARD_PASS: _ClassVar[RuntimeEventType] - RUNTIME_EVENT_TYPE_BATCH: _ClassVar[RuntimeEventType] - RUNTIME_EVENT_TYPE_QUEUE: _ClassVar[RuntimeEventType] - RUNTIME_EVENT_TYPE_TRANSFER: _ClassVar[RuntimeEventType] -RUNTIME_EVENT_TYPE_UNSPECIFIED: RuntimeEventType -RUNTIME_EVENT_TYPE_FORWARD_PASS: RuntimeEventType -RUNTIME_EVENT_TYPE_BATCH: RuntimeEventType -RUNTIME_EVENT_TYPE_QUEUE: RuntimeEventType -RUNTIME_EVENT_TYPE_TRANSFER: RuntimeEventType - -class GetLoadRequest(_message.Message): - __slots__ = ("include_per_rank",) - INCLUDE_PER_RANK_FIELD_NUMBER: _ClassVar[int] - include_per_rank: bool - def __init__(self, include_per_rank: _Optional[bool] = ...) -> None: ... - -class LoadInfo(_message.Message): - __slots__ = ("instance_id", "timestamp_unix_nanos", "running_requests", "queued_requests", "active_kv_sessions", "used_kv_blocks", "total_kv_blocks", "running_tokens", "waiting_tokens", "prefill_batch_size", "decode_batch_size", "ranks", "attributes") - class AttributesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... - INSTANCE_ID_FIELD_NUMBER: _ClassVar[int] - TIMESTAMP_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] - RUNNING_REQUESTS_FIELD_NUMBER: _ClassVar[int] - QUEUED_REQUESTS_FIELD_NUMBER: _ClassVar[int] - ACTIVE_KV_SESSIONS_FIELD_NUMBER: _ClassVar[int] - USED_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] - TOTAL_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] - RUNNING_TOKENS_FIELD_NUMBER: _ClassVar[int] - WAITING_TOKENS_FIELD_NUMBER: _ClassVar[int] - PREFILL_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] - DECODE_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] - RANKS_FIELD_NUMBER: _ClassVar[int] - ATTRIBUTES_FIELD_NUMBER: _ClassVar[int] - instance_id: str - timestamp_unix_nanos: int - running_requests: int - queued_requests: int - active_kv_sessions: int - used_kv_blocks: int - total_kv_blocks: int - running_tokens: int - waiting_tokens: int - prefill_batch_size: int - decode_batch_size: int - ranks: _containers.RepeatedCompositeFieldContainer[RankLoadInfo] - attributes: _containers.ScalarMap[str, str] - def __init__(self, instance_id: _Optional[str] = ..., timestamp_unix_nanos: _Optional[int] = ..., running_requests: _Optional[int] = ..., queued_requests: _Optional[int] = ..., active_kv_sessions: _Optional[int] = ..., used_kv_blocks: _Optional[int] = ..., total_kv_blocks: _Optional[int] = ..., running_tokens: _Optional[int] = ..., waiting_tokens: _Optional[int] = ..., prefill_batch_size: _Optional[int] = ..., decode_batch_size: _Optional[int] = ..., ranks: _Optional[_Iterable[_Union[RankLoadInfo, _Mapping]]] = ..., attributes: _Optional[_Mapping[str, str]] = ...) -> None: ... - -class RankLoadInfo(_message.Message): - __slots__ = ("data_parallel_rank", "running_requests", "queued_requests", "used_kv_blocks", "total_kv_blocks", "prefill_batch_size", "decode_batch_size") - DATA_PARALLEL_RANK_FIELD_NUMBER: _ClassVar[int] - RUNNING_REQUESTS_FIELD_NUMBER: _ClassVar[int] - QUEUED_REQUESTS_FIELD_NUMBER: _ClassVar[int] - USED_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] - TOTAL_KV_BLOCKS_FIELD_NUMBER: _ClassVar[int] - PREFILL_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] - DECODE_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int] - data_parallel_rank: int - running_requests: int - queued_requests: int - used_kv_blocks: int - total_kv_blocks: int - prefill_batch_size: int - decode_batch_size: int - def __init__(self, data_parallel_rank: _Optional[int] = ..., running_requests: _Optional[int] = ..., queued_requests: _Optional[int] = ..., used_kv_blocks: _Optional[int] = ..., total_kv_blocks: _Optional[int] = ..., prefill_batch_size: _Optional[int] = ..., decode_batch_size: _Optional[int] = ...) -> None: ... - -class SubscribeRuntimeEventsRequest(_message.Message): - __slots__ = ("types",) - TYPES_FIELD_NUMBER: _ClassVar[int] - types: _containers.RepeatedScalarFieldContainer[RuntimeEventType] - def __init__(self, types: _Optional[_Iterable[_Union[RuntimeEventType, str]]] = ...) -> None: ... - -class SubscribeRuntimeEventsResponse(_message.Message): - __slots__ = ("runtime_event", "error") - RUNTIME_EVENT_FIELD_NUMBER: _ClassVar[int] - ERROR_FIELD_NUMBER: _ClassVar[int] - runtime_event: RuntimeEvent - error: _error_pb2.EngineError - def __init__(self, runtime_event: _Optional[_Union[RuntimeEvent, _Mapping]] = ..., error: _Optional[_Union[_error_pb2.EngineError, _Mapping]] = ...) -> None: ... - -class RuntimeEvent(_message.Message): - __slots__ = ("event_id", "timestamp_unix_nanos", "type", "attributes") - class AttributesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... - EVENT_ID_FIELD_NUMBER: _ClassVar[int] - TIMESTAMP_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - ATTRIBUTES_FIELD_NUMBER: _ClassVar[int] - event_id: str - timestamp_unix_nanos: int - type: RuntimeEventType - attributes: _containers.ScalarMap[str, str] - def __init__(self, event_id: _Optional[str] = ..., timestamp_unix_nanos: _Optional[int] = ..., type: _Optional[_Union[RuntimeEventType, str]] = ..., attributes: _Optional[_Mapping[str, str]] = ...) -> None: ... diff --git a/packages/python/src/openengine/v1/openengine_pb2.py b/packages/python/src/openengine/v1/openengine_pb2.py deleted file mode 100644 index 8fc18d7..0000000 --- a/packages/python/src/openengine/v1/openengine_pb2.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: openengine/v1/openengine.proto -# Protobuf Python Version: 6.33.5 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - '', - 'openengine/v1/openengine.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from openengine.v1 import engine_pb2 as openengine_dot_v1_dot_engine__pb2 -from openengine.v1 import generation_pb2 as openengine_dot_v1_dot_generation__pb2 -from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 -from openengine.v1 import lifecycle_pb2 as openengine_dot_v1_dot_lifecycle__pb2 -from openengine.v1 import lora_pb2 as openengine_dot_v1_dot_lora__pb2 -from openengine.v1 import model_pb2 as openengine_dot_v1_dot_model__pb2 -from openengine.v1 import observability_pb2 as openengine_dot_v1_dot_observability__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eopenengine/v1/openengine.proto\x12\ropenengine.v1\x1a\x1aopenengine/v1/engine.proto\x1a\x1eopenengine/v1/generation.proto\x1a\x16openengine/v1/kv.proto\x1a\x1dopenengine/v1/lifecycle.proto\x1a\x18openengine/v1/lora.proto\x1a\x19openengine/v1/model.proto\x1a!openengine/v1/observability.proto2\xa9\t\n\nOpenEngine\x12M\n\x08Generate\x12\x1e.openengine.v1.GenerateRequest\x1a\x1f.openengine.v1.GenerateResponse0\x01\x12O\n\rGetEngineInfo\x12#.openengine.v1.GetEngineInfoRequest\x1a\x19.openengine.v1.EngineInfo\x12L\n\x0cGetModelInfo\x12\".openengine.v1.GetModelInfoRequest\x1a\x18.openengine.v1.ModelInfo\x12\x41\n\x07GetLoad\x12\x1d.openengine.v1.GetLoadRequest\x1a\x17.openengine.v1.LoadInfo\x12\x45\n\x06Health\x12\x1c.openengine.v1.HealthRequest\x1a\x1d.openengine.v1.HealthResponse\x12\x42\n\x05\x41\x62ort\x12\x1b.openengine.v1.AbortRequest\x1a\x1c.openengine.v1.AbortResponse\x12\x44\n\x05\x44rain\x12\x1b.openengine.v1.DrainRequest\x1a\x1c.openengine.v1.DrainResponse0\x01\x12K\n\x08LoadLora\x12\x1e.openengine.v1.LoadLoraRequest\x1a\x1f.openengine.v1.LoadLoraResponse\x12Q\n\nUnloadLora\x12 .openengine.v1.UnloadLoraRequest\x1a!.openengine.v1.UnloadLoraResponse\x12N\n\tListLoras\x12\x1f.openengine.v1.ListLorasRequest\x1a .openengine.v1.ListLorasResponse\x12^\n\x12GetKvConnectorInfo\x12(.openengine.v1.GetKvConnectorInfoRequest\x1a\x1e.openengine.v1.KvConnectorInfo\x12\x66\n\x11GetKvEventSources\x12\'.openengine.v1.GetKvEventSourcesRequest\x1a(.openengine.v1.GetKvEventSourcesResponse\x12h\n\x11SubscribeKvEvents\x12\'.openengine.v1.SubscribeKvEventsRequest\x1a(.openengine.v1.SubscribeKvEventsResponse0\x01\x12w\n\x16SubscribeRuntimeEvents\x12,.openengine.v1.SubscribeRuntimeEventsRequest\x1a-.openengine.v1.SubscribeRuntimeEventsResponse0\x01\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'openengine.v1.openengine_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_OPENENGINE']._serialized_start=253 - _globals['_OPENENGINE']._serialized_end=1446 -# @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/openengine/v1/openengine_pb2.pyi b/packages/python/src/openengine/v1/openengine_pb2.pyi deleted file mode 100644 index 27db98d..0000000 --- a/packages/python/src/openengine/v1/openengine_pb2.pyi +++ /dev/null @@ -1,11 +0,0 @@ -from openengine.v1 import engine_pb2 as _engine_pb2 -from openengine.v1 import generation_pb2 as _generation_pb2 -from openengine.v1 import kv_pb2 as _kv_pb2 -from openengine.v1 import lifecycle_pb2 as _lifecycle_pb2 -from openengine.v1 import lora_pb2 as _lora_pb2 -from openengine.v1 import model_pb2 as _model_pb2 -from openengine.v1 import observability_pb2 as _observability_pb2 -from google.protobuf import descriptor as _descriptor -from typing import ClassVar as _ClassVar - -DESCRIPTOR: _descriptor.FileDescriptor diff --git a/packages/python/src/openengine/v1/openengine_pb2_grpc.py b/packages/python/src/openengine/v1/openengine_pb2_grpc.py deleted file mode 100644 index 3290cac..0000000 --- a/packages/python/src/openengine/v1/openengine_pb2_grpc.py +++ /dev/null @@ -1,668 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -import grpc -import warnings - -from openengine.v1 import engine_pb2 as openengine_dot_v1_dot_engine__pb2 -from openengine.v1 import generation_pb2 as openengine_dot_v1_dot_generation__pb2 -from openengine.v1 import kv_pb2 as openengine_dot_v1_dot_kv__pb2 -from openengine.v1 import lifecycle_pb2 as openengine_dot_v1_dot_lifecycle__pb2 -from openengine.v1 import lora_pb2 as openengine_dot_v1_dot_lora__pb2 -from openengine.v1 import model_pb2 as openengine_dot_v1_dot_model__pb2 -from openengine.v1 import observability_pb2 as openengine_dot_v1_dot_observability__pb2 - -GRPC_GENERATED_VERSION = '1.81.1' -GRPC_VERSION = grpc.__version__ -_version_not_supported = False - -try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - raise RuntimeError( - f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in openengine/v1/openengine_pb2_grpc.py depends on' - + f' grpcio>={GRPC_GENERATED_VERSION}.' - + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' - + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' - ) - - -class OpenEngineStub: - """Missing associated documentation comment in .proto file.""" - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.Generate = channel.unary_stream( - '/openengine.v1.OpenEngine/Generate', - request_serializer=openengine_dot_v1_dot_generation__pb2.GenerateRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_generation__pb2.GenerateResponse.FromString, - _registered_method=True) - self.GetEngineInfo = channel.unary_unary( - '/openengine.v1.OpenEngine/GetEngineInfo', - request_serializer=openengine_dot_v1_dot_engine__pb2.GetEngineInfoRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_engine__pb2.EngineInfo.FromString, - _registered_method=True) - self.GetModelInfo = channel.unary_unary( - '/openengine.v1.OpenEngine/GetModelInfo', - request_serializer=openengine_dot_v1_dot_model__pb2.GetModelInfoRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_model__pb2.ModelInfo.FromString, - _registered_method=True) - self.GetLoad = channel.unary_unary( - '/openengine.v1.OpenEngine/GetLoad', - request_serializer=openengine_dot_v1_dot_observability__pb2.GetLoadRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_observability__pb2.LoadInfo.FromString, - _registered_method=True) - self.Health = channel.unary_unary( - '/openengine.v1.OpenEngine/Health', - request_serializer=openengine_dot_v1_dot_lifecycle__pb2.HealthRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_lifecycle__pb2.HealthResponse.FromString, - _registered_method=True) - self.Abort = channel.unary_unary( - '/openengine.v1.OpenEngine/Abort', - request_serializer=openengine_dot_v1_dot_lifecycle__pb2.AbortRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_lifecycle__pb2.AbortResponse.FromString, - _registered_method=True) - self.Drain = channel.unary_stream( - '/openengine.v1.OpenEngine/Drain', - request_serializer=openengine_dot_v1_dot_lifecycle__pb2.DrainRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_lifecycle__pb2.DrainResponse.FromString, - _registered_method=True) - self.LoadLora = channel.unary_unary( - '/openengine.v1.OpenEngine/LoadLora', - request_serializer=openengine_dot_v1_dot_lora__pb2.LoadLoraRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_lora__pb2.LoadLoraResponse.FromString, - _registered_method=True) - self.UnloadLora = channel.unary_unary( - '/openengine.v1.OpenEngine/UnloadLora', - request_serializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraResponse.FromString, - _registered_method=True) - self.ListLoras = channel.unary_unary( - '/openengine.v1.OpenEngine/ListLoras', - request_serializer=openengine_dot_v1_dot_lora__pb2.ListLorasRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_lora__pb2.ListLorasResponse.FromString, - _registered_method=True) - self.GetKvConnectorInfo = channel.unary_unary( - '/openengine.v1.OpenEngine/GetKvConnectorInfo', - request_serializer=openengine_dot_v1_dot_kv__pb2.GetKvConnectorInfoRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_kv__pb2.KvConnectorInfo.FromString, - _registered_method=True) - self.GetKvEventSources = channel.unary_unary( - '/openengine.v1.OpenEngine/GetKvEventSources', - request_serializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesResponse.FromString, - _registered_method=True) - self.SubscribeKvEvents = channel.unary_stream( - '/openengine.v1.OpenEngine/SubscribeKvEvents', - request_serializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsResponse.FromString, - _registered_method=True) - self.SubscribeRuntimeEvents = channel.unary_stream( - '/openengine.v1.OpenEngine/SubscribeRuntimeEvents', - request_serializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsRequest.SerializeToString, - response_deserializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsResponse.FromString, - _registered_method=True) - - -class OpenEngineServicer: - """Missing associated documentation comment in .proto file.""" - - def Generate(self, request, context): - """Core inference path. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def GetEngineInfo(self, request, context): - """Runtime metadata and scheduling state. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def GetModelInfo(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def GetLoad(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def Health(self, request, context): - """Health and lifecycle. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def Abort(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def Drain(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def LoadLora(self, request, context): - """LoRA lifecycle. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def UnloadLora(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def ListLoras(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def GetKvConnectorInfo(self, request, context): - """Disaggregated serving / KV transfer. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def GetKvEventSources(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def SubscribeKvEvents(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def SubscribeRuntimeEvents(self, request, context): - """Structured runtime events for planners/controllers. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_OpenEngineServicer_to_server(servicer, server): - rpc_method_handlers = { - 'Generate': grpc.unary_stream_rpc_method_handler( - servicer.Generate, - request_deserializer=openengine_dot_v1_dot_generation__pb2.GenerateRequest.FromString, - response_serializer=openengine_dot_v1_dot_generation__pb2.GenerateResponse.SerializeToString, - ), - 'GetEngineInfo': grpc.unary_unary_rpc_method_handler( - servicer.GetEngineInfo, - request_deserializer=openengine_dot_v1_dot_engine__pb2.GetEngineInfoRequest.FromString, - response_serializer=openengine_dot_v1_dot_engine__pb2.EngineInfo.SerializeToString, - ), - 'GetModelInfo': grpc.unary_unary_rpc_method_handler( - servicer.GetModelInfo, - request_deserializer=openengine_dot_v1_dot_model__pb2.GetModelInfoRequest.FromString, - response_serializer=openengine_dot_v1_dot_model__pb2.ModelInfo.SerializeToString, - ), - 'GetLoad': grpc.unary_unary_rpc_method_handler( - servicer.GetLoad, - request_deserializer=openengine_dot_v1_dot_observability__pb2.GetLoadRequest.FromString, - response_serializer=openengine_dot_v1_dot_observability__pb2.LoadInfo.SerializeToString, - ), - 'Health': grpc.unary_unary_rpc_method_handler( - servicer.Health, - request_deserializer=openengine_dot_v1_dot_lifecycle__pb2.HealthRequest.FromString, - response_serializer=openengine_dot_v1_dot_lifecycle__pb2.HealthResponse.SerializeToString, - ), - 'Abort': grpc.unary_unary_rpc_method_handler( - servicer.Abort, - request_deserializer=openengine_dot_v1_dot_lifecycle__pb2.AbortRequest.FromString, - response_serializer=openengine_dot_v1_dot_lifecycle__pb2.AbortResponse.SerializeToString, - ), - 'Drain': grpc.unary_stream_rpc_method_handler( - servicer.Drain, - request_deserializer=openengine_dot_v1_dot_lifecycle__pb2.DrainRequest.FromString, - response_serializer=openengine_dot_v1_dot_lifecycle__pb2.DrainResponse.SerializeToString, - ), - 'LoadLora': grpc.unary_unary_rpc_method_handler( - servicer.LoadLora, - request_deserializer=openengine_dot_v1_dot_lora__pb2.LoadLoraRequest.FromString, - response_serializer=openengine_dot_v1_dot_lora__pb2.LoadLoraResponse.SerializeToString, - ), - 'UnloadLora': grpc.unary_unary_rpc_method_handler( - servicer.UnloadLora, - request_deserializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraRequest.FromString, - response_serializer=openengine_dot_v1_dot_lora__pb2.UnloadLoraResponse.SerializeToString, - ), - 'ListLoras': grpc.unary_unary_rpc_method_handler( - servicer.ListLoras, - request_deserializer=openengine_dot_v1_dot_lora__pb2.ListLorasRequest.FromString, - response_serializer=openengine_dot_v1_dot_lora__pb2.ListLorasResponse.SerializeToString, - ), - 'GetKvConnectorInfo': grpc.unary_unary_rpc_method_handler( - servicer.GetKvConnectorInfo, - request_deserializer=openengine_dot_v1_dot_kv__pb2.GetKvConnectorInfoRequest.FromString, - response_serializer=openengine_dot_v1_dot_kv__pb2.KvConnectorInfo.SerializeToString, - ), - 'GetKvEventSources': grpc.unary_unary_rpc_method_handler( - servicer.GetKvEventSources, - request_deserializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesRequest.FromString, - response_serializer=openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesResponse.SerializeToString, - ), - 'SubscribeKvEvents': grpc.unary_stream_rpc_method_handler( - servicer.SubscribeKvEvents, - request_deserializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsRequest.FromString, - response_serializer=openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsResponse.SerializeToString, - ), - 'SubscribeRuntimeEvents': grpc.unary_stream_rpc_method_handler( - servicer.SubscribeRuntimeEvents, - request_deserializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsRequest.FromString, - response_serializer=openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'openengine.v1.OpenEngine', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler,)) - server.add_registered_method_handlers('openengine.v1.OpenEngine', rpc_method_handlers) - - - # This class is part of an EXPERIMENTAL API. -class OpenEngine: - """Missing associated documentation comment in .proto file.""" - - @staticmethod - def Generate(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_stream( - request, - target, - '/openengine.v1.OpenEngine/Generate', - openengine_dot_v1_dot_generation__pb2.GenerateRequest.SerializeToString, - openengine_dot_v1_dot_generation__pb2.GenerateResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def GetEngineInfo(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/GetEngineInfo', - openengine_dot_v1_dot_engine__pb2.GetEngineInfoRequest.SerializeToString, - openengine_dot_v1_dot_engine__pb2.EngineInfo.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def GetModelInfo(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/GetModelInfo', - openengine_dot_v1_dot_model__pb2.GetModelInfoRequest.SerializeToString, - openengine_dot_v1_dot_model__pb2.ModelInfo.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def GetLoad(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/GetLoad', - openengine_dot_v1_dot_observability__pb2.GetLoadRequest.SerializeToString, - openengine_dot_v1_dot_observability__pb2.LoadInfo.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def Health(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/Health', - openengine_dot_v1_dot_lifecycle__pb2.HealthRequest.SerializeToString, - openengine_dot_v1_dot_lifecycle__pb2.HealthResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def Abort(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/Abort', - openengine_dot_v1_dot_lifecycle__pb2.AbortRequest.SerializeToString, - openengine_dot_v1_dot_lifecycle__pb2.AbortResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def Drain(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_stream( - request, - target, - '/openengine.v1.OpenEngine/Drain', - openengine_dot_v1_dot_lifecycle__pb2.DrainRequest.SerializeToString, - openengine_dot_v1_dot_lifecycle__pb2.DrainResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def LoadLora(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/LoadLora', - openengine_dot_v1_dot_lora__pb2.LoadLoraRequest.SerializeToString, - openengine_dot_v1_dot_lora__pb2.LoadLoraResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def UnloadLora(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/UnloadLora', - openengine_dot_v1_dot_lora__pb2.UnloadLoraRequest.SerializeToString, - openengine_dot_v1_dot_lora__pb2.UnloadLoraResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def ListLoras(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/ListLoras', - openengine_dot_v1_dot_lora__pb2.ListLorasRequest.SerializeToString, - openengine_dot_v1_dot_lora__pb2.ListLorasResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def GetKvConnectorInfo(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/GetKvConnectorInfo', - openengine_dot_v1_dot_kv__pb2.GetKvConnectorInfoRequest.SerializeToString, - openengine_dot_v1_dot_kv__pb2.KvConnectorInfo.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def GetKvEventSources(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/openengine.v1.OpenEngine/GetKvEventSources', - openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesRequest.SerializeToString, - openengine_dot_v1_dot_kv__pb2.GetKvEventSourcesResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def SubscribeKvEvents(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_stream( - request, - target, - '/openengine.v1.OpenEngine/SubscribeKvEvents', - openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsRequest.SerializeToString, - openengine_dot_v1_dot_kv__pb2.SubscribeKvEventsResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - - @staticmethod - def SubscribeRuntimeEvents(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_stream( - request, - target, - '/openengine.v1.OpenEngine/SubscribeRuntimeEvents', - openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsRequest.SerializeToString, - openengine_dot_v1_dot_observability__pb2.SubscribeRuntimeEventsResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) diff --git a/packages/python/tests/test_bindings.py b/packages/python/tests/test_bindings.py deleted file mode 100644 index 09442db..0000000 --- a/packages/python/tests/test_bindings.py +++ /dev/null @@ -1,41 +0,0 @@ -import unittest - -import grpc - -from openengine import SCHEMA_RELEASE, SCHEMA_REVISION, __version__ -from openengine.v1.generation_pb2 import GenerateRequest -from openengine.v1.openengine_pb2_grpc import OpenEngineStub - - -class BindingsTest(unittest.TestCase): - def test_request_round_trip_preserves_optional_zero(self) -> None: - request = GenerateRequest( - request_id="python-smoke", - model="test-model", - prompt="Hello", - priority=0, - ) - - decoded = GenerateRequest.FromString(request.SerializeToString()) - - self.assertEqual(decoded.request_id, "python-smoke") - self.assertEqual(decoded.WhichOneof("input"), "prompt") - self.assertTrue(decoded.HasField("priority")) - self.assertEqual(decoded.priority, 0) - - def test_client_stub_can_be_constructed(self) -> None: - channel = grpc.insecure_channel("localhost:1") - self.addCleanup(channel.close) - - stub = OpenEngineStub(channel) - - self.assertTrue(callable(stub.Generate)) - self.assertTrue(callable(stub.GetEngineInfo)) - - def test_package_metadata_matches_schema(self) -> None: - self.assertEqual(SCHEMA_REVISION, 1) - self.assertEqual(SCHEMA_RELEASE, f"v{__version__}") - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/rust/openengine-proto/examples/cross_language_fixture.rs b/packages/rust/openengine-proto/examples/cross_language_fixture.rs deleted file mode 100644 index 3842981..0000000 --- a/packages/rust/openengine-proto/examples/cross_language_fixture.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::env; -use std::fs; -use std::path::Path; - -use openengine_proto::openengine::v1::{generate_request, GenerateRequest}; -use prost::Message; - -fn fixture() -> GenerateRequest { - GenerateRequest { - request_id: "cross-language".into(), - model: "test-model".into(), - input: Some(generate_request::Input::Prompt("Hello".into())), - priority: Some(0), - ..Default::default() - } -} - -fn encode(path: &Path) { - fs::write(path, fixture().encode_to_vec()).unwrap(); -} - -fn decode(path: &Path) { - let bytes = fs::read(path).unwrap(); - let request = GenerateRequest::decode(bytes.as_slice()).unwrap(); - assert_eq!(request, fixture()); -} - -fn main() { - let mut args = env::args_os().skip(1); - let operation = args.next().expect("expected encode or decode"); - let path = args.next().expect("expected fixture path"); - assert!(args.next().is_none(), "unexpected additional arguments"); - - match operation.to_str() { - Some("encode") => encode(Path::new(&path)), - Some("decode") => decode(Path::new(&path)), - _ => panic!("expected encode or decode"), - } -} diff --git a/packages/rust/openengine-proto/src/lib.rs b/packages/rust/openengine-proto/src/lib.rs deleted file mode 100644 index d09df73..0000000 --- a/packages/rust/openengine-proto/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Generated Prost messages and Tonic services for OpenEngine. - -/// Monotonically increasing revision of the packaged wire contract. -pub const SCHEMA_REVISION: u32 = 1; - -/// Immutable OpenEngine release corresponding to these bindings. -pub const SCHEMA_RELEASE: &str = concat!("v", env!("CARGO_PKG_VERSION")); - -/// Serialized descriptors for the complete `openengine.v1` package. -pub const FILE_DESCRIPTOR_SET: &[u8] = include_bytes!("generated/openengine_descriptor.bin"); - -/// Modules arranged to match the protobuf package name. -pub mod openengine { - /// Version 1 of the OpenEngine wire API. - pub mod v1 { - include!("generated/openengine.v1.rs"); - } -} diff --git a/packages/rust/openengine-proto/tests/bindings.rs b/packages/rust/openengine-proto/tests/bindings.rs deleted file mode 100644 index 5be8322..0000000 --- a/packages/rust/openengine-proto/tests/bindings.rs +++ /dev/null @@ -1,45 +0,0 @@ -use openengine_proto::openengine::v1::{generate_request, GenerateRequest}; -use openengine_proto::{FILE_DESCRIPTOR_SET, SCHEMA_RELEASE, SCHEMA_REVISION}; -use prost::Message; -use prost_types::FileDescriptorSet; - -#[test] -fn request_round_trip_preserves_optional_zero() { - let request = GenerateRequest { - request_id: "rust-smoke".into(), - model: "test-model".into(), - input: Some(generate_request::Input::Prompt("Hello".into())), - priority: Some(0), - ..Default::default() - }; - - let decoded = GenerateRequest::decode(request.encode_to_vec().as_slice()).unwrap(); - - assert_eq!(decoded.request_id, "rust-smoke"); - assert_eq!(decoded.priority, Some(0)); - assert!(matches!( - decoded.input, - Some(generate_request::Input::Prompt(prompt)) if prompt == "Hello" - )); -} - -#[test] -fn descriptor_set_contains_openengine_service() { - let descriptors = FileDescriptorSet::decode(FILE_DESCRIPTOR_SET).unwrap(); - let service_file = descriptors - .file - .iter() - .find(|file| file.name.as_deref() == Some("openengine/v1/openengine.proto")) - .unwrap(); - - assert!(service_file - .service - .iter() - .any(|service| service.name.as_deref() == Some("OpenEngine"))); -} - -#[test] -fn package_metadata_matches_schema() { - assert_eq!(SCHEMA_REVISION, 1); - assert_eq!(SCHEMA_RELEASE, concat!("v", env!("CARGO_PKG_VERSION"))); -} diff --git a/packages/rust/openengine-proto/Cargo.toml b/packages/rust/openengine/Cargo.toml similarity index 75% rename from packages/rust/openengine-proto/Cargo.toml rename to packages/rust/openengine/Cargo.toml index 63f8e89..6a22582 100644 --- a/packages/rust/openengine-proto/Cargo.toml +++ b/packages/rust/openengine/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "openengine-proto" +name = "openengine" version.workspace = true edition.workspace = true rust-version.workspace = true @@ -7,8 +7,11 @@ license.workspace = true repository.workspace = true description = "Generated Rust bindings for the OpenEngine gRPC protocol" readme = "README.md" +homepage = "https://github.com/ai-dynamo/openengine" +documentation = "https://docs.rs/openengine" keywords = ["grpc", "inference", "protobuf"] categories = ["api-bindings", "network-programming"] +publish = ["crates-io"] [dependencies] prost = "0.14.4" diff --git a/packages/rust/openengine/LICENSE b/packages/rust/openengine/LICENSE new file mode 100644 index 0000000..4c9ad98 --- /dev/null +++ b/packages/rust/openengine/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/rust/openengine-proto/README.md b/packages/rust/openengine/README.md similarity index 78% rename from packages/rust/openengine-proto/README.md rename to packages/rust/openengine/README.md index 21d2706..38b2b3d 100644 --- a/packages/rust/openengine-proto/README.md +++ b/packages/rust/openengine/README.md @@ -10,14 +10,11 @@ Generated Prost messages and Tonic client/server bindings for the protocol. ```bash -cargo add openengine-proto +cargo add openengine ``` ```rust -use openengine_proto::openengine::v1::{ - open_engine_client::OpenEngineClient, - GenerateRequest, -}; +use openengine::v1::{control_client::ControlClient, inference_client::InferenceClient}; ``` The crate contains generated Rust source and a protobuf descriptor set. diff --git a/packages/rust/openengine-proto/src/generated/openengine.v1.rs b/packages/rust/openengine/src/generated/openengine.v1.rs similarity index 77% rename from packages/rust/openengine-proto/src/generated/openengine.v1.rs rename to packages/rust/openengine/src/generated/openengine.v1.rs index a7ea8bb..d04b061 100644 --- a/packages/rust/openengine-proto/src/generated/openengine.v1.rs +++ b/packages/rust/openengine/src/generated/openengine.v1.rs @@ -1,7 +1,7 @@ // This file is @generated by prost-build. /// Accepted failures emit one terminal EngineError and close with OK. /// Validation and transport failures use non-OK gRPC status instead. -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct EngineError { #[prost(enumeration = "ErrorCode", tag = "1")] pub code: i32, @@ -10,12 +10,6 @@ pub struct EngineError { /// Retry may succeed without changing the request. #[prost(bool, tag = "3")] pub retryable: bool, - /// Zero permits immediate retry. - #[prost(uint64, optional, tag = "4")] - pub retry_after_ms: ::core::option::Option, - /// Machine-readable context. - #[prost(message, optional, tag = "5")] - pub details: ::core::option::Option<::prost_types::Struct>, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -31,8 +25,7 @@ pub enum ErrorCode { KvSessionNotFound = 8, KvTransferFailed = 9, Cancelled = 10, - Draining = 11, - Internal = 12, + Internal = 11, } impl ErrorCode { /// String value of the enum field names used in the ProtoBuf definition. @@ -52,7 +45,6 @@ impl ErrorCode { Self::KvSessionNotFound => "ERROR_CODE_KV_SESSION_NOT_FOUND", Self::KvTransferFailed => "ERROR_CODE_KV_TRANSFER_FAILED", Self::Cancelled => "ERROR_CODE_CANCELLED", - Self::Draining => "ERROR_CODE_DRAINING", Self::Internal => "ERROR_CODE_INTERNAL", } } @@ -70,7 +62,6 @@ impl ErrorCode { "ERROR_CODE_KV_SESSION_NOT_FOUND" => Some(Self::KvSessionNotFound), "ERROR_CODE_KV_TRANSFER_FAILED" => Some(Self::KvTransferFailed), "ERROR_CODE_CANCELLED" => Some(Self::Cancelled), - "ERROR_CODE_DRAINING" => Some(Self::Draining), "ERROR_CODE_INTERNAL" => Some(Self::Internal), _ => None, } @@ -86,11 +77,10 @@ pub struct KvSessionRef { pub endpoints: ::prost::alloc::vec::Vec, #[prost(uint32, tag = "4")] pub dp_rank: u32, - /// Engine-specific KV-transfer parameters (e.g. NixlConnector - /// remote_host / remote_port / tp_size / remote_block_ids / do_remote\_\*), - /// carried as a Struct so numbers, booleans, and arrays survive the wire with - /// their JSON type intact. Struct numbers are IEEE-754 doubles (exact only to - /// 2^53); carry larger integer values as strings or use a dedicated field. + /// Engine-specific KV-transfer and rendezvous parameters, carried as a Struct + /// so numbers, booleans, and arrays survive the wire with their JSON type + /// intact. Struct numbers are IEEE-754 doubles (exact only to 2^53); carry + /// larger integer values as decimal strings. #[prost(message, optional, tag = "5")] pub attributes_struct: ::core::option::Option<::prost_types::Struct>, } @@ -104,8 +94,6 @@ pub struct KvEndpoint { #[prost(string, tag = "3")] pub protocol: ::prost::alloc::string::String, } -#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] -pub struct GetKvConnectorInfoRequest {} #[derive(Clone, PartialEq, ::prost::Message)] pub struct KvConnectorInfo { #[prost(bool, optional, tag = "1")] @@ -122,9 +110,7 @@ pub struct KvConnectorInfo { pub supports_decode_pull: ::core::option::Option, #[prost(bool, optional, tag = "7")] pub supports_abort_cleanup: ::core::option::Option, - #[prost(bool, optional, tag = "8")] - pub supports_drain: ::core::option::Option, - #[prost(uint32, optional, tag = "9")] + #[prost(uint32, optional, tag = "8")] pub schema_version: ::core::option::Option, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -306,85 +292,89 @@ impl StorageMedium { } } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] -pub struct GetEngineInfoRequest {} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct TokenIds { + #[prost(uint32, repeated, tag = "1")] + pub ids: ::prost::alloc::vec::Vec, +} +/// A single multimodal input. Exactly one `source` should be set. The engine +/// owns fetch, decode, and preprocessing, so pre-decoded or RDMA media +/// descriptors are not represented here. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct MediaItem { + #[prost(enumeration = "Modality", tag = "1")] + pub modality: i32, + /// optional, hints raw_bytes decode + #[prost(string, tag = "5")] + pub mime_type: ::prost::alloc::string::String, + /// optional caller id / mm_hash + #[prost(string, tag = "6")] + pub uuid: ::prost::alloc::string::String, + #[prost(oneof = "media_item::Source", tags = "2, 3, 4")] + pub source: ::core::option::Option, +} +/// Nested message and enum types in `MediaItem`. +pub mod media_item { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Source { + /// http(s):// -- engine fetches + #[prost(string, tag = "2")] + Url(::prost::alloc::string::String), + /// data:;base64,\<...> -- engine decodes + #[prost(string, tag = "3")] + DataUri(::prost::alloc::string::String), + /// pre-fetched bytes -- engine still preprocesses + #[prost(bytes, tag = "4")] + RawBytes(::prost::alloc::vec::Vec), + } +} #[derive(Clone, PartialEq, ::prost::Message)] -pub struct EngineInfo { - /// sglang, vllm, tensorrt_llm, etc. +pub struct GenerateRequest { #[prost(string, tag = "1")] - pub engine_name: ::prost::alloc::string::String, + pub request_id: ::prost::alloc::string::String, #[prost(string, tag = "2")] - pub engine_version: ::prost::alloc::string::String, - #[prost(enumeration = "EngineRole", tag = "3")] - pub role: i32, - #[prost(string, tag = "4")] - pub instance_id: ::prost::alloc::string::String, - #[prost(string, repeated, tag = "5")] - pub supported_models: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + pub model: ::prost::alloc::string::String, + #[prost(message, optional, tag = "5")] + pub sampling: ::core::option::Option, #[prost(message, optional, tag = "6")] - pub parallelism: ::core::option::Option, + pub stopping: ::core::option::Option, #[prost(message, optional, tag = "7")] - pub kv_connector: ::core::option::Option, - /// Monotonic wire contract revision; zero is invalid. - #[prost(uint32, tag = "8")] - pub schema_revision: u32, - /// Oldest compatible client revision. - #[prost(uint32, tag = "9")] - pub minimum_client_revision: u32, - /// Immutable release or source tag for this schema. - #[prost(string, tag = "10")] - pub schema_release: ::prost::alloc::string::String, -} -#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] -pub struct ParallelismInfo { - #[prost(uint32, optional, tag = "1")] - pub tensor_parallel_size: ::core::option::Option, - #[prost(uint32, optional, tag = "2")] - pub pipeline_parallel_size: ::core::option::Option, - #[prost(uint32, optional, tag = "3")] - pub data_parallel_size: ::core::option::Option, - #[prost(uint32, optional, tag = "4")] - pub data_parallel_rank: ::core::option::Option, - #[prost(uint32, optional, tag = "5")] - pub data_parallel_start_rank: ::core::option::Option, -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum EngineRole { - Unspecified = 0, - Aggregated = 1, - Prefill = 2, - Decode = 3, + pub response: ::core::option::Option, + #[prost(message, optional, tag = "8")] + pub kv: ::core::option::Option, + #[prost(message, optional, tag = "9")] + pub guided: ::core::option::Option, + /// Multimodal inputs. Order is significant: the i-th item aligns with the + /// i-th (un-expanded) placeholder marker carried in the prompt/token_ids. + /// The engine fetches/decodes and preprocesses each item, then expands the + /// marker into the model's replacement run. Empty for text-only requests. + #[prost(message, repeated, tag = "10")] + pub media: ::prost::alloc::vec::Vec, + /// Loaded LoRA adapter name to apply to this request. Empty = base model. + /// ModelInfo.supports_lora advertises whether lifecycle and selection are + /// available through OpenEngine. + #[prost(string, tag = "11")] + pub lora_name: ::prost::alloc::string::String, + /// Engine-specific request parameters that have no portable field above (e.g. + /// an experimental sampler knob). NOT part of the portable contract: an engine + /// MAY ignore keys it does not recognize, and a request MUST remain valid with + /// this field empty. Clients treat it as best-effort and never depend on it + /// for correctness. Carried as a Struct so JSON types survive the wire. + #[prost(message, optional, tag = "12")] + pub extra: ::core::option::Option<::prost_types::Struct>, + #[prost(oneof = "generate_request::Input", tags = "3, 4")] + pub input: ::core::option::Option, } -impl EngineRole { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Unspecified => "ENGINE_ROLE_UNSPECIFIED", - Self::Aggregated => "ENGINE_ROLE_AGGREGATED", - Self::Prefill => "ENGINE_ROLE_PREFILL", - Self::Decode => "ENGINE_ROLE_DECODE", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "ENGINE_ROLE_UNSPECIFIED" => Some(Self::Unspecified), - "ENGINE_ROLE_AGGREGATED" => Some(Self::Aggregated), - "ENGINE_ROLE_PREFILL" => Some(Self::Prefill), - "ENGINE_ROLE_DECODE" => Some(Self::Decode), - _ => None, - } +/// Nested message and enum types in `GenerateRequest`. +pub mod generate_request { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Input { + #[prost(string, tag = "3")] + Prompt(::prost::alloc::string::String), + #[prost(message, tag = "4")] + TokenIds(super::TokenIds), } } -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct TokenIds { - #[prost(uint32, repeated, tag = "1")] - pub ids: ::prost::alloc::vec::Vec, -} #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct SamplingParams { #[prost(double, optional, tag = "1")] @@ -455,11 +445,9 @@ pub struct AllCandidates {} pub struct KvOptions { #[prost(message, optional, tag = "1")] pub session: ::core::option::Option, - #[prost(uint32, optional, tag = "2")] - pub data_parallel_rank: ::core::option::Option, - #[prost(bool, optional, tag = "3")] + #[prost(bool, optional, tag = "2")] pub bypass_prefix_cache: ::core::option::Option, - #[prost(string, optional, tag = "4")] + #[prost(string, optional, tag = "3")] pub cache_salt: ::core::option::Option<::prost::alloc::string::String>, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -519,86 +507,6 @@ pub struct ChoiceConstraint { #[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] pub struct JsonObjectConstraint {} #[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenerateRequest { - #[prost(string, tag = "1")] - pub request_id: ::prost::alloc::string::String, - #[prost(string, tag = "2")] - pub model: ::prost::alloc::string::String, - #[prost(message, optional, tag = "5")] - pub sampling: ::core::option::Option, - #[prost(message, optional, tag = "6")] - pub stopping: ::core::option::Option, - #[prost(message, optional, tag = "7")] - pub response: ::core::option::Option, - #[prost(message, optional, tag = "8")] - pub kv: ::core::option::Option, - #[prost(message, optional, tag = "9")] - pub guided: ::core::option::Option, - /// Multimodal inputs. Order is significant: the i-th item aligns with the - /// i-th (un-expanded) placeholder marker carried in the prompt/token_ids. - /// The engine fetches/decodes and preprocesses each item, then expands the - /// marker into the model's replacement run. Empty for text-only requests. - #[prost(message, repeated, tag = "10")] - pub media: ::prost::alloc::vec::Vec, - /// Loaded LoRA adapter name to apply to this request. Empty = base model. - /// ModelInfo.supports_lora advertises whether lifecycle and selection are - /// available through OpenEngine. - #[prost(string, tag = "11")] - pub lora_name: ::prost::alloc::string::String, - /// Higher values receive higher scheduling priority. - #[prost(int32, optional, tag = "12")] - pub priority: ::core::option::Option, - /// Optional request metadata for tracing/admission/routing. - #[prost(map = "string, string", tag = "13")] - pub metadata: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, - #[prost(oneof = "generate_request::Input", tags = "3, 4")] - pub input: ::core::option::Option, -} -/// Nested message and enum types in `GenerateRequest`. -pub mod generate_request { - #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] - pub enum Input { - #[prost(string, tag = "3")] - Prompt(::prost::alloc::string::String), - #[prost(message, tag = "4")] - TokenIds(super::TokenIds), - } -} -/// A single multimodal input. Exactly one `source` should be set. The engine -/// owns fetch, decode, and preprocessing, so pre-decoded or RDMA media -/// descriptors are not represented here. -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct MediaItem { - #[prost(enumeration = "Modality", tag = "1")] - pub modality: i32, - /// optional, hints raw_bytes decode - #[prost(string, tag = "5")] - pub mime_type: ::prost::alloc::string::String, - /// optional caller id / mm_hash - #[prost(string, tag = "6")] - pub uuid: ::prost::alloc::string::String, - #[prost(oneof = "media_item::Source", tags = "2, 3, 4")] - pub source: ::core::option::Option, -} -/// Nested message and enum types in `MediaItem`. -pub mod media_item { - #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] - pub enum Source { - /// http(s):// -- engine fetches - #[prost(string, tag = "2")] - Url(::prost::alloc::string::String), - /// data:;base64,\<...> -- engine decodes - #[prost(string, tag = "3")] - DataUri(::prost::alloc::string::String), - /// pre-fetched bytes -- engine still preprocesses - #[prost(bytes, tag = "4")] - RawBytes(::prost::alloc::vec::Vec), - } -} -#[derive(Clone, PartialEq, ::prost::Message)] pub struct GenerateResponse { #[prost(string, tag = "1")] pub request_id: ::prost::alloc::string::String, @@ -716,8 +624,7 @@ pub struct Usage { #[prost(uint32, optional, tag = "5")] pub reasoning_tokens: ::core::option::Option, } -/// Multimodal modality discriminator. 0 is treated as image for forward -/// compatibility with senders that omit the field. +/// Multimodal modality discriminator. UNSPECIFIED means the sender left it unset. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Modality { @@ -782,29 +689,184 @@ impl FinishReason { } } } -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct HealthRequest { - /// False means a lightweight readiness/liveness check. True asks the engine to - /// run a role-appropriate minimal inference probe and report it as a check. - #[prost(bool, tag = "1")] - pub include_inference_probe: bool, - /// Optional. Used when include_inference_probe is true. Empty means engine - /// default served model. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetServerInfoRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ServerInfo { + /// sglang, vllm, tensorrt_llm, etc. + #[prost(string, tag = "1")] + pub engine_name: ::prost::alloc::string::String, #[prost(string, tag = "2")] - pub model: ::prost::alloc::string::String, - /// Optional expected role for role-specific inference probes. + pub engine_version: ::prost::alloc::string::String, #[prost(enumeration = "EngineRole", tag = "3")] - pub role: i32, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct HealthResponse { - #[prost(enumeration = "HealthState", tag = "1")] - pub state: i32, - #[prost(message, repeated, tag = "2")] - pub checks: ::prost::alloc::vec::Vec, + pub engine_role: i32, + #[prost(string, tag = "4")] + pub instance_id: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "5")] + pub supported_models: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(message, optional, tag = "6")] + pub parallelism: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub kv_connector: ::core::option::Option, + /// Contract revision implemented; zero is invalid. + #[prost(uint32, tag = "8")] + pub schema_revision: u32, + /// Oldest compatible contract revision. + #[prost(uint32, tag = "9")] + pub minimum_client_revision: u32, + /// Immutable BSR module commit; unpublished builds may use a source commit. + #[prost(string, tag = "10")] + pub schema_release: ::prost::alloc::string::String, + /// Configured capacity for this deployed server. + #[prost(message, optional, tag = "11")] + pub capacity: ::core::option::Option, + /// Engine-specific server metadata with no portable field (e.g. attention + /// backend, build flags, experimental capabilities). NOT part of the portable + /// contract: clients read it opportunistically and never depend on it for + /// correctness. Carried as a Struct so JSON types survive the wire. + #[prost(message, optional, tag = "12")] + pub extra: ::core::option::Option<::prost_types::Struct>, } -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct HealthCheck { +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DeploymentCapacity { + /// Tokens per deployed KV-cache block. + #[prost(uint32, optional, tag = "1")] + pub kv_block_size: ::core::option::Option, + /// Allocatable KV blocks in the reporting scope. + #[prost(uint64, optional, tag = "2")] + pub total_kv_blocks: ::core::option::Option, + /// Concurrent running-request ceiling. + #[prost(uint64, optional, tag = "3")] + pub max_running_requests: ::core::option::Option, + /// Scheduler token ceiling per batch. + #[prost(uint64, optional, tag = "4")] + pub max_batched_tokens: ::core::option::Option, + /// Maximum simultaneously resident LoRA adapters. + #[prost(uint32, optional, tag = "5")] + pub max_loras: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ParallelismInfo { + #[prost(uint32, optional, tag = "1")] + pub tensor_parallel_size: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub pipeline_parallel_size: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub data_parallel_size: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub data_parallel_rank: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub data_parallel_start_rank: ::core::option::Option, + /// Ranks per decode-context group; at least 1. + #[prost(uint32, optional, tag = "6")] + pub decode_context_parallel_size: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetLoadRequest { + #[prost(bool, tag = "1")] + pub include_per_rank: bool, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LoadInfo { + #[prost(string, tag = "1")] + pub instance_id: ::prost::alloc::string::String, + #[prost(uint64, optional, tag = "2")] + pub timestamp_unix_nanos: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub running_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub queued_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "5")] + pub active_kv_sessions: ::core::option::Option, + #[prost(uint64, optional, tag = "6")] + pub used_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "7")] + pub total_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "8")] + pub running_tokens: ::core::option::Option, + #[prost(uint64, optional, tag = "9")] + pub waiting_tokens: ::core::option::Option, + #[prost(uint32, optional, tag = "10")] + pub prefill_batch_size: ::core::option::Option, + #[prost(uint32, optional, tag = "11")] + pub decode_batch_size: ::core::option::Option, + #[prost(message, repeated, tag = "20")] + pub ranks: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "30")] + pub attributes: ::core::option::Option<::prost_types::Struct>, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RankLoadInfo { + #[prost(uint32, optional, tag = "1")] + pub data_parallel_rank: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub running_requests: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub queued_requests: ::core::option::Option, + #[prost(uint64, optional, tag = "4")] + pub used_kv_blocks: ::core::option::Option, + #[prost(uint64, optional, tag = "5")] + pub total_kv_blocks: ::core::option::Option, + #[prost(uint32, optional, tag = "6")] + pub prefill_batch_size: ::core::option::Option, + #[prost(uint32, optional, tag = "7")] + pub decode_batch_size: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum EngineRole { + Unspecified = 0, + Aggregated = 1, + Prefill = 2, + Decode = 3, +} +impl EngineRole { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ENGINE_ROLE_UNSPECIFIED", + Self::Aggregated => "ENGINE_ROLE_AGGREGATED", + Self::Prefill => "ENGINE_ROLE_PREFILL", + Self::Decode => "ENGINE_ROLE_DECODE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ENGINE_ROLE_UNSPECIFIED" => Some(Self::Unspecified), + "ENGINE_ROLE_AGGREGATED" => Some(Self::Aggregated), + "ENGINE_ROLE_PREFILL" => Some(Self::Prefill), + "ENGINE_ROLE_DECODE" => Some(Self::Decode), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HealthRequest { + /// False means a lightweight readiness/liveness check. True asks the engine to + /// run a role-appropriate minimal inference probe and report it as a check. + #[prost(bool, tag = "1")] + pub include_inference_probe: bool, + /// Optional. Used when include_inference_probe is true. Empty means engine + /// default served model. + #[prost(string, tag = "2")] + pub model: ::prost::alloc::string::String, + /// Optional expected role for role-specific inference probes. + #[prost(enumeration = "EngineRole", tag = "3")] + pub role: i32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HealthResponse { + #[prost(enumeration = "HealthState", tag = "1")] + pub state: i32, + #[prost(message, repeated, tag = "2")] + pub checks: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HealthCheck { /// grpc, scheduler, model, kv_connector, role, inference_probe #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, @@ -839,39 +901,6 @@ pub struct AbortResponse { #[prost(string, tag = "2")] pub message: ::prost::alloc::string::String, } -#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] -pub struct DrainRequest { - #[prost(bool, tag = "1")] - pub stop_accepting_new_requests: bool, - /// Absent means no deadline; zero is immediate. - #[prost(uint32, optional, tag = "2")] - pub deadline_ms: ::core::option::Option, - #[prost(bool, tag = "3")] - pub abort_after_deadline: bool, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct DrainResponse { - #[prost(uint32, optional, tag = "2")] - pub in_flight_requests: ::core::option::Option, - #[prost(uint32, optional, tag = "3")] - pub open_kv_sessions: ::core::option::Option, - #[prost(string, tag = "4")] - pub message: ::prost::alloc::string::String, - #[prost(oneof = "drain_response::Event", tags = "1, 5")] - pub event: ::core::option::Option, -} -/// Nested message and enum types in `DrainResponse`. -pub mod drain_response { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Event { - /// Progress or successful completion. - #[prost(enumeration = "super::DrainState", tag = "1")] - State(i32), - /// Terminal failure. - #[prost(message, tag = "5")] - Error(super::EngineError), - } -} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum HealthState { @@ -879,8 +908,7 @@ pub enum HealthState { Starting = 1, Ready = 2, Degraded = 3, - Draining = 4, - NotReady = 5, + NotReady = 4, } impl HealthState { /// String value of the enum field names used in the ProtoBuf definition. @@ -893,7 +921,6 @@ impl HealthState { Self::Starting => "HEALTH_STATE_STARTING", Self::Ready => "HEALTH_STATE_READY", Self::Degraded => "HEALTH_STATE_DEGRADED", - Self::Draining => "HEALTH_STATE_DRAINING", Self::NotReady => "HEALTH_STATE_NOT_READY", } } @@ -904,7 +931,6 @@ impl HealthState { "HEALTH_STATE_STARTING" => Some(Self::Starting), "HEALTH_STATE_READY" => Some(Self::Ready), "HEALTH_STATE_DEGRADED" => Some(Self::Degraded), - "HEALTH_STATE_DRAINING" => Some(Self::Draining), "HEALTH_STATE_NOT_READY" => Some(Self::NotReady), _ => None, } @@ -939,38 +965,6 @@ impl AbortStatus { } } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum DrainState { - Unspecified = 0, - Started = 1, - InProgress = 2, - Complete = 3, -} -impl DrainState { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Unspecified => "DRAIN_STATE_UNSPECIFIED", - Self::Started => "DRAIN_STATE_STARTED", - Self::InProgress => "DRAIN_STATE_IN_PROGRESS", - Self::Complete => "DRAIN_STATE_COMPLETE", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "DRAIN_STATE_UNSPECIFIED" => Some(Self::Unspecified), - "DRAIN_STATE_STARTED" => Some(Self::Started), - "DRAIN_STATE_IN_PROGRESS" => Some(Self::InProgress), - "DRAIN_STATE_COMPLETE" => Some(Self::Complete), - _ => None, - } - } -} #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct LoraAdapter { #[prost(int64, tag = "1")] @@ -1014,7 +1008,7 @@ pub struct GetModelInfoRequest { #[prost(string, tag = "1")] pub model: ::prost::alloc::string::String, } -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ModelInfo { #[prost(string, tag = "1")] pub model_id: ::prost::alloc::string::String, @@ -1022,18 +1016,12 @@ pub struct ModelInfo { pub served_model_name: ::prost::alloc::string::String, #[prost(string, repeated, tag = "3")] pub served_model_aliases: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Effective context-window limit in this deployment. #[prost(uint32, optional, tag = "4")] pub max_context_length: ::core::option::Option, + /// Effective generated-token limit in this deployment. #[prost(uint32, optional, tag = "5")] pub max_output_tokens: ::core::option::Option, - #[prost(uint32, optional, tag = "6")] - pub kv_block_size: ::core::option::Option, - #[prost(uint64, optional, tag = "7")] - pub total_kv_blocks: ::core::option::Option, - #[prost(uint64, optional, tag = "8")] - pub max_running_requests: ::core::option::Option, - #[prost(uint64, optional, tag = "9")] - pub max_batched_tokens: ::core::option::Option, #[prost(string, repeated, tag = "10")] pub tokenizer_modes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, #[prost(bool, optional, tag = "20")] @@ -1053,6 +1041,12 @@ pub struct ModelInfo { pub reasoning_parser: ::prost::alloc::string::String, #[prost(string, tag = "26")] pub tool_call_parser: ::prost::alloc::string::String, + /// Engine-specific model metadata with no portable field (e.g. kv-cache dtype, + /// quantization, capabilities not yet standardized). NOT part of the portable + /// contract: clients read it opportunistically and never depend on it for + /// correctness. Carried as a Struct so JSON types survive the wire. + #[prost(message, optional, tag = "28")] + pub extra: ::core::option::Option<::prost_types::Struct>, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct GenerationCapabilities { @@ -1162,132 +1156,8 @@ impl GuidedDecodingMode { } } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] -pub struct GetLoadRequest { - #[prost(bool, tag = "1")] - pub include_per_rank: bool, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct LoadInfo { - #[prost(string, tag = "1")] - pub instance_id: ::prost::alloc::string::String, - #[prost(uint64, optional, tag = "2")] - pub timestamp_unix_nanos: ::core::option::Option, - #[prost(uint32, optional, tag = "3")] - pub running_requests: ::core::option::Option, - #[prost(uint32, optional, tag = "4")] - pub queued_requests: ::core::option::Option, - #[prost(uint32, optional, tag = "5")] - pub active_kv_sessions: ::core::option::Option, - #[prost(uint64, optional, tag = "6")] - pub used_kv_blocks: ::core::option::Option, - #[prost(uint64, optional, tag = "7")] - pub total_kv_blocks: ::core::option::Option, - #[prost(uint64, optional, tag = "8")] - pub running_tokens: ::core::option::Option, - #[prost(uint64, optional, tag = "9")] - pub waiting_tokens: ::core::option::Option, - #[prost(uint32, optional, tag = "10")] - pub prefill_batch_size: ::core::option::Option, - #[prost(uint32, optional, tag = "11")] - pub decode_batch_size: ::core::option::Option, - #[prost(message, repeated, tag = "20")] - pub ranks: ::prost::alloc::vec::Vec, - #[prost(map = "string, string", tag = "30")] - pub attributes: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, -} -#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] -pub struct RankLoadInfo { - #[prost(uint32, optional, tag = "1")] - pub data_parallel_rank: ::core::option::Option, - #[prost(uint32, optional, tag = "2")] - pub running_requests: ::core::option::Option, - #[prost(uint32, optional, tag = "3")] - pub queued_requests: ::core::option::Option, - #[prost(uint64, optional, tag = "4")] - pub used_kv_blocks: ::core::option::Option, - #[prost(uint64, optional, tag = "5")] - pub total_kv_blocks: ::core::option::Option, - #[prost(uint32, optional, tag = "6")] - pub prefill_batch_size: ::core::option::Option, - #[prost(uint32, optional, tag = "7")] - pub decode_batch_size: ::core::option::Option, -} -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct SubscribeRuntimeEventsRequest { - #[prost(enumeration = "RuntimeEventType", repeated, tag = "1")] - pub types: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SubscribeRuntimeEventsResponse { - #[prost(oneof = "subscribe_runtime_events_response::Event", tags = "1, 2")] - pub event: ::core::option::Option, -} -/// Nested message and enum types in `SubscribeRuntimeEventsResponse`. -pub mod subscribe_runtime_events_response { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Event { - #[prost(message, tag = "1")] - RuntimeEvent(super::RuntimeEvent), - /// Terminal. - #[prost(message, tag = "2")] - Error(super::EngineError), - } -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RuntimeEvent { - #[prost(string, tag = "1")] - pub event_id: ::prost::alloc::string::String, - #[prost(uint64, tag = "2")] - pub timestamp_unix_nanos: u64, - #[prost(enumeration = "RuntimeEventType", tag = "3")] - pub r#type: i32, - #[prost(map = "string, string", tag = "4")] - pub attributes: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum RuntimeEventType { - Unspecified = 0, - ForwardPass = 1, - Batch = 2, - Queue = 3, - Transfer = 4, -} -impl RuntimeEventType { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Unspecified => "RUNTIME_EVENT_TYPE_UNSPECIFIED", - Self::ForwardPass => "RUNTIME_EVENT_TYPE_FORWARD_PASS", - Self::Batch => "RUNTIME_EVENT_TYPE_BATCH", - Self::Queue => "RUNTIME_EVENT_TYPE_QUEUE", - Self::Transfer => "RUNTIME_EVENT_TYPE_TRANSFER", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "RUNTIME_EVENT_TYPE_UNSPECIFIED" => Some(Self::Unspecified), - "RUNTIME_EVENT_TYPE_FORWARD_PASS" => Some(Self::ForwardPass), - "RUNTIME_EVENT_TYPE_BATCH" => Some(Self::Batch), - "RUNTIME_EVENT_TYPE_QUEUE" => Some(Self::Queue), - "RUNTIME_EVENT_TYPE_TRANSFER" => Some(Self::Transfer), - _ => None, - } - } -} /// Generated client implementations. -pub mod open_engine_client { +pub mod inference_client { #![allow( unused_variables, dead_code, @@ -1298,10 +1168,10 @@ pub mod open_engine_client { use tonic::codegen::*; use tonic::codegen::http::Uri; #[derive(Debug, Clone)] - pub struct OpenEngineClient { + pub struct InferenceClient { inner: tonic::client::Grpc, } - impl OpenEngineClient { + impl InferenceClient { /// Attempt to create a new client by connecting to a given endpoint. pub async fn connect(dst: D) -> Result where @@ -1312,7 +1182,7 @@ pub mod open_engine_client { Ok(Self::new(conn)) } } - impl OpenEngineClient + impl InferenceClient where T: tonic::client::GrpcService, T::Error: Into, @@ -1330,7 +1200,7 @@ pub mod open_engine_client { pub fn with_interceptor( inner: T, interceptor: F, - ) -> OpenEngineClient> + ) -> InferenceClient> where F: tonic::service::Interceptor, T::ResponseBody: Default, @@ -1344,7 +1214,7 @@ pub mod open_engine_client { http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { - OpenEngineClient::new(InterceptedService::new(inner, interceptor)) + InferenceClient::new(InterceptedService::new(inner, interceptor)) } /// Compress requests with the given encoding. /// @@ -1395,18 +1265,298 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/Generate", + "/openengine.v1.Inference/Generate", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Generate")); + .insert(GrpcMethod::new("openengine.v1.Inference", "Generate")); self.inner.server_streaming(req, path, codec).await } + } +} +/// Generated server implementations. +pub mod inference_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with InferenceServer. + #[async_trait] + pub trait Inference: std::marker::Send + std::marker::Sync + 'static { + /// Server streaming response type for the Generate method. + type GenerateStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + std::marker::Send + + 'static; + /// Core inference path. + async fn generate( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + } + #[derive(Debug)] + pub struct InferenceServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl InferenceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for InferenceServer + where + T: Inference, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/openengine.v1.Inference/Generate" => { + #[allow(non_camel_case_types)] + struct GenerateSvc(pub Arc); + impl< + T: Inference, + > tonic::server::ServerStreamingService + for GenerateSvc { + type Response = super::GenerateResponse; + type ResponseStream = T::GenerateStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::generate(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GenerateSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + let mut response = http::Response::new( + tonic::body::Body::default(), + ); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } + } + } + } + impl Clone for InferenceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "openengine.v1.Inference"; + impl tonic::server::NamedService for InferenceServer { + const NAME: &'static str = SERVICE_NAME; + } +} +/// Generated client implementations. +pub mod control_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ControlClient { + inner: tonic::client::Grpc, + } + impl ControlClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl ControlClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ControlClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + ControlClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } /// Runtime metadata and scheduling state. - pub async fn get_engine_info( + pub async fn get_server_info( &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { self.inner .ready() .await @@ -1417,11 +1567,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/GetEngineInfo", + "/openengine.v1.Control/GetServerInfo", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "GetEngineInfo")); + .insert(GrpcMethod::new("openengine.v1.Control", "GetServerInfo")); self.inner.unary(req, path, codec).await } pub async fn get_model_info( @@ -1438,11 +1588,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/GetModelInfo", + "/openengine.v1.Control/GetModelInfo", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "GetModelInfo")); + .insert(GrpcMethod::new("openengine.v1.Control", "GetModelInfo")); self.inner.unary(req, path, codec).await } pub async fn get_load( @@ -1459,11 +1609,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/GetLoad", + "/openengine.v1.Control/GetLoad", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "GetLoad")); + .insert(GrpcMethod::new("openengine.v1.Control", "GetLoad")); self.inner.unary(req, path, codec).await } /// Health and lifecycle. @@ -1481,11 +1631,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/Health", + "/openengine.v1.Control/Health", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Health")); + .insert(GrpcMethod::new("openengine.v1.Control", "Health")); self.inner.unary(req, path, codec).await } pub async fn abort( @@ -1502,37 +1652,13 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/Abort", + "/openengine.v1.Control/Abort", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Abort")); + .insert(GrpcMethod::new("openengine.v1.Control", "Abort")); self.inner.unary(req, path, codec).await } - pub async fn drain( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response>, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic_prost::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/Drain", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "Drain")); - self.inner.server_streaming(req, path, codec).await - } /// LoRA lifecycle. pub async fn load_lora( &mut self, @@ -1551,11 +1677,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/LoadLora", + "/openengine.v1.Control/LoadLora", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "LoadLora")); + .insert(GrpcMethod::new("openengine.v1.Control", "LoadLora")); self.inner.unary(req, path, codec).await } pub async fn unload_lora( @@ -1575,11 +1701,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/UnloadLora", + "/openengine.v1.Control/UnloadLora", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "UnloadLora")); + .insert(GrpcMethod::new("openengine.v1.Control", "UnloadLora")); self.inner.unary(req, path, codec).await } pub async fn list_loras( @@ -1599,40 +1725,14 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/ListLoras", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("openengine.v1.OpenEngine", "ListLoras")); - self.inner.unary(req, path, codec).await - } - /// Disaggregated serving / KV transfer. - pub async fn get_kv_connector_info( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic_prost::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/GetKvConnectorInfo", + "/openengine.v1.Control/ListLoras", ); let mut req = request.into_request(); req.extensions_mut() - .insert( - GrpcMethod::new("openengine.v1.OpenEngine", "GetKvConnectorInfo"), - ); + .insert(GrpcMethod::new("openengine.v1.Control", "ListLoras")); self.inner.unary(req, path, codec).await } + /// Disaggregated serving / KV transfer. Connector info: ServerInfo.kv_connector. pub async fn get_kv_event_sources( &mut self, request: impl tonic::IntoRequest, @@ -1650,13 +1750,11 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/GetKvEventSources", + "/openengine.v1.Control/GetKvEventSources", ); let mut req = request.into_request(); req.extensions_mut() - .insert( - GrpcMethod::new("openengine.v1.OpenEngine", "GetKvEventSources"), - ); + .insert(GrpcMethod::new("openengine.v1.Control", "GetKvEventSources")); self.inner.unary(req, path, codec).await } pub async fn subscribe_kv_events( @@ -1676,48 +1774,17 @@ pub mod open_engine_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/SubscribeKvEvents", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("openengine.v1.OpenEngine", "SubscribeKvEvents"), - ); - self.inner.server_streaming(req, path, codec).await - } - /// Structured runtime events for planners/controllers. - pub async fn subscribe_runtime_events( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response< - tonic::codec::Streaming, - >, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic_prost::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/openengine.v1.OpenEngine/SubscribeRuntimeEvents", + "/openengine.v1.Control/SubscribeKvEvents", ); let mut req = request.into_request(); req.extensions_mut() - .insert( - GrpcMethod::new("openengine.v1.OpenEngine", "SubscribeRuntimeEvents"), - ); + .insert(GrpcMethod::new("openengine.v1.Control", "SubscribeKvEvents")); self.inner.server_streaming(req, path, codec).await } } } /// Generated server implementations. -pub mod open_engine_server { +pub mod control_server { #![allow( unused_variables, dead_code, @@ -1726,25 +1793,14 @@ pub mod open_engine_server { clippy::let_unit_value, )] use tonic::codegen::*; - /// Generated trait containing gRPC methods that should be implemented for use with OpenEngineServer. + /// Generated trait containing gRPC methods that should be implemented for use with ControlServer. #[async_trait] - pub trait OpenEngine: std::marker::Send + std::marker::Sync + 'static { - /// Server streaming response type for the Generate method. - type GenerateStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result, - > - + std::marker::Send - + 'static; - /// Core inference path. - async fn generate( - &self, - request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + pub trait Control: std::marker::Send + std::marker::Sync + 'static { /// Runtime metadata and scheduling state. - async fn get_engine_info( + async fn get_server_info( &self, - request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; async fn get_model_info( &self, request: tonic::Request, @@ -1762,16 +1818,6 @@ pub mod open_engine_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; - /// Server streaming response type for the Drain method. - type DrainStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result, - > - + std::marker::Send - + 'static; - async fn drain( - &self, - request: tonic::Request, - ) -> std::result::Result, tonic::Status>; /// LoRA lifecycle. async fn load_lora( &self, @@ -1794,11 +1840,7 @@ pub mod open_engine_server { tonic::Response, tonic::Status, >; - /// Disaggregated serving / KV transfer. - async fn get_kv_connector_info( - &self, - request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + /// Disaggregated serving / KV transfer. Connector info: ServerInfo.kv_connector. async fn get_kv_event_sources( &self, request: tonic::Request, @@ -1822,33 +1864,16 @@ pub mod open_engine_server { tonic::Response, tonic::Status, >; - /// Server streaming response type for the SubscribeRuntimeEvents method. - type SubscribeRuntimeEventsStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result< - super::SubscribeRuntimeEventsResponse, - tonic::Status, - >, - > - + std::marker::Send - + 'static; - /// Structured runtime events for planners/controllers. - async fn subscribe_runtime_events( - &self, - request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; } #[derive(Debug)] - pub struct OpenEngineServer { + pub struct ControlServer { inner: Arc, accept_compression_encodings: EnabledCompressionEncodings, send_compression_encodings: EnabledCompressionEncodings, max_decoding_message_size: Option, max_encoding_message_size: Option, } - impl OpenEngineServer { + impl ControlServer { pub fn new(inner: T) -> Self { Self::from_arc(Arc::new(inner)) } @@ -1899,9 +1924,9 @@ pub mod open_engine_server { self } } - impl tonic::codegen::Service> for OpenEngineServer + impl tonic::codegen::Service> for ControlServer where - T: OpenEngine, + T: Control, B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { @@ -1916,71 +1941,25 @@ pub mod open_engine_server { } fn call(&mut self, req: http::Request) -> Self::Future { match req.uri().path() { - "/openengine.v1.OpenEngine/Generate" => { - #[allow(non_camel_case_types)] - struct GenerateSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::ServerStreamingService - for GenerateSvc { - type Response = super::GenerateResponse; - type ResponseStream = T::GenerateStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { - let inner = Arc::clone(&self.0); - let fut = async move { - ::generate(&inner, request).await - }; - Box::pin(fut) - } - } - let accept_compression_encodings = self.accept_compression_encodings; - let send_compression_encodings = self.send_compression_encodings; - let max_decoding_message_size = self.max_decoding_message_size; - let max_encoding_message_size = self.max_encoding_message_size; - let inner = self.inner.clone(); - let fut = async move { - let method = GenerateSvc(inner); - let codec = tonic_prost::ProstCodec::default(); - let mut grpc = tonic::server::Grpc::new(codec) - .apply_compression_config( - accept_compression_encodings, - send_compression_encodings, - ) - .apply_max_message_size_config( - max_decoding_message_size, - max_encoding_message_size, - ); - let res = grpc.server_streaming(method, req).await; - Ok(res) - }; - Box::pin(fut) - } - "/openengine.v1.OpenEngine/GetEngineInfo" => { + "/openengine.v1.Control/GetServerInfo" => { #[allow(non_camel_case_types)] - struct GetEngineInfoSvc(pub Arc); + struct GetServerInfoSvc(pub Arc); impl< - T: OpenEngine, - > tonic::server::UnaryService - for GetEngineInfoSvc { - type Response = super::EngineInfo; + T: Control, + > tonic::server::UnaryService + for GetServerInfoSvc { + type Response = super::ServerInfo; type Future = BoxFuture< tonic::Response, tonic::Status, >; fn call( &mut self, - request: tonic::Request, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_engine_info(&inner, request).await + ::get_server_info(&inner, request).await }; Box::pin(fut) } @@ -1991,7 +1970,7 @@ pub mod open_engine_server { let max_encoding_message_size = self.max_encoding_message_size; let inner = self.inner.clone(); let fut = async move { - let method = GetEngineInfoSvc(inner); + let method = GetServerInfoSvc(inner); let codec = tonic_prost::ProstCodec::default(); let mut grpc = tonic::server::Grpc::new(codec) .apply_compression_config( @@ -2007,11 +1986,11 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/GetModelInfo" => { + "/openengine.v1.Control/GetModelInfo" => { #[allow(non_camel_case_types)] - struct GetModelInfoSvc(pub Arc); + struct GetModelInfoSvc(pub Arc); impl< - T: OpenEngine, + T: Control, > tonic::server::UnaryService for GetModelInfoSvc { type Response = super::ModelInfo; @@ -2025,7 +2004,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_model_info(&inner, request).await + ::get_model_info(&inner, request).await }; Box::pin(fut) } @@ -2052,12 +2031,10 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/GetLoad" => { + "/openengine.v1.Control/GetLoad" => { #[allow(non_camel_case_types)] - struct GetLoadSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::UnaryService + struct GetLoadSvc(pub Arc); + impl tonic::server::UnaryService for GetLoadSvc { type Response = super::LoadInfo; type Future = BoxFuture< @@ -2070,7 +2047,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_load(&inner, request).await + ::get_load(&inner, request).await }; Box::pin(fut) } @@ -2097,10 +2074,10 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/Health" => { + "/openengine.v1.Control/Health" => { #[allow(non_camel_case_types)] - struct HealthSvc(pub Arc); - impl tonic::server::UnaryService + struct HealthSvc(pub Arc); + impl tonic::server::UnaryService for HealthSvc { type Response = super::HealthResponse; type Future = BoxFuture< @@ -2113,7 +2090,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::health(&inner, request).await + ::health(&inner, request).await }; Box::pin(fut) } @@ -2140,10 +2117,10 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/Abort" => { + "/openengine.v1.Control/Abort" => { #[allow(non_camel_case_types)] - struct AbortSvc(pub Arc); - impl tonic::server::UnaryService + struct AbortSvc(pub Arc); + impl tonic::server::UnaryService for AbortSvc { type Response = super::AbortResponse; type Future = BoxFuture< @@ -2156,7 +2133,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::abort(&inner, request).await + ::abort(&inner, request).await }; Box::pin(fut) } @@ -2183,58 +2160,10 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/Drain" => { - #[allow(non_camel_case_types)] - struct DrainSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::ServerStreamingService - for DrainSvc { - type Response = super::DrainResponse; - type ResponseStream = T::DrainStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { - let inner = Arc::clone(&self.0); - let fut = async move { - ::drain(&inner, request).await - }; - Box::pin(fut) - } - } - let accept_compression_encodings = self.accept_compression_encodings; - let send_compression_encodings = self.send_compression_encodings; - let max_decoding_message_size = self.max_decoding_message_size; - let max_encoding_message_size = self.max_encoding_message_size; - let inner = self.inner.clone(); - let fut = async move { - let method = DrainSvc(inner); - let codec = tonic_prost::ProstCodec::default(); - let mut grpc = tonic::server::Grpc::new(codec) - .apply_compression_config( - accept_compression_encodings, - send_compression_encodings, - ) - .apply_max_message_size_config( - max_decoding_message_size, - max_encoding_message_size, - ); - let res = grpc.server_streaming(method, req).await; - Ok(res) - }; - Box::pin(fut) - } - "/openengine.v1.OpenEngine/LoadLora" => { + "/openengine.v1.Control/LoadLora" => { #[allow(non_camel_case_types)] - struct LoadLoraSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::UnaryService + struct LoadLoraSvc(pub Arc); + impl tonic::server::UnaryService for LoadLoraSvc { type Response = super::LoadLoraResponse; type Future = BoxFuture< @@ -2247,7 +2176,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::load_lora(&inner, request).await + ::load_lora(&inner, request).await }; Box::pin(fut) } @@ -2274,11 +2203,11 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/UnloadLora" => { + "/openengine.v1.Control/UnloadLora" => { #[allow(non_camel_case_types)] - struct UnloadLoraSvc(pub Arc); + struct UnloadLoraSvc(pub Arc); impl< - T: OpenEngine, + T: Control, > tonic::server::UnaryService for UnloadLoraSvc { type Response = super::UnloadLoraResponse; @@ -2292,7 +2221,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::unload_lora(&inner, request).await + ::unload_lora(&inner, request).await }; Box::pin(fut) } @@ -2319,12 +2248,10 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/ListLoras" => { + "/openengine.v1.Control/ListLoras" => { #[allow(non_camel_case_types)] - struct ListLorasSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::UnaryService + struct ListLorasSvc(pub Arc); + impl tonic::server::UnaryService for ListLorasSvc { type Response = super::ListLorasResponse; type Future = BoxFuture< @@ -2337,7 +2264,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::list_loras(&inner, request).await + ::list_loras(&inner, request).await }; Box::pin(fut) } @@ -2364,57 +2291,11 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/GetKvConnectorInfo" => { - #[allow(non_camel_case_types)] - struct GetKvConnectorInfoSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::UnaryService - for GetKvConnectorInfoSvc { - type Response = super::KvConnectorInfo; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { - let inner = Arc::clone(&self.0); - let fut = async move { - ::get_kv_connector_info(&inner, request) - .await - }; - Box::pin(fut) - } - } - let accept_compression_encodings = self.accept_compression_encodings; - let send_compression_encodings = self.send_compression_encodings; - let max_decoding_message_size = self.max_decoding_message_size; - let max_encoding_message_size = self.max_encoding_message_size; - let inner = self.inner.clone(); - let fut = async move { - let method = GetKvConnectorInfoSvc(inner); - let codec = tonic_prost::ProstCodec::default(); - let mut grpc = tonic::server::Grpc::new(codec) - .apply_compression_config( - accept_compression_encodings, - send_compression_encodings, - ) - .apply_max_message_size_config( - max_decoding_message_size, - max_encoding_message_size, - ); - let res = grpc.unary(method, req).await; - Ok(res) - }; - Box::pin(fut) - } - "/openengine.v1.OpenEngine/GetKvEventSources" => { + "/openengine.v1.Control/GetKvEventSources" => { #[allow(non_camel_case_types)] - struct GetKvEventSourcesSvc(pub Arc); + struct GetKvEventSourcesSvc(pub Arc); impl< - T: OpenEngine, + T: Control, > tonic::server::UnaryService for GetKvEventSourcesSvc { type Response = super::GetKvEventSourcesResponse; @@ -2428,8 +2309,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_kv_event_sources(&inner, request) - .await + ::get_kv_event_sources(&inner, request).await }; Box::pin(fut) } @@ -2456,11 +2336,11 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/SubscribeKvEvents" => { + "/openengine.v1.Control/SubscribeKvEvents" => { #[allow(non_camel_case_types)] - struct SubscribeKvEventsSvc(pub Arc); + struct SubscribeKvEventsSvc(pub Arc); impl< - T: OpenEngine, + T: Control, > tonic::server::ServerStreamingService< super::SubscribeKvEventsRequest, > for SubscribeKvEventsSvc { @@ -2476,8 +2356,7 @@ pub mod open_engine_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::subscribe_kv_events(&inner, request) - .await + ::subscribe_kv_events(&inner, request).await }; Box::pin(fut) } @@ -2504,54 +2383,6 @@ pub mod open_engine_server { }; Box::pin(fut) } - "/openengine.v1.OpenEngine/SubscribeRuntimeEvents" => { - #[allow(non_camel_case_types)] - struct SubscribeRuntimeEventsSvc(pub Arc); - impl< - T: OpenEngine, - > tonic::server::ServerStreamingService< - super::SubscribeRuntimeEventsRequest, - > for SubscribeRuntimeEventsSvc { - type Response = super::SubscribeRuntimeEventsResponse; - type ResponseStream = T::SubscribeRuntimeEventsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { - let inner = Arc::clone(&self.0); - let fut = async move { - ::subscribe_runtime_events(&inner, request) - .await - }; - Box::pin(fut) - } - } - let accept_compression_encodings = self.accept_compression_encodings; - let send_compression_encodings = self.send_compression_encodings; - let max_decoding_message_size = self.max_decoding_message_size; - let max_encoding_message_size = self.max_encoding_message_size; - let inner = self.inner.clone(); - let fut = async move { - let method = SubscribeRuntimeEventsSvc(inner); - let codec = tonic_prost::ProstCodec::default(); - let mut grpc = tonic::server::Grpc::new(codec) - .apply_compression_config( - accept_compression_encodings, - send_compression_encodings, - ) - .apply_max_message_size_config( - max_decoding_message_size, - max_encoding_message_size, - ); - let res = grpc.server_streaming(method, req).await; - Ok(res) - }; - Box::pin(fut) - } _ => { Box::pin(async move { let mut response = http::Response::new( @@ -2574,7 +2405,7 @@ pub mod open_engine_server { } } } - impl Clone for OpenEngineServer { + impl Clone for ControlServer { fn clone(&self) -> Self { let inner = self.inner.clone(); Self { @@ -2587,8 +2418,8 @@ pub mod open_engine_server { } } /// Generated gRPC service name - pub const SERVICE_NAME: &str = "openengine.v1.OpenEngine"; - impl tonic::server::NamedService for OpenEngineServer { + pub const SERVICE_NAME: &str = "openengine.v1.Control"; + impl tonic::server::NamedService for ControlServer { const NAME: &'static str = SERVICE_NAME; } } diff --git a/packages/rust/openengine-proto/src/generated/openengine_descriptor.bin b/packages/rust/openengine/src/generated/openengine_descriptor.bin similarity index 50% rename from packages/rust/openengine-proto/src/generated/openengine_descriptor.bin rename to packages/rust/openengine/src/generated/openengine_descriptor.bin index f99bc0e71a92e9465b69d4cb8a317f7e98da9a1e..03b85f6f3acf8a9e6967295102dee2988bf790d9 100644 GIT binary patch literal 49440 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 literal 51923 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 exit 1 fi diff --git a/scripts/check-release-version.sh b/scripts/check-release-version.sh new file mode 100755 index 0000000..450fd8c --- /dev/null +++ b/scripts/check-release-version.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -ne 1 || ! $1 =~ ^openengine-v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + echo "usage: $0 openengine-vMAJOR.MINOR.PATCH" >&2 + exit 2 +fi + +repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +tag_version=${BASH_REMATCH[1]} +crate_version=$( + cargo metadata \ + --manifest-path "${repository}/Cargo.toml" \ + --no-deps \ + --format-version 1 \ + | jq --raw-output '.packages[] | select(.name == "openengine") | .version' +) + +if [[ -z ${crate_version} || ${crate_version} != "${tag_version}" ]]; then + echo "release tag: ${tag_version}" >&2 + echo "Rust crate: ${crate_version:-not found}" >&2 + exit 1 +fi + +echo "OpenEngine crate release version matches: ${tag_version}" diff --git a/scripts/check_release_version.py b/scripts/check_release_version.py deleted file mode 100755 index 94a506a..0000000 --- a/scripts/check_release_version.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 -"""Verify that a release tag matches every published package version.""" - -from __future__ import annotations - -import re -import sys -import tomllib -from pathlib import Path - - -def read_toml(path: Path) -> dict: - with path.open("rb") as source: - return tomllib.load(source) - - -def main() -> int: - if len(sys.argv) != 2 or not re.fullmatch(r"v[0-9]+\.[0-9]+\.[0-9]+", sys.argv[1]): - print("usage: check_release_version.py vMAJOR.MINOR.PATCH", file=sys.stderr) - return 2 - - repository = Path(__file__).resolve().parent.parent - tag_version = sys.argv[1].removeprefix("v") - python_version = read_toml(repository / "packages/python/pyproject.toml")["project"]["version"] - rust_version = read_toml(repository / "Cargo.toml")["workspace"]["package"]["version"] - - versions = { - "release tag": tag_version, - "Python package": python_version, - "Rust crate": rust_version, - } - if len(set(versions.values())) != 1: - for label, version in versions.items(): - print(f"{label}: {version}", file=sys.stderr) - return 1 - - print(f"OpenEngine release versions match: {tag_version}") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/scripts/cross_language_fixture.py b/scripts/cross_language_fixture.py deleted file mode 100755 index 2e51898..0000000 --- a/scripts/cross_language_fixture.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 -"""Encode or verify the shared Python/Rust wire fixture.""" - -from __future__ import annotations - -import sys -from pathlib import Path - -from openengine.v1.generation_pb2 import GenerateRequest - - -def fixture() -> GenerateRequest: - return GenerateRequest( - request_id="cross-language", - model="test-model", - prompt="Hello", - priority=0, - ) - - -def main() -> int: - if len(sys.argv) != 3 or sys.argv[1] not in {"encode", "decode"}: - print("usage: cross_language_fixture.py (encode|decode) PATH", file=sys.stderr) - return 2 - - operation, raw_path = sys.argv[1:] - path = Path(raw_path) - if operation == "encode": - path.write_bytes(fixture().SerializeToString()) - return 0 - - decoded = GenerateRequest.FromString(path.read_bytes()) - if decoded != fixture(): - print("decoded Rust fixture does not match the Python fixture", file=sys.stderr) - return 1 - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/scripts/generate-python.sh b/scripts/generate-python.sh deleted file mode 100755 index 6986245..0000000 --- a/scripts/generate-python.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) -python=${PYTHON:-python3} -output="${repository}/packages/python/src" -export LC_ALL=C - -if ! "${python}" -c "import grpc_tools.protoc" 2>/dev/null; then - echo "grpcio-tools is required; install grpcio-tools==1.81.1" >&2 - exit 1 -fi - -protos=("${repository}"/proto/openengine/v1/*.proto) - -for generated in \ - "${output}"/openengine/v1/*_pb2.py \ - "${output}"/openengine/v1/*_pb2.pyi \ - "${output}"/openengine/v1/*_pb2_grpc.py; do - if [[ -e "${generated}" ]]; then - rm -- "${generated}" - fi -done - -"${python}" -m grpc_tools.protoc \ - -I "${repository}/proto" \ - --python_out="${output}" \ - --pyi_out="${output}" \ - "${protos[@]}" - -"${python}" -m grpc_tools.protoc \ - -I "${repository}/proto" \ - --grpc_python_out="${output}" \ - "${repository}/proto/openengine/v1/openengine.proto" diff --git a/scripts/test-cross-language.sh b/scripts/test-cross-language.sh deleted file mode 100755 index 5269f56..0000000 --- a/scripts/test-cross-language.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) -temporary_directory=$(mktemp -d) -python=${PYTHON:-python3} -trap 'rm -rf "${temporary_directory}"' EXIT - -export PYTHONPATH="${repository}/packages/python/src${PYTHONPATH:+:${PYTHONPATH}}" - -"${python}" "${repository}/scripts/cross_language_fixture.py" \ - encode "${temporary_directory}/python.bin" -cargo run --quiet \ - --manifest-path "${repository}/Cargo.toml" \ - --package openengine-proto \ - --example cross_language_fixture \ - -- decode "${temporary_directory}/python.bin" - -cargo run --quiet \ - --manifest-path "${repository}/Cargo.toml" \ - --package openengine-proto \ - --example cross_language_fixture \ - -- encode "${temporary_directory}/rust.bin" -"${python}" "${repository}/scripts/cross_language_fixture.py" \ - decode "${temporary_directory}/rust.bin" diff --git a/tools/rust-codegen/src/main.rs b/tools/rust-codegen/src/main.rs index 665b664..b82e398 100644 --- a/tools/rust-codegen/src/main.rs +++ b/tools/rust-codegen/src/main.rs @@ -10,7 +10,7 @@ fn main() -> Result<(), Box> { .unwrap_or(env::current_dir()?); let proto_root = repository.join("proto"); let package_root = proto_root.join("openengine/v1"); - let output = repository.join("packages/rust/openengine-proto/src/generated"); + let output = repository.join("packages/rust/openengine/src/generated"); fs::create_dir_all(&output)?; From 844470361bf45cf0f0819c2913ba5c87ba1e4dfa Mon Sep 17 00:00:00 2001 From: Connor Carpenter Date: Thu, 3 Sep 2026 13:04:10 -0700 Subject: [PATCH 4/6] ci(rust): use allowlisted toolchain action Signed-off-by: Connor Carpenter --- .github/workflows/rust-release.yml | 4 ++-- .github/workflows/rust.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index 853d383..46ffb9b 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -30,7 +30,7 @@ jobs: fi - name: Set up Rust - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + uses: dtolnay/rust-toolchain@master with: toolchain: stable @@ -85,7 +85,7 @@ jobs: uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 - name: Set up Rust - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + uses: dtolnay/rust-toolchain@master with: toolchain: stable diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 14a037a..cdc1f42 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -40,7 +40,7 @@ jobs: uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 - name: Set up Rust - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + uses: dtolnay/rust-toolchain@master with: toolchain: stable @@ -59,7 +59,7 @@ jobs: uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 - name: Set up Rust - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.toolchain }} @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 - name: Set up Rust - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 + uses: dtolnay/rust-toolchain@master with: toolchain: stable components: clippy,rustfmt From a7eb9df8a07738afcc9f5741eea5ae351b393673 Mon Sep 17 00:00:00 2001 From: Connor Carpenter Date: Thu, 3 Sep 2026 16:26:02 -0700 Subject: [PATCH 5/6] fix(rust): harden crate release workflow Signed-off-by: Connor Carpenter --- .github/workflows/rust-release.yml | 17 +++++++++-------- RELEASING.md | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index 46ffb9b..58f7018 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -8,6 +8,9 @@ on: permissions: contents: read +env: + RUSTUP_TOOLCHAIN: "1.98.1" + jobs: validate: name: Validate release @@ -30,9 +33,7 @@ jobs: fi - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable + run: rustup toolchain install "${RUSTUP_TOOLCHAIN}" --profile minimal --no-self-update - name: Check release version run: ./scripts/check-release-version.sh "${GITHUB_REF_NAME}" @@ -51,10 +52,12 @@ jobs: run: | version="${VERSION#openengine-v}" url="https://crates.io/api/v1/crates/openengine/${version}" - status="$(curl --silent --output /dev/null --write-out '%{http_code}' "${url}")" + user_agent="openengine-release (+https://github.com/ai-dynamo/openengine)" + response="${RUNNER_TEMP}/openengine-${version}.json" + status="$(curl --silent --show-error --user-agent "${user_agent}" --output "${response}" --write-out '%{http_code}' "${url}")" case "${status}" in 200) - remote_checksum="$(curl --fail --silent --show-error "${url}" | jq --raw-output '.version.checksum')" + remote_checksum="$(jq --raw-output '.version.checksum' "${response}")" local_checksum="$(sha256sum "target/package/openengine-${version}.crate" | cut --delimiter=' ' --fields=1)" if [[ "${local_checksum}" != "${remote_checksum}" ]]; then echo "::error::crates.io already has openengine ${version} with different contents" @@ -85,9 +88,7 @@ jobs: uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 - name: Set up Rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable + run: rustup toolchain install "${RUSTUP_TOOLCHAIN}" --profile minimal --no-self-update - name: Authenticate with crates.io id: auth diff --git a/RELEASING.md b/RELEASING.md index fe5910b..bf89e92 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -69,7 +69,7 @@ The crate must exist before crates.io allows a Trusted Publisher to be configure 1. Create the `release` GitHub environment and protect it with the desired approval policy. 2. Prepare and merge the crate release commit using the process below. 3. Create the signed `openengine-vMAJOR.MINOR.PATCH` tag locally, but do not push it yet. -4. Create a short-lived crates.io token authorized to publish a new crate, publish from the tagged commit with `CARGO_REGISTRY_TOKEN=... cargo publish --locked --package openengine`, and immediately revoke the token. +4. Create a short-lived crates.io token authorized to publish a new crate, install the release workflow's pinned Rust toolchain with `rustup toolchain install 1.98.1 --profile minimal`, publish from the tagged commit with `CARGO_REGISTRY_TOKEN=... cargo +1.98.1 publish --locked --package openengine`, and immediately revoke the token. 5. Add the project maintainers or an `ai-dynamo` GitHub team as crate owners. 6. Configure a crates.io Trusted Publisher for GitHub owner `ai-dynamo`, repository `openengine`, workflow `rust-release.yml`, and environment `release`. 7. Push the signed tag. The workflow verifies that the existing crates.io archive matches the tagged source and skips a duplicate publication. From 1008955af27d621dd77d20feeebbe831b8182a21 Mon Sep 17 00:00:00 2001 From: tanmayv25 Date: Wed, 16 Sep 2026 12:57:01 -0700 Subject: [PATCH 6/6] fix(rust): validate packaged schema identity Signed-off-by: tanmayv25 --- .github/workflows/rust-release.yml | 3 + .github/workflows/rust.yml | 7 ++ CONTRIBUTING.md | 1 + Cargo.lock | 31 +++++++ RELEASING.md | 3 +- packages/rust/openengine/README.md | 2 +- packages/rust/openengine/schema-release.json | 7 ++ .../rust/openengine/src/generated/schema.rs | 7 ++ packages/rust/openengine/src/lib.rs | 6 +- scripts/check-schema-release.sh | 93 +++++++++++++++++++ tools/rust-codegen/Cargo.toml | 2 + tools/rust-codegen/src/main.rs | 53 +++++++++++ 12 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 packages/rust/openengine/schema-release.json create mode 100644 packages/rust/openengine/src/generated/schema.rs create mode 100755 scripts/check-schema-release.sh diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index 58f7018..1b3083a 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -38,6 +38,9 @@ jobs: - name: Check release version run: ./scripts/check-release-version.sh "${GITHUB_REF_NAME}" + - name: Check schema release metadata + run: ./scripts/check-schema-release.sh --verify-registry + - name: Check generated bindings run: ./scripts/check-generated.sh diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index cdc1f42..559c6e4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,6 +10,7 @@ on: - "tools/rust-codegen/**" - "scripts/check-generated.sh" - "scripts/check-release-version.sh" + - "scripts/check-schema-release.sh" - "scripts/generate-rust.sh" - "Cargo.toml" - "Cargo.lock" @@ -22,6 +23,7 @@ on: - "tools/rust-codegen/**" - "scripts/check-generated.sh" - "scripts/check-release-version.sh" + - "scripts/check-schema-release.sh" - "scripts/generate-rust.sh" - "Cargo.toml" - "Cargo.lock" @@ -38,12 +40,17 @@ jobs: steps: - name: Check out repository uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2 + with: + fetch-depth: 0 - name: Set up Rust uses: dtolnay/rust-toolchain@master with: toolchain: stable + - name: Check schema release metadata + run: ./scripts/check-schema-release.sh + - name: Check generated bindings run: ./scripts/check-generated.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae2dc0f..9773008 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,7 @@ buf lint ./scripts/generate-rust.sh ./scripts/check-generated.sh +./scripts/check-schema-release.sh cargo check --locked --workspace --all-targets cargo clippy --locked --workspace --all-targets -- -D warnings diff --git a/Cargo.lock b/Cargo.lock index e30c5d8..f7ea283 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,6 +436,8 @@ name = "openengine-rust-codegen" version = "0.0.0" dependencies = [ "protoc-bin-vendored", + "serde", + "serde_json", "tonic-prost-build", ] @@ -695,6 +697,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -715,6 +727,19 @@ dependencies = [ "syn 3.0.4", ] +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + [[package]] name = "slab" version = "0.4.12" @@ -1006,3 +1031,9 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/RELEASING.md b/RELEASING.md index bf89e92..a50cb46 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -79,12 +79,13 @@ Subsequent releases use crates.io Trusted Publishing and do not require a stored ### Prepare a crate release 1. Identify the published schema release for the bindings. If the schema changed, publish and verify it through the BSR process above first. -2. Update the workspace package version in `Cargo.toml` and set `SCHEMA_RELEASE` in `packages/rust/openengine/src/lib.rs` to the immutable BSR module commit. +2. Update the workspace package version in `Cargo.toml` and the crate version, schema revision, immutable BSR module commit, Git tag, and Git commit in `packages/rust/openengine/schema-release.json`. Update the pinned schema link in `packages/rust/openengine/README.md`. 3. Regenerate and validate the package: ```bash ./scripts/generate-rust.sh ./scripts/check-generated.sh + ./scripts/check-schema-release.sh --verify-registry cargo check --locked --workspace --all-targets cargo clippy --locked --workspace --all-targets -- -D warnings cargo doc --locked --no-deps --package openengine diff --git a/packages/rust/openengine/README.md b/packages/rust/openengine/README.md index 38b2b3d..846cafc 100644 --- a/packages/rust/openengine/README.md +++ b/packages/rust/openengine/README.md @@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0 # OpenEngine Rust bindings Generated Prost messages and Tonic client/server bindings for the -[`openengine.v1`](https://github.com/ai-dynamo/openengine/tree/main/proto/openengine/v1) +[`openengine.v1`](https://github.com/ai-dynamo/openengine/tree/v0.1.0/proto/openengine/v1) protocol. ```bash diff --git a/packages/rust/openengine/schema-release.json b/packages/rust/openengine/schema-release.json new file mode 100644 index 0000000..759858e --- /dev/null +++ b/packages/rust/openengine/schema-release.json @@ -0,0 +1,7 @@ +{ + "crate_version": "0.1.0", + "schema_revision": 1, + "schema_release": "768a93c7b44e40f28c692ad0b471a8f2", + "schema_git_tag": "v0.1.0", + "schema_git_commit": "b5f2bd93721f7b888d3e2440679e0ae7012939d1" +} diff --git a/packages/rust/openengine/src/generated/schema.rs b/packages/rust/openengine/src/generated/schema.rs new file mode 100644 index 0000000..ec997ae --- /dev/null +++ b/packages/rust/openengine/src/generated/schema.rs @@ -0,0 +1,7 @@ +// @generated by openengine-rust-codegen. + +/// Monotonically increasing revision of the packaged wire contract. +pub const SCHEMA_REVISION: u32 = 1; + +/// Immutable schema release corresponding to these bindings. +pub const SCHEMA_RELEASE: &str = "768a93c7b44e40f28c692ad0b471a8f2"; diff --git a/packages/rust/openengine/src/lib.rs b/packages/rust/openengine/src/lib.rs index 777e823..9bc07f5 100644 --- a/packages/rust/openengine/src/lib.rs +++ b/packages/rust/openengine/src/lib.rs @@ -4,11 +4,7 @@ // otherwise interprets as HTML tags. #![allow(rustdoc::invalid_html_tags)] -/// Monotonically increasing revision of the packaged wire contract. -pub const SCHEMA_REVISION: u32 = 1; - -/// Immutable Buf Schema Registry commit corresponding to these bindings. -pub const SCHEMA_RELEASE: &str = "768a93c7b44e40f28c692ad0b471a8f2"; +include!("generated/schema.rs"); /// Serialized descriptors for the complete `openengine.v1` package. pub const FILE_DESCRIPTOR_SET: &[u8] = include_bytes!("generated/openengine_descriptor.bin"); diff --git a/scripts/check-schema-release.sh b/scripts/check-schema-release.sh new file mode 100755 index 0000000..375bcf2 --- /dev/null +++ b/scripts/check-schema-release.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +set -euo pipefail + +if (( $# > 1 )); then + echo "usage: $0 [--verify-registry]" >&2 + exit 2 +fi +if (( $# == 1 )) && [[ $1 != "--verify-registry" ]]; then + echo "usage: $0 [--verify-registry]" >&2 + exit 2 +fi + +repository=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +manifest="${repository}/packages/rust/openengine/schema-release.json" + +crate_version=$(jq --exit-status --raw-output '.crate_version' "${manifest}") +schema_release=$(jq --exit-status --raw-output '.schema_release' "${manifest}") +schema_tag=$(jq --exit-status --raw-output '.schema_git_tag' "${manifest}") +schema_commit=$(jq --exit-status --raw-output '.schema_git_commit' "${manifest}") + +workspace_version=$( + cargo metadata \ + --manifest-path "${repository}/Cargo.toml" \ + --no-deps \ + --format-version 1 \ + | jq --raw-output '.packages[] | select(.name == "openengine") | .version' +) + +if [[ -z ${workspace_version} || ${workspace_version} != "${crate_version}" ]]; then + echo "schema release manifest: ${crate_version}" >&2 + echo "Rust crate: ${workspace_version:-not found}" >&2 + exit 1 +fi + +if ! git -C "${repository}" cat-file -e "${schema_commit}^{commit}"; then + echo "Schema Git commit is unavailable: ${schema_commit}" >&2 + echo "Fetch the repository history and tags before running this check." >&2 + exit 1 +fi + +tag_commit=$(git -C "${repository}" rev-parse --verify "${schema_tag}^{commit}") +if [[ ${tag_commit} != "${schema_commit}" ]]; then + echo "Schema Git tag ${schema_tag}: ${tag_commit}" >&2 + echo "Schema Git commit: ${schema_commit}" >&2 + exit 1 +fi + +if ! git -C "${repository}" diff --quiet "${schema_commit}" HEAD -- 'proto/openengine/v1/*.proto'; then + git -C "${repository}" diff "${schema_commit}" HEAD -- 'proto/openengine/v1/*.proto' + echo "Packaged schema differs from declared schema commit ${schema_commit}." >&2 + exit 1 +fi + +if [[ ${1:-} == "--verify-registry" ]]; then + archive=$(mktemp) + local_protos="${archive}.local" + published_protos="${archive}.published" + trap 'rm -f "${archive}" "${local_protos}" "${published_protos}"' EXIT + curl \ + --silent \ + --show-error \ + --fail \ + --retry 3 \ + "https://buf.build/openengine/openengine/archive/${schema_release}.tar.gz" \ + --output "${archive}" + + git -C "${repository}" ls-files 'proto/openengine/v1/*.proto' \ + | sed 's#^proto/##' \ + | sort \ + > "${local_protos}" + tar -tzf "${archive}" \ + | sed -n '/\.proto$/p' \ + | sort \ + > "${published_protos}" + + if [[ ! -s ${local_protos} ]] || ! cmp -s "${local_protos}" "${published_protos}"; then + echo "Local proto files:" >&2 + cat "${local_protos}" >&2 + echo "Published proto files:" >&2 + cat "${published_protos}" >&2 + exit 1 + fi + + while IFS= read -r proto; do + if ! tar -xOzf "${archive}" "${proto}" \ + | cmp -s "${repository}/proto/${proto}" -; then + echo "Published schema differs from the packaged schema: ${proto}" >&2 + exit 1 + fi + done < "${local_protos}" +fi + +echo "OpenEngine crate metadata matches ${schema_tag} (${schema_commit})." diff --git a/tools/rust-codegen/Cargo.toml b/tools/rust-codegen/Cargo.toml index 8c24a5d..660e6fd 100644 --- a/tools/rust-codegen/Cargo.toml +++ b/tools/rust-codegen/Cargo.toml @@ -8,4 +8,6 @@ publish = false [dependencies] protoc-bin-vendored = "=3.2.0" +serde = { version = "=1.0.229", features = ["derive"] } +serde_json = "=1.0.151" tonic-prost-build = "=0.14.6" diff --git a/tools/rust-codegen/src/main.rs b/tools/rust-codegen/src/main.rs index b82e398..d8906c1 100644 --- a/tools/rust-codegen/src/main.rs +++ b/tools/rust-codegen/src/main.rs @@ -1,8 +1,19 @@ +use serde::Deserialize; use std::env; use std::error::Error; use std::fs; use std::path::PathBuf; +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct SchemaRelease { + crate_version: String, + schema_revision: u32, + schema_release: String, + schema_git_tag: String, + schema_git_commit: String, +} + fn main() -> Result<(), Box> { let repository = env::args_os() .nth(1) @@ -10,10 +21,26 @@ fn main() -> Result<(), Box> { .unwrap_or(env::current_dir()?); let proto_root = repository.join("proto"); let package_root = proto_root.join("openengine/v1"); + let crate_root = repository.join("packages/rust/openengine"); + let release_manifest = crate_root.join("schema-release.json"); let output = repository.join("packages/rust/openengine/src/generated"); fs::create_dir_all(&output)?; + let release: SchemaRelease = serde_json::from_slice(&fs::read(release_manifest)?)?; + validate_release(&release)?; + fs::write( + output.join("schema.rs"), + format!( + "// @generated by openengine-rust-codegen.\n\n\ + /// Monotonically increasing revision of the packaged wire contract.\n\ + pub const SCHEMA_REVISION: u32 = {};\n\n\ + /// Immutable schema release corresponding to these bindings.\n\ + pub const SCHEMA_RELEASE: &str = {:?};\n", + release.schema_revision, release.schema_release, + ), + )?; + let mut protos = fs::read_dir(&package_root)? .filter_map(Result::ok) .map(|entry| entry.path()) @@ -37,3 +64,29 @@ fn main() -> Result<(), Box> { Ok(()) } + +fn validate_release(release: &SchemaRelease) -> Result<(), Box> { + if release.schema_revision == 0 { + return Err("schema_revision must be greater than zero".into()); + } + if release.crate_version.is_empty() { + return Err("crate_version must not be empty".into()); + } + if release.schema_git_tag.is_empty() { + return Err("schema_git_tag must not be empty".into()); + } + if !is_lower_hex(&release.schema_release, &[32, 40]) { + return Err("schema_release must be a 32- or 40-character lowercase hex ID".into()); + } + if !is_lower_hex(&release.schema_git_commit, &[40]) { + return Err("schema_git_commit must be a 40-character lowercase Git commit".into()); + } + Ok(()) +} + +fn is_lower_hex(value: &str, lengths: &[usize]) -> bool { + lengths.contains(&value.len()) + && value + .bytes() + .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte)) +}