feat(engine): minimal vendor profile for baml_py + CLI#3936
Conversation
Add a feature-gated "vendor profile" so `baml_py` and the `baml` CLI can be built with a much smaller dependency tree for environments that vendor all third-party crates. Building either with --no-default-features drops the LSP, Boundary cloud (auth/login/deploy), serve/dev servers, REPL, optimize/TUI, the Studio tracing publisher, and AWS Bedrock — each behind an on-by-default feature, so published artifacts (PyPI/NPM/gems/release CLI) are unchanged. Highlights: - New feature gates: lsp, serve, dev, repl, tui, optimize, studio, vertex, cloud (plus existing bedrock). Providers compiled out fail at request time with a clear message rather than vanishing from the language. - New `baml-http` crate: the reqwest API subset BAML uses, implemented on hyper + hyper-util + hyper-rustls (native) and re-exporting reqwest on wasm32. Shipping code no longer pulls reqwest into the native tree. - Dependency hygiene: replace async-std usage with tokio/wasmtimer, drop dead deps (sha2, whoami, test-log/pretty_assertions moved to dev-deps), gate jsonish's test corpus behind cfg(test). - Vendor profile is ~283 crates (~289 with vertex) vs ~460+ for the wheel; ring is the only native-code crate on Linux. - CI: new `vendor-profile` job compiles the --no-default-features builds (with and without vertex) and asserts reqwest stays out of the native tree. - Docs: engine/VENDORING.md + scripts/vendor-audit-coverage.py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
⏭️ Performance benchmarks were skippedPerf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to To run them on this PR, do any of the following, then push a commit (or re-run CI):
|
Bumps pyo3, pyo3-async-runtimes, and pyo3-build-config to 0.28 so the Python binding layer matches newer pyo3 versions (smaller import/review surface for vendoring consumers that already carry a recent pyo3). Mechanical migration, no behavior change intended: - Python::with_gil -> Python::attach, allow_threads -> detach (0.26 rename). - pyo3::PyObject was removed from the crate root; re-provided as a crate-local `type PyObject = Py<PyAny>` alias so signatures are unchanged. - downcast/downcast_bound -> cast/cast_bound. - #[pyclass] Clone types opt into the FromPyObject derive explicitly via #[pyclass(from_py_object)] to preserve current behavior. - abi3-py38 retained (package already requires Python >=3.10). Compiles clean (0 warnings) on both default and --no-default-features. To retarget 0.26 instead, only the three version strings change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ixes Addresses vendoring friction for monorepos that ban `ring` and mandate the system/BoringSSL crypto stack. - baml-http: TLS backend is now a cargo feature. `native-tls` (default) uses the platform TLS stack (SChannel / Security.framework / system OpenSSL) via hyper-tls, reads the OS trust store, and keeps `ring` out of the tree. `rustls-tls` (opt-in) restores the static rustls + ring + webpki stack with HTTP/2. `native-tls-vendored` statically vendors OpenSSL for portable Linux wheels. native-tls connections use HTTP/1.1 (hyper-tls does not forward the ALPN h2 hint; SSE and LLM calls are unaffected). - baml-runtime: remove a dead direct `ring` dependency (only referenced in a comment). With native-tls default, the base vendor profile is now ring-free. Note: the `vertex` feature still pulls ring via gcp_auth 0.12. - cli: clap-cargo 0.14 -> 0.12, which 6 -> 7 (align with commonly-hosted monorepo versions). Verified: full compile matrix (both TLS backends, default + vendor profile + vertex), wasm, clippy (-D warnings) on both backends, and a live HTTPS call to OpenAI over native-tls returning a clean 401. ⚠ native-tls as the default means prebuilt Linux wheels now need a system libssl (or the native-tls-vendored feature). Revisit before release if that regresses manylinux packaging. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The `vertex` feature pulled `ring` via `gcp_auth 0.12`, which used it for both TLS (hyper-rustls) and JWT RS256 signing — the last ring source in the vendor profile. gcp_auth is a community crate (github.com/djc/gcp_auth), not a Google project, so its crypto choices are not load-bearing. Vendor it into engine/vendored/gcp-auth (MIT, like minijinja) with two localized changes in src/types.rs: - HTTPS client: hyper-rustls -> hyper-tls (platform/native TLS, OS trust store, HTTP/1.1). - JWT signer: ring::signature RSA_PKCS1_SHA256 -> the pure-Rust `rsa` + `sha2` crates. A unit test asserts the signature is byte-identical to `openssl dgst -sha256 -sign`, so Google's token endpoint accepts it exactly as before. Result: the vendor profile is now ring-free WITH `--features vertex` (0 ring crates in the tree). To use a different signing backend (e.g. BoringSSL), replace the ~15-line Signer impl. Verified: full compile matrix + wasm, the byte-equality signer test, and a live Vertex call — ADC token obtained over native-tls, request reached aiplatform.googleapis.com (403 CONSUMER_INVALID for a fake project = auth succeeded). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1.0 requires each derive's feature to be listed explicitly (0.99 enabled all by default). The workspace uses only the `From` and `Constructor` derives, so the dep becomes `features = ["from", "constructor"]`. No source changes needed; 0.99 is fully gone from the tree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The vendored gcp-auth fork is a crate we modified (ring-free TLS + RSA signer), so it should get the same CI coverage as first-party code rather than sitting outside the workspace as an excluded path dep. Promote it to a workspace member: - fmt to the workspace style (imports_granularity=Crate, StdExternalCrate). - clippy is clean under -D warnings. - its one network test (`gcloud`) is already #[ignore]d, so `cargo test --workspace` stays hermetic; the signer byte-equality test now runs as part of the workspace suite. - no separate Cargo.lock (uses the workspace lockfile). minijinja stays excluded: it is a large fork tracked close to upstream, and its test suite / dev-deps should not enter our build graph. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a manually-dispatchable workflow that builds the minimal vendor profile (--no-default-features --features vertex,native-tls-vendored) as an x86_64 extension that runs in ultra-hermetic sandboxes (old GLIBC, no libgcc_s.so.1): - built on manylinux2014 (GLIBC 2.17), - statically linked libgcc/libstdc++ via RUSTFLAGS, - vendored OpenSSL (no system libssl). The build fails unless the artifact has no libgcc_s dependency and requires GLIBC <= 2.17, then uploads baml_py.so as an artifact to drop into third_party. Also adds the `native-tls-vendored` feature forwarding (baml-http -> baml-runtime -> baml-cli -> baml-python-ffi) that the vendored OpenSSL build needs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…TFLAGS) Adds -static-libgcc/-static-libstdc++ to the x86_64-unknown-linux-gnu target in engine/.cargo/config.toml so the built extension has no libgcc_s.so.1 dynamic dependency. Also makes normal x86_64 release wheels hermetic for the same sandboxes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Target-specific rustflags are ignored for host builds (cargo#8607), which is how maturin builds in the manylinux container. Use CARGO_BUILD_RUSTFLAGS (applies to host builds) and forward it into the container via maturin-action docker-options. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… only that) maturin re-encodes .cargo/config.toml [build].rustflags into CARGO_ENCODED_RUSTFLAGS, overriding env-based RUSTFLAGS. Patch the runner-local config before the build; the committed config is untouched so other platforms' release wheels are unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
Adds a feature-gated vendor profile: a way to build
baml_pyand thebamlCLI with a much smaller dependency tree, for environments that vendor all third-party crates (where every external crate must be imported and reviewed).Building either crate with
--no-default-featuresdrops the optional surface; everything is on by default, so published artifacts (PyPI / NPM / gems / release CLI) are unchanged.(vs ~460+ for the published wheel;
ringis the only native-code crate on Linux.)Feature gates (all default-on)
lspbaml lspbedrockaws-*/smithy treeserve/devbaml serve/devreplbaml repltui/optimizecloudbaml auth/login/deploystudiovertexA provider compiled out (e.g.
vertex,bedrock) still exists in the language; it fails at request time with a clear "built without the X feature" message rather than disappearing.baml-http(new crate)Shipping HTTP now goes through
baml-http, which exposes the reqwest API subset BAML uses:The LLM send path was already funneled through one client factory + two send sites, and the SSE decoder was already reqwest-agnostic, so the swap is contained. reqwest remains for non-shipping code (LSP CORS proxy, playground, sandbox, tests).
Known deltas vs reqwest: no env proxies (
HTTP_PROXY),read_timeoutis an idle-between-chunks timeout. Seebaml-http/src/lib.rs.Dependency hygiene (affects all builds)
async-std(a second async runtime, 3 trivial uses) with tokio/wasmtimer +tokio::fs.sha2(baml-rpc, baml-runtime),whoami(baml-core).test-log/pretty_assertionsto dev-deps where they belong.#[cfg(test)](it waspub mod tests;, shipping in every build). 483 tests still run.CI
New
vendor-profilejob inprimary.yml: compiles both--no-default-featuresbuilds (with and withoutvertex) and fails ifreqwestre-enters the native tree.Verification
init→generate→baml testhitting OpenAI over hyper (401), and with--features vertex, resolved ADC credentials via gcp_auth and reached Vertex through hyper (real 403 for a fake project).Docs:
engine/VENDORING.md,engine/scripts/vendor-audit-coverage.py.🤖 Generated with Claude Code