Remove minijinja from sys_llm and LSP/diagnostics - #4229
Conversation
Rewrite every test that exercises the legacy jinja render path to the BEP-049 backtick prompt system: bex_engine integration tests, baml_tests corpus + drivers, baml_cli profiles e2e, and sdk_tests fixtures. Direct sys_llm::render_prompt Rust-level tests are rewritten BAML-level via hand-built baml.llm.Context + prompt closures; template_string jinja macros become plain expression functions; 3-arg baml.llm.render_prompt / build_request calls go through the compiled Fn$render_prompt / Fn$build_request companions. Still on legacy syntax (blocked on new-system gaps, addressed next): - three ignored media interpolation tests (structural assembler renders media values as empty text) - test_render_prompt_with_enums (ctx.enums; production always passed empty enum maps, so this is test-only surface)
Delete the legacy Jinja prompt engine now that every runtime test renders
through the BEP-049 backtick prompt closures:
- sys_llm: drop the jinja render module and execute_render_prompt_from_owned;
re-export OutputFormatContent from types directly.
- Delete the sys_jinja and sys_jinja_types crates and the minijinja /
minijinja-contrib workspace dependencies (boundaryml fork, ~0.5 MB of
binary size).
- stdlib: render_specialized_prompt loses its template/args params and throws
root.errors.RenderPrompt with a migration hint for null-closure (legacy
#"..."#) functions; remove get_jinja_template, prompt_template_for,
PrimitiveClient.render_prompt, and the ExecutionContext jinja_string/args
threading. Legacy syntax still parses; removing it is a follow-up (M6).
- Remove the template-string {% macro %} emit pass and its plumbing
(CompiledUnit.template_macros, Program/BytecodeProgram/SysOpContext
template_strings_macros, FunctionMeta::Llm prompt_template); bump
bex_cache FORMAT_VERSION to 4 for the wire-format change.
- LSP: remove check_jinja_templates and its sys_jinja_types-based validator;
retire diagnostics E0070-E0087 and the dead TypeError::Jinja* variants.
- Media in backtick prompts: assemble_prompt_ast now takes the raw values
alongside their rendered string forms, so ${img} becomes a media content
part (matching the legacy renderer's trim/drop semantics) for both
in-language and host-injected media representations.
- Migrate the remaining direct-call tests (stream_llm_function type-args pin,
env.rs assemble calls, media build_request tests); drop the jinja halves of
the prompt_tag_e2e parity tests, the ctx.enums render test (that context was
never populated in production), and the string_methods pycompat fixture.
- Regenerate stdlib, describe, and package-item snapshots.
- prompt_role_name now matches baml.llm.Role exactly: with raw values
reaching the assembler, the old .Role suffix match swallowed user-defined
classes named Role as chat-role markers (corpus regression test added).
- Enable the openai and anthropic mixed text+image build_request tests,
re-pinned to current deliberate builder behavior (media messages promote
to the user role; anthropic max_tokens defaults to 8192), and add sys_ops
unit tests covering the assembler's media shapes and legacy trim parity.
- Fail fast on RenderPrompt in the retry and fallback orchestrators: the
error is deterministic, so surface the migration hint instead of the
generic "All orchestration steps failed".
- Remove the now write-only legacy prompt data: LlmBodyDef.prompt, RawPrompt,
Interpolation, TemplateStringDef.body and its HIR/PPIR copies (their last
readers went with the jinja validator and macro emit pass).
- Refresh stale comments that still described the deleted jinja engine
(dedent.rs, lower_cst.rs, companions.rs, sys_llm docs, stdlib Context and
render_prompt_values docs) and regenerate the architecture crate graph.
- Known follow-up: media nested in composites (${images} for image[]) is
stringified with its container; only top-level media interpolations become
media parts (noted at prompt_media_value).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
⏭️ 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):
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThe pull request removes the legacy MiniJinja prompt pipeline and migrates LLM rendering to compiled backtick prompt closures. Compiler metadata, runtime layouts, diagnostics, LSP validation, dependencies, cache formats, and related tests are updated accordingly. ChangesPrompt rendering migration
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Binary size checks passed✅ 7 passed
Generated by |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
baml_language/crates/baml_compiler2_ast/src/lower_cst.rs (1)
2398-2424: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winEmit a deprecation diagnostic for legacy
template_stringbodies.
parse_template_string()still reads the raw-string body and the HIR/PPIT data only carrynameandparams; this path currently records the item and drops its prompt body with no migration/no-op warning.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@baml_language/crates/baml_compiler2_ast/src/lower_cst.rs` around lines 2398 - 2424, Update lower_template_string to emit a deprecation diagnostic when a legacy template_string body is present, while preserving the existing name and parameter lowering. Reuse the parser’s raw-body presence information and the established diagnostic type/message conventions, ensuring the body remains intentionally ignored after the warning.
🧹 Nitpick comments (1)
baml_language/crates/bex_engine/tests/build_request.rs (1)
1059-1099: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winStale ignored test — the correct expected values are already documented in the
#[ignore]message.
test_anthropic_audio_url's ignore reason states the builder actually emitsmax_tokens: 8192and"type": "input_audio", but the assertion body still pins the old4096/"audio"values. Since the PR's own goal is "enabling related provider tests" for media, andtest_anthropic_mixed_text_and_imagewas just fixed to pin8192for the analogous case, updating this assertion to match and re-enabling the test looks like a straightforward, low-risk win.♻️ Proposed fix (pending confirmation of actual builder output)
-#[ignore = "request builder emits max_tokens 8192 and type input_audio; assertion pins 4096 and audio"] async fn test_anthropic_audio_url() { ... assert_eq!( body, serde_json::json!({ "model": "claude-3-5-sonnet-20241022", - "max_tokens": 4096, + "max_tokens": 8192, "messages": [ { "role": "user", "content": [ {"type": "text", "text": "Transcribe this audio:"}, - {"type": "audio", "source": {"type": "url", "url": "https://example.com/speech.mp3"}} + {"type": "input_audio", "source": {"type": "url", "url": "https://example.com/speech.mp3"}} ] } ] }) ); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@baml_language/crates/bex_engine/tests/build_request.rs` around lines 1059 - 1099, Update test_anthropic_audio_url to assert the builder’s current output: max_tokens 8192 and the input_audio content type, then remove its #[ignore] attribute so the test runs. Preserve the existing model, URL, and message structure assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@baml_language/crates/baml_compiler2_ast/src/lower_cst.rs`:
- Around line 2398-2424: Update lower_template_string to emit a deprecation
diagnostic when a legacy template_string body is present, while preserving the
existing name and parameter lowering. Reuse the parser’s raw-body presence
information and the established diagnostic type/message conventions, ensuring
the body remains intentionally ignored after the warning.
---
Nitpick comments:
In `@baml_language/crates/bex_engine/tests/build_request.rs`:
- Around line 1059-1099: Update test_anthropic_audio_url to assert the builder’s
current output: max_tokens 8192 and the input_audio content type, then remove
its #[ignore] attribute so the test runs. Preserve the existing model, URL, and
message structure assertions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 73ddad96-1529-4677-8889-327b23fe6233
⛔ Files ignored due to path filters (22)
baml_language/Cargo.lockis excluded by!**/*.lockbaml_language/architecture/architecture.svgis excluded by!**/*.svgbaml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_namespace_llm.snapis excluded by!**/*.snapbaml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/google_llm_env.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/parse_companions.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/prompt_tag_runtime.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/streaming_parsing.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/baml_src/type_reflection.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____03_ppir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__03_ppir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__04_5_mir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__04_tir.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__05_diagnostics.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__06_codegen.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/snapshots/compiles/string_methods/baml_tests__compiles__string_methods__10_formatter__string_methods.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/src/compiler2_tir/snapshots/baml_tests__compiler2_tir__phase5__snapshot_baml_package_items.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snapis excluded by!**/*.snapbaml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snapis excluded by!**/*.snap
📒 Files selected for processing (80)
baml_language/Cargo.tomlbaml_language/crates/baml_base/src/dedent.rsbaml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm.bamlbaml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm_types.bamlbaml_language/crates/baml_builtins2_codegen/src/extract.rsbaml_language/crates/baml_cli/tests/test_profiles_e2e.rsbaml_language/crates/baml_compiler2_ast/src/ast.rsbaml_language/crates/baml_compiler2_ast/src/companions.rsbaml_language/crates/baml_compiler2_ast/src/lower_cst.rsbaml_language/crates/baml_compiler2_emit/src/lib.rsbaml_language/crates/baml_compiler2_hir/src/item_tree/builder.rsbaml_language/crates/baml_compiler2_hir/src/item_tree/template_strings.rsbaml_language/crates/baml_compiler2_ppir/src/item_data/functions.rsbaml_language/crates/baml_compiler2_ppir/src/item_data/template_strings.rsbaml_language/crates/baml_compiler_diagnostics/src/diagnostic.rsbaml_language/crates/baml_compiler_diagnostics/src/errors/type_error.rsbaml_language/crates/baml_compiler_diagnostics/src/to_diagnostic.rsbaml_language/crates/baml_lsp2_actions/Cargo.tomlbaml_language/crates/baml_lsp2_actions/src/check.rsbaml_language/crates/baml_lsp2_actions_tests/test_files/completion/prompt_ctx.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/completion/prompt_ctx_client.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/completion/prompt_underscore.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/semantic_tokens/type_aliases_jinja.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/type_aliases_jinja.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/enum/enums_in_jinja.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/enum/nullable_enums_in_jinja.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/prompt_errors/prompt1.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/prompt_errors/prompt2.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/prompt_errors/role.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/valid.bamlbaml_language/crates/baml_lsp2_actions_tests/test_files/syntax/template_string/bad_calls.bamlbaml_language/crates/baml_tests/baml_src/ns_google_llm_env/google_llm_env.bamlbaml_language/crates/baml_tests/baml_src/ns_parse_companions/parse_companions.bamlbaml_language/crates/baml_tests/baml_src/ns_prompt_tag_runtime/prompt_tag_runtime.bamlbaml_language/crates/baml_tests/baml_src/ns_streaming_parsing/streaming_parsing.bamlbaml_language/crates/baml_tests/baml_src/ns_type_reflection/type_reflection.bamlbaml_language/crates/baml_tests/projects/compiles/string_methods/string_methods.bamlbaml_language/crates/baml_tests/src/compiler2_tir/phase3a.rsbaml_language/crates/baml_tests/tests/env.rsbaml_language/crates/baml_tests/tests/google_llm_env.rsbaml_language/crates/baml_tests/tests/parse_companions.rsbaml_language/crates/baml_tests/tests/prompt_tag_e2e.rsbaml_language/crates/baml_tests/tests/streaming_parsing.rsbaml_language/crates/bex_cache/src/lib.rsbaml_language/crates/bex_engine/Cargo.tomlbaml_language/crates/bex_engine/src/lib.rsbaml_language/crates/bex_engine/tests/build_request.rsbaml_language/crates/bex_engine/tests/collect_tests.rsbaml_language/crates/bex_engine/tests/common/mod.rsbaml_language/crates/bex_engine/tests/llm_render.rsbaml_language/crates/bex_engine/tests/orchestration.rsbaml_language/crates/bex_engine/tests/prof_gate.rsbaml_language/crates/bex_vm/src/vm.rsbaml_language/crates/bex_vm_types/src/link.rsbaml_language/crates/bex_vm_types/src/types.rsbaml_language/crates/bex_vm_types/src/types/function.rsbaml_language/crates/bex_vm_types/src/unit.rsbaml_language/crates/sys_jinja/Cargo.tomlbaml_language/crates/sys_jinja/src/lib.rsbaml_language/crates/sys_jinja_types/Cargo.tomlbaml_language/crates/sys_jinja_types/src/evaluate_type/expr.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/mod.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/pretty_print.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/stmt.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/test_expr.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/test_stmt.rsbaml_language/crates/sys_jinja_types/src/evaluate_type/types.rsbaml_language/crates/sys_jinja_types/src/lib.rsbaml_language/crates/sys_llm/Cargo.tomlbaml_language/crates/sys_llm/src/jinja/error.rsbaml_language/crates/sys_llm/src/jinja/mod.rsbaml_language/crates/sys_llm/src/jinja/output_format_object.rsbaml_language/crates/sys_llm/src/jinja/render.rsbaml_language/crates/sys_llm/src/jinja/value_conversion.rsbaml_language/crates/sys_llm/src/lib.rsbaml_language/crates/sys_ops/src/lib.rsbaml_language/crates/sys_types/src/lib.rsbaml_language/sdk_tests/crates/csharp/phase10_stream/baml_src/ns_csharp_phase10/main.bamlbaml_language/sdk_tests/fixtures/llm_functions/baml_src/ns_ipsum/functions.bamlbaml_language/sdk_tests/fixtures/llm_functions/baml_src/ns_lorem/functions.baml
💤 Files with no reviewable changes (44)
- baml_language/crates/sys_jinja_types/src/evaluate_type/expr.rs
- baml_language/crates/sys_jinja/Cargo.toml
- baml_language/crates/baml_lsp2_actions_tests/test_files/completion/prompt_underscore.baml
- baml_language/crates/baml_lsp2_actions_tests/test_files/completion/prompt_ctx.baml
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/prompt_errors/role.baml
- baml_language/crates/bex_engine/Cargo.toml
- baml_language/crates/sys_jinja_types/Cargo.toml
- baml_language/crates/baml_lsp2_actions_tests/test_files/completion/prompt_ctx_client.baml
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/enum/nullable_enums_in_jinja.baml
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/prompt_errors/prompt2.baml
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/template_string/bad_calls.baml
- baml_language/crates/sys_jinja_types/src/evaluate_type/test_expr.rs
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/class/type_aliases_jinja.baml
- baml_language/crates/baml_compiler2_hir/src/item_tree/builder.rs
- baml_language/crates/sys_llm/src/jinja/mod.rs
- baml_language/crates/sys_jinja_types/src/lib.rs
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/prompt_errors/prompt1.baml
- baml_language/crates/sys_llm/src/jinja/error.rs
- baml_language/crates/sys_llm/Cargo.toml
- baml_language/crates/baml_lsp2_actions/Cargo.toml
- baml_language/crates/sys_jinja_types/src/evaluate_type/test_stmt.rs
- baml_language/crates/baml_compiler2_ppir/src/item_data/functions.rs
- baml_language/crates/baml_compiler2_ppir/src/item_data/template_strings.rs
- baml_language/crates/baml_compiler2_hir/src/item_tree/template_strings.rs
- baml_language/crates/sys_llm/src/jinja/value_conversion.rs
- baml_language/crates/baml_lsp2_actions_tests/test_files/semantic_tokens/type_aliases_jinja.baml
- baml_language/crates/baml_tests/projects/compiles/string_methods/string_methods.baml
- baml_language/crates/sys_jinja/src/lib.rs
- baml_language/crates/sys_jinja_types/src/evaluate_type/pretty_print.rs
- baml_language/crates/sys_llm/src/jinja/output_format_object.rs
- baml_language/crates/bex_vm_types/src/types.rs
- baml_language/crates/sys_jinja_types/src/evaluate_type/mod.rs
- baml_language/crates/sys_jinja_types/src/evaluate_type/stmt.rs
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/enum/enums_in_jinja.baml
- baml_language/crates/sys_llm/src/jinja/render.rs
- baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/functions_v2/valid.baml
- baml_language/Cargo.toml
- baml_language/crates/baml_compiler_diagnostics/src/errors/type_error.rs
- baml_language/crates/bex_vm_types/src/link.rs
- baml_language/crates/sys_jinja_types/src/evaluate_type/types.rs
- baml_language/crates/baml_compiler_diagnostics/src/to_diagnostic.rs
- baml_language/crates/bex_vm/src/vm.rs
- baml_language/crates/bex_vm_types/src/unit.rs
- baml_language/crates/sys_types/src/lib.rs
Conflicts: the two bytecode_format display snapshots, regenerated from the merged tree.
Issue Reference
Changes
sys_llm::render_prompttests are rewritten BAML-level; jinja-macrotemplate_stringtests become plain expression functions; 3-argbaml.llm.render_prompt/build_requestcalls go through the compiledFn$render_prompt/Fn$build_requestcompanions.sys_llm/src/jinja, thesys_jinjaandsys_jinja_typescrates, and the minijinja/minijinja-contrib workspace deps (the boundaryml fork).Cargo.lockno longer resolves minijinja; expected baml-cli size reduction is the ~0.5 MB discussed on the ticket (size gate will report the exact delta).render_specialized_prompt(return_type, prompt_closure)drops itstemplate/argsparams; a null closure (legacy#"..."#function) throwsbaml.errors.RenderPromptwith a migration hint instead of rendering. The retry/fallback orchestrators rethrowRenderPromptinstead of burying it under "All orchestration steps failed" (it is deterministic; retrying cannot help).get_jinja_template,prompt_template_for,PrimitiveClient.render_prompt, and theExecutionContext.jinja_string/argsthreading are gone. Legacy syntax still parses; removing it from the grammar is M6.{% macro %}emit pass and its plumbing (CompiledUnit.template_macros,Program/BytecodeProgram/SysOpContext.template_strings_macros,FunctionMeta::Llm.prompt_template), plus the now write-only legacy prompt data (LlmBodyDef.prompt,RawPrompt,TemplateStringDef.bodythrough HIR/PPIR).bex_cache::FORMAT_VERSIONbumps to 4 for the wire-format change.check_jinja_templatesand thesys_jinja_typesvalidator; retire E0070-E0087 (codes are not reused) and the deadTypeError::Jinja*variants; drop the fixtures that pinned validator output.assemble_prompt_astnow receives the raw interpolation values alongside their rendered string forms, so${img}becomes a media content part (bothbaml.media.*instances and host-injected media ADTs), matching the legacy renderer's trim/drop semantics.prompt_role_namematchesbaml.llm.Roleexactly so a user class namedRoleis no longer mistaken for a chat-role marker. The previously-ignored openai/anthropic mixed text+image tests are enabled, re-pinned to current deliberate builder behavior (media messages promote to the user role; anthropicmax_tokensdefaults to 8192).Dropped intentionally:
ctx.enumsrendering (production always passed empty enum maps; it was reachable only from a Rust-level test API) and thestring_methodspycompat fixture (existed solely to exercise the deleted validator).Known follow-up: media nested in composites (
${images}for animage[]param, class fields, map values) is stringified with its container; only top-level media interpolations become media parts (noted atprompt_media_value). The legacy converter recursed into composites.Testing
cargo nextest run --all-features --workspace --exclude baml_tests --exclude baml_cli --exclude baml_lsp2_actions --exclude "sdk_test_*" --exclude baml_bridge(4677 passed)cargo test -p baml_tests(corpus 2551+, all tiers; snapshots regenerated for the stdlib/describe/package-item churn)cargo test -p baml_cli -p baml_lsp2_actions -p baml_lsp2_actions_tests -p bex_enginecargo nextest run -p sdk_test_python_pydantic2 / rust / typescript / typescript_web / java / go / swift / cpp / llm_recordings -E 'test(llm_functions)'(csharp verified through the harness compile + sdkgen path; no dotnet locally)mise run fmt,mise run stow,mise run clippy,mise run clippy-wasm,prek run --all-filesrg minijinjaacross the workspace: only the bex_cache format-version history comment remainsSummary by CodeRabbit
New Features
${...}interpolation for LLM calls, streaming, rendering/preview, roles, and media handling.Bug Fixes
Roleclasses from being treated as chat role markers.Refactor