Skip to content

feat(bridges): support providing host callables as lambdas with optional args#3787

Merged
sxlijin merged 2 commits into
canaryfrom
sam/callbacks-optargs
Jun 18, 2026
Merged

feat(bridges): support providing host callables as lambdas with optional args#3787
sxlijin merged 2 commits into
canaryfrom
sam/callbacks-optargs

Conversation

@sxlijin

@sxlijin sxlijin commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features

    • Improved TypeScript callable typings for optional parameters using a trailing $opts?: { ... } object.
  • Bug Fixes

    • Host-callable dispatch now consistently routes required positional arguments separately from named optional arguments, with omitted optionals correctly using the host’s defaults.
    • Updated host-call argument payload handling to support the new argument envelope consistently across runtimes.
  • Documentation

    • Expanded documentation describing the expected host-call argument structure and optional semantics.
  • Tests

    • Added/updated fixtures and end-to-end tests for optional-argument behavior and validation (including broken-syntax cases).

@vercel

vercel Bot commented Jun 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jun 18, 2026 11:16pm
promptfiddle Ready Ready Preview, Comment Jun 18, 2026 11:16pm
promptfiddle2 Ready Ready Preview, Comment Jun 18, 2026 11:16pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f4daa0ce-718f-408b-a4c2-19d533bd42c0

📥 Commits

Reviewing files that changed from the base of the PR and between fc3b3a4 and a93ed3c.

⛔ Files ignored due to path filters (13)
  • baml_language/Cargo.lock is excluded by !**/*.lock
  • baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__01_lexer__callback_param_defaults.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__02_parser__callback_param_defaults.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/src/compiler2_tir/snapshots/baml_tests__compiler2_tir__phase5__snapshot_baml_package_items.snap is excluded by !**/*.snap
  • baml_language/sdks/go/bridge_go/cffi/proto/baml_core/cffi/v1/baml_outbound.pb.go is excluded by !**/*.pb.go
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.d.ts.map is excluded by !**/dist/**, !**/*.map
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.js is excluded by !**/dist/**
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.js.map is excluded by !**/dist/**, !**/*.map
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.d.ts is excluded by !**/dist/**
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.js is excluded by !**/dist/**
  • baml_language/sdks/python/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (28)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_host/host.baml
  • baml_language/crates/baml_tests/projects/broken_syntax/optional_parameter_defaults/callback_param_defaults.baml
  • baml_language/crates/bex_engine/src/conversion.rs
  • baml_language/crates/bex_engine/tests/host_value_callable.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/bex_vm_types/src/types.rs
  • baml_language/crates/bridge_ctypes/src/lib.rs
  • baml_language/crates/bridge_ctypes/src/value_encode.rs
  • baml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.proto
  • baml_language/crates/bridge_wasm/src/host_value.rs
  • baml_language/crates/bridge_wasm/tests/host_callable.rs
  • baml_language/crates/sys_native/src/host_impls.rs
  • baml_language/sdk_tests/crates/python_pydantic2/function_calls/customizable/test_host_callables.py
  • baml_language/sdk_tests/crates/typescript_node/function_calls/customizable/host_callables.test.ts
  • baml_language/sdk_tests/fixtures/function_calls/baml_src/ns_host_callable_tests/main.baml
  • baml_language/sdks/go/bridge_go/pkg/host_value.go
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.d.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/leaf.rs
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/translate_ty.rs
  • baml_language/sdks/python/rust/bridge_python/src/host_value.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/Cargo.toml
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/emit/mod.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyi
✅ Files skipped from review due to trivial changes (5)
  • baml_language/crates/baml_tests/projects/broken_syntax/optional_parameter_defaults/callback_param_defaults.baml
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_host/host.baml
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.d.ts
🚧 Files skipped from review as they are similar to previous changes (21)
  • baml_language/crates/bex_vm_types/src/types.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/Cargo.toml
  • baml_language/crates/bridge_ctypes/src/lib.rs
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/leaf.rs
  • baml_language/crates/bridge_wasm/src/host_value.rs
  • baml_language/crates/bex_engine/src/conversion.rs
  • baml_language/crates/bridge_ctypes/src/value_encode.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/bridge_wasm/tests/host_callable.rs
  • baml_language/crates/sys_native/src/host_impls.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts
  • baml_language/sdk_tests/crates/typescript_node/function_calls/customizable/host_callables.test.ts
  • baml_language/sdk_tests/fixtures/function_calls/baml_src/ns_host_callable_tests/main.baml
  • baml_language/sdks/python/rust/bridge_python/src/host_value.rs
  • baml_language/sdk_tests/crates/python_pydantic2/function_calls/customizable/test_host_callables.py
  • baml_language/sdks/go/bridge_go/pkg/host_value.go
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyi
  • baml_language/crates/bex_engine/tests/host_value_callable.rs
  • baml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.proto
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs

📝 Walkthrough

Walkthrough

Introduces a BamlToHostCall/BamlToHostArg protobuf envelope for host-callable dispatch. The VM now stores declared parameter metadata on HostClosure and splits arguments into required positional and optional name→value packs. Bridges (WASM, native, Go, Node.js, Python) encode and decode this pack, reshaping optional args into language-native conventions ($opts for TypeScript, kwargs for Python). TypeScript codegen emits $opts trailing objects; Python codegen emits typing.Protocol stubs for optional-arg callables.

Changes

Host callable optional parameter dispatch

Layer / File(s) Summary
Proto schema: BamlToHostCall, BamlToHostArg + generated artifacts
baml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.proto, baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.d.ts, baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js, baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py, baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyi
Adds BamlToHostCall (repeated BamlToHostArg envelope) and BamlToHostArg (value, arg_name, is_optional_arg) to the proto schema, then regenerates Node.js and Python protobuf artifacts.
VM and engine: HostClosure.params field and arg-splitting sysop
baml_language/crates/bex_vm_types/src/types.rs, baml_language/crates/bex_engine/src/conversion.rs, baml_language/crates/bex_vm/src/vm.rs
Adds params: Box<Vec<RuntimeFunctionParamTy>> to HostClosure; conversion captures declared params; host_closure_call_sysop splits user_args into required positional and optional (non-OMITTED_ARG) map, then passes [positional_ptr, optional_ptr] as args[1].
Bridge encoding: build_to_host_call in bridge_ctypes, sys_native, WASM
baml_language/crates/bridge_ctypes/src/value_encode.rs, baml_language/crates/bridge_ctypes/src/lib.rs, baml_language/crates/sys_native/src/host_impls.rs, baml_language/crates/bridge_wasm/src/host_value.rs
Adds build_to_host_call to serialize positional and optional BexExternalValue lists into BamlToHostCall; re-exports it; updates sys_native and WASM bridges to unpack the args_pack and encode via the new helper before dispatching.
SDK bridges: decode BamlToHostCall in Go, Node.js, Python
baml_language/sdks/go/bridge_go/pkg/host_value.go, baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts, baml_language/sdks/python/rust/bridge_python/src/host_value.rs
Go unmarshals BamlToHostCall; Node.js adds decodeHostCall/reshapeHostArgs to fold optionals into a trailing $opts object in makeHostCallableDispatch; Python decode_args returns (positional_tuple, kwargs_dict) and dispatch_in_python calls the callable with both.
TypeScript codegen: optional params → $opts trailing object in Callable types
baml_language/sdks/nodejs/sdkgen_typescript_node/src/translate_ty.rs, baml_language/sdks/nodejs/sdkgen_typescript_node/src/leaf.rs
Ty::Callable emission groups optional params into $opts?: { field?: T | undefined } | undefined; makes safe_param_name/option_field_name pub(crate); updates defineFunction/defineInstanceFunction codegen to interpolate the new trailing variable; updates tests.
Python codegen: optional callable params → typing.Protocol stubs in .pyi
baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs, baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs, baml_language/sdks/python/rust/sdkgen_python_pydantic2/Cargo.toml
Adds callback_protocols map to TranslateCtx; Ty::Callable looks up the protocol name when params include optionals; LeafBody::callback_protocols() collects optional-arg callables; render_callback_protocol emits typing.Protocol classes; render_leaf_body_pyi emits them before leaf symbols and adds indexmap dependency.
BAML fixtures, engine/bridge test harness updates, SDK end-to-end tests
baml_language/sdk_tests/fixtures/function_calls/baml_src/ns_host_callable_tests/main.baml, baml_language/crates/bex_engine/tests/host_value_callable.rs, baml_language/crates/bridge_wasm/tests/host_callable.rs, baml_language/sdk_tests/crates/python_pydantic2/function_calls/customizable/test_host_callables.py, baml_language/sdk_tests/crates/typescript_node/function_calls/customizable/host_callables.test.ts, baml_language/crates/baml_builtins2/baml_std/baml/ns_host/host.baml, baml_language/crates/baml_tests/projects/broken_syntax/optional_parameter_defaults/callback_param_defaults.baml
Adds three BAML optional-arg fixture functions and a broken-syntax fixture; updates engine and WASM test harnesses to decode BamlToHostCall; adds Python and TypeScript SDK tests validating default application, named optional delivery, and combined optional args; updates call_host_value documentation for the args_pack wire format.

Sequence Diagram(s)

sequenceDiagram
  participant BAML as BAML VM (host_closure_call_sysop)
  participant sysop as SysOp::BamlHostCallHostValue
  participant native as sys_native / WASM
  participant sdk as Go / Node.js / Python SDK
  participant host as Host callback

  rect rgba(70, 130, 180, 0.5)
    note over BAML,sysop: Arg splitting (Rust VM)
    BAML->>BAML: extract hc.params from HostClosure
    BAML->>BAML: iterate user_args with params → positional[], optional{name→value}
    BAML->>BAML: drop OMITTED_ARG optionals
    BAML->>sysop: args[1] = [positional_ptr, optional_ptr]
  end

  rect rgba(60, 179, 113, 0.5)
    note over sysop,native: Bridge encoding (sys_native / WASM)
    sysop->>native: unpack [positional_array, optional_map]
    native->>native: build_to_host_call → BamlToHostCall bytes
    native->>native: fire_dispatch(args_bytes)
  end

  rect rgba(210, 105, 30, 0.5)
    note over native,host: Bridge decoding (Go / Node.js / Python)
    sdk->>sdk: unmarshal BamlToHostCall
    sdk->>sdk: Node.js: reshapeHostArgs → [...positional, $opts?]
    sdk->>sdk: Python: (positional_tuple, kwargs_dict)
    sdk->>sdk: Go: rawArgs from GetArgs()
    sdk->>host: callback invocation with shaped args
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • BoundaryML/baml#3571: Both PRs change the host-callable dispatch machinery around the VM's HostClosure/SysOp::BamlHostCallHostValue (including HostClosure metadata/parameter handling and the host-call payload/decoding path), so this PR's argument-packaging changes build directly on the host-value infrastructure introduced in #3571.

Poem

🐇 Hop, hop, the optional args now flow,
From VM's pack to bridge below!
$opts for TypeScript, kwargs in Python's land,
BamlToHostCall — a careful hand.
Omitted params? Dropped on the wire.
Defaults applied, as hosts desire! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: support for host callables (callbacks) with optional arguments in bridge implementations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sam/callbacks-optargs

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.43.0)
baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 57515579ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +511 to +512
const head = rawArgs.slice(0, required);
const tail = rawArgs.slice(required);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Walk params instead of slicing required args

When a callable type declares an optional parameter before a required one, e.g. (x?: int, y: int) -> string, the engine still builds the host-call arg list in parameter order from the call plan, so a named call supplies raw args as [x, y]. This reshape counts all required params and slices that many values from the front, so x is delivered as the positional y argument and the real y is folded into $opts.x/lost. The parser/TIR allow this parameter order for function types, so the adapter needs to walk params and rawArgs together rather than assuming all required parameters are leading.

Useful? React with 👍 / 👎.

Comment on lines +1699 to +1702
if p.mode == baml_codegen_types::CodegenFunctionParamMode::Optional {
write!(sig, ", {pname}: {pty} = ...").unwrap();
} else {
write!(sig, ", {pname}: {pty}").unwrap();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid default-before-required protocol signatures

For a valid callable type with an optional parameter before a required one, such as (x?: int, y: int) -> string, this emits def __call__(self, x: int = ..., y: int), which is invalid Python syntax because a non-default argument follows a default argument. That makes the generated .pyi unusable for any leaf exposing such a callback type; the Protocol signature needs to be rendered in a Python-valid order/convention instead of preserving the optional-before-required order with defaults.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
baml_language/sdks/python/rust/bridge_python/src/host_value.rs (2)

213-217: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update host_dispatch_callback doc to describe the new BamlHostDispatch envelope format.

The doc comment still describes args as a "protobuf-encoded BamlOutboundValue", but the implementation now expects a BamlHostDispatch envelope (see lines 364-371 where it parses BamlHostDispatch and extracts the args field).

📝 Suggested documentation fix
 /// Dispatch a BAML→host call into Python.
 ///
-/// `args` is a protobuf-encoded `BamlOutboundValue` whose variant is a
-/// `BamlValueList` (see `sys_native::host_impls::call_host_value` —
-/// args are wrapped as `BexExternalValue::Array` before encoding).
+/// `args` is a protobuf-encoded `BamlHostDispatch` envelope whose `args`
+/// field contains a list-shaped `BamlOutboundValue` (see
+/// `sys_native::host_impls::call_host_value`).
 #[expect(
🤖 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/sdks/python/rust/bridge_python/src/host_value.rs` around lines
213 - 217, Update the documentation comment for the host_dispatch_callback
function to accurately reflect the current implementation. The doc comment
currently describes args as a protobuf-encoded BamlOutboundValue, but the
implementation now expects a BamlHostDispatch envelope from which the args field
is extracted during parsing. Replace the outdated description with an accurate
one that references the BamlHostDispatch envelope format and explains that args
is extracted from this envelope structure.

12-16: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update file header documentation to reflect the new envelope-based wire format.

Step 2 in the dispatch callback description still references decoding BamlOutboundValue directly, but the implementation now first parses a BamlHostDispatch envelope (lines 364-371) and then extracts its args field before decoding.

📝 Suggested documentation update
 /// The dispatch callback:
 /// 1. Looks up the Python callable by `host_value_key`.
-/// 2. Decodes the `BamlOutboundValue` args into Python values via
-///    `baml_core.proto._decode_value_holder` (already a list shape).
+/// 2. Parses the `BamlHostDispatch` envelope and decodes its `args` field
+///    (a list-shaped `BamlOutboundValue`) into Python values via
+///    `baml_core.proto.decode_value`.
 /// 3. Invokes the callable. If the return is a coroutine, runs it to
🤖 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/sdks/python/rust/bridge_python/src/host_value.rs` around lines
12 - 16, The file header documentation at the top of the file describing the
dispatch callback process is outdated. Update the documentation in the comment
block (lines 12-16) to reflect the new envelope-based wire format. Instead of
step 2 describing direct decoding of BamlOutboundValue, update it to first
mention parsing the BamlHostDispatch envelope (as seen in the implementation
around lines 364-371), then extracting the args field from that envelope, and
finally decoding those args via baml_core.proto._decode_value_holder. This will
align the documentation with the actual implementation flow.
🧹 Nitpick comments (1)
baml_language/crates/bridge_ctypes/src/value_encode.rs (1)

456-480: ⚡ Quick win

Add focused unit tests for the new dispatch/type helpers.

function_ty_to_proto and host_dispatch_envelope define cross-bridge wire shape, but this file’s tests don’t directly lock their behavior yet. Please add unit tests that assert: (1) function params preserve name/optional/type mapping, (2) non-function inputs return None, and (3) host_dispatch_envelope sets args + callee_type as expected.

🤖 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/bridge_ctypes/src/value_encode.rs` around lines 456 -
480, Add unit tests at the end of this file to lock the behavior of
function_ty_to_proto and host_dispatch_envelope. Create tests that verify
function_ty_to_proto correctly extracts and maps function parameters (preserving
their name, optional, and type attributes) when given a RuntimeTy::Function,
returns None for non-function types, and that host_dispatch_envelope correctly
populates both the args field with the input BamlOutboundValue and the
callee_type field by calling function_ty_to_proto on the provided RuntimeTy.
🤖 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.

Inline comments:
In `@baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts`:
- Around line 469-477: The functions `decodeHostDispatch` and `reshapeHostArgs`
are silently coercing or dropping arguments instead of validating dispatch
arity. In `decodeHostDispatch`, instead of treating a missing or falsy `args`
field as an empty list, add validation to ensure the decoded arguments match the
expected arity for the callable. In `reshapeHostArgs`, instead of silently
dropping overflow optional-tail values when the rawArgs length exceeds declared
optional parameters, add validation that throws an error when the argument count
does not match the expected arity. This will surface contract violations rather
than silently mis-mapping callback arguments.

In `@baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs`:
- Around line 171-173: The FQN leaf segment obtained from the fqn_leaf function
call (which assigns to the owner variable) and the arg.name references contain
unsanitized characters including potential $ companion suffixes that are invalid
in Python identifiers. Apply sanitization to the owner variable after the
fqn_leaf call at line 171 and to arg.name when it is used in the format string
at line 173, as well as to parameter names at lines 187 and 1872 where callback
Protocol bases are being generated. Ensure all identifiers used in the Protocol
class names in the .pyi output contain only valid Python identifier characters.

---

Outside diff comments:
In `@baml_language/sdks/python/rust/bridge_python/src/host_value.rs`:
- Around line 213-217: Update the documentation comment for the
host_dispatch_callback function to accurately reflect the current
implementation. The doc comment currently describes args as a protobuf-encoded
BamlOutboundValue, but the implementation now expects a BamlHostDispatch
envelope from which the args field is extracted during parsing. Replace the
outdated description with an accurate one that references the BamlHostDispatch
envelope format and explains that args is extracted from this envelope
structure.
- Around line 12-16: The file header documentation at the top of the file
describing the dispatch callback process is outdated. Update the documentation
in the comment block (lines 12-16) to reflect the new envelope-based wire
format. Instead of step 2 describing direct decoding of BamlOutboundValue,
update it to first mention parsing the BamlHostDispatch envelope (as seen in the
implementation around lines 364-371), then extracting the args field from that
envelope, and finally decoding those args via
baml_core.proto._decode_value_holder. This will align the documentation with the
actual implementation flow.

---

Nitpick comments:
In `@baml_language/crates/bridge_ctypes/src/value_encode.rs`:
- Around line 456-480: Add unit tests at the end of this file to lock the
behavior of function_ty_to_proto and host_dispatch_envelope. Create tests that
verify function_ty_to_proto correctly extracts and maps function parameters
(preserving their name, optional, and type attributes) when given a
RuntimeTy::Function, returns None for non-function types, and that
host_dispatch_envelope correctly populates both the args field with the input
BamlOutboundValue and the callee_type field by calling function_ty_to_proto on
the provided RuntimeTy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1a0f9d4d-951e-473e-92f2-3cda66494ef1

📥 Commits

Reviewing files that changed from the base of the PR and between 1581adc and 5751557.

⛔ Files ignored due to path filters (12)
  • baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__01_lexer__callback_param_defaults.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__02_parser__callback_param_defaults.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/src/compiler2_tir/snapshots/baml_tests__compiler2_tir__phase5__snapshot_baml_package_items.snap is excluded by !**/*.snap
  • baml_language/sdks/go/bridge_go/cffi/proto/baml_core/cffi/v1/baml_outbound.pb.go is excluded by !**/*.pb.go
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.d.ts.map is excluded by !**/dist/**, !**/*.map
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.js is excluded by !**/dist/**
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.js.map is excluded by !**/dist/**, !**/*.map
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.d.ts is excluded by !**/dist/**
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.js is excluded by !**/dist/**
  • baml_language/sdks/python/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (26)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_host/host.baml
  • baml_language/crates/baml_tests/projects/broken_syntax/optional_parameter_defaults/callback_param_defaults.baml
  • baml_language/crates/bex_engine/src/conversion.rs
  • baml_language/crates/bex_engine/tests/host_value_callable.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/bex_vm_types/src/types.rs
  • baml_language/crates/bridge_ctypes/src/lib.rs
  • baml_language/crates/bridge_ctypes/src/value_encode.rs
  • baml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.proto
  • baml_language/crates/bridge_wasm/src/host_value.rs
  • baml_language/crates/sys_native/src/host_impls.rs
  • baml_language/crates/sys_ops/src/lib.rs
  • baml_language/sdk_tests/crates/python_pydantic2/function_calls/customizable/test_host_callables.py
  • baml_language/sdk_tests/crates/typescript_node/function_calls/customizable/host_callables.test.ts
  • baml_language/sdk_tests/fixtures/function_calls/baml_src/ns_host_callable_tests/main.baml
  • baml_language/sdks/go/bridge_go/pkg/host_value.go
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.d.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/leaf.rs
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/translate_ty.rs
  • baml_language/sdks/python/rust/bridge_python/src/host_value.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyi

Comment thread baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts Outdated
Comment thread baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs Outdated
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@github-actions

Copy link
Copy Markdown

No description provided.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

1 similar comment
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@baml_language/crates/bex_engine/tests/host_value_callable.rs`:
- Around line 218-222: The code in the host_value_callable.rs test uses
filter_map on to_host_args.args which silently drops any args where the value
field is None, masking potential wire-format regressions. Replace the filter_map
call with map combined with expect() or unwrap() to fail fast when encountering
a decoded arg with a missing value field, ensuring that malformed arguments are
caught immediately rather than being silently filtered out.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6523747e-905f-445a-a8b5-d236a3b5d2d0

📥 Commits

Reviewing files that changed from the base of the PR and between 4c94c56 and 66c1a94.

⛔ Files ignored due to path filters (12)
  • baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__01_lexer__callback_param_defaults.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__02_parser__callback_param_defaults.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/broken_syntax/optional_parameter_defaults/baml_tests__broken_syntax__optional_parameter_defaults__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/src/compiler2_tir/snapshots/baml_tests__compiler2_tir__phase5__snapshot_baml_package_items.snap is excluded by !**/*.snap
  • baml_language/sdks/go/bridge_go/cffi/proto/baml_core/cffi/v1/baml_outbound.pb.go is excluded by !**/*.pb.go
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.d.ts.map is excluded by !**/dist/**, !**/*.map
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.js is excluded by !**/dist/**
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto.js.map is excluded by !**/dist/**, !**/*.map
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.d.ts is excluded by !**/dist/**
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.js is excluded by !**/dist/**
  • baml_language/sdks/python/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (26)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_host/host.baml
  • baml_language/crates/baml_tests/projects/broken_syntax/optional_parameter_defaults/callback_param_defaults.baml
  • baml_language/crates/bex_engine/src/conversion.rs
  • baml_language/crates/bex_engine/tests/host_value_callable.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/bex_vm_types/src/types.rs
  • baml_language/crates/bridge_ctypes/src/lib.rs
  • baml_language/crates/bridge_ctypes/src/value_encode.rs
  • baml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.proto
  • baml_language/crates/bridge_wasm/src/host_value.rs
  • baml_language/crates/bridge_wasm/tests/host_callable.rs
  • baml_language/crates/sys_native/src/host_impls.rs
  • baml_language/sdk_tests/crates/python_pydantic2/function_calls/customizable/test_host_callables.py
  • baml_language/sdk_tests/crates/typescript_node/function_calls/customizable/host_callables.test.ts
  • baml_language/sdk_tests/fixtures/function_calls/baml_src/ns_host_callable_tests/main.baml
  • baml_language/sdks/go/bridge_go/pkg/host_value.go
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.d.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/leaf.rs
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/translate_ty.rs
  • baml_language/sdks/python/rust/bridge_python/src/host_value.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyi
✅ Files skipped from review due to trivial changes (4)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_host/host.baml
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.d.ts
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.py
🚧 Files skipped from review as they are similar to previous changes (19)
  • baml_language/sdks/python/src/baml_core/cffi/v1/baml_outbound_pb2.pyi
  • baml_language/sdk_tests/fixtures/function_calls/baml_src/ns_host_callable_tests/main.baml
  • baml_language/crates/bridge_ctypes/src/lib.rs
  • baml_language/sdk_tests/crates/typescript_node/function_calls/customizable/host_callables.test.ts
  • baml_language/crates/baml_tests/projects/broken_syntax/optional_parameter_defaults/callback_param_defaults.baml
  • baml_language/crates/bex_vm_types/src/types.rs
  • baml_language/crates/bridge_ctypes/types/baml_core/cffi/v1/baml_outbound.proto
  • baml_language/sdks/go/bridge_go/pkg/host_value.go
  • baml_language/sdks/python/rust/bridge_python/src/host_value.rs
  • baml_language/crates/bridge_wasm/tests/host_callable.rs
  • baml_language/crates/sys_native/src/host_impls.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs
  • baml_language/crates/bridge_wasm/src/host_value.rs
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/leaf.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto.ts
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/leaf.rs
  • baml_language/crates/bex_engine/src/conversion.rs
  • baml_language/sdks/nodejs/sdkgen_typescript_node/src/translate_ty.rs

Comment thread baml_language/crates/bex_engine/tests/host_value_callable.rs Outdated
@sxlijin sxlijin changed the title Sam/callbacks optargs feat: support providing host callables as lambdas with optional args Jun 18, 2026
@sxlijin sxlijin changed the title feat: support providing host callables as lambdas with optional args feat(bridges): support providing host callables as lambdas with optional args Jun 18, 2026
@sxlijin sxlijin force-pushed the sam/callbacks-optargs branch from 9b4c96b to fc3b3a4 Compare June 18, 2026 21:46
@sxlijin sxlijin added this pull request to the merge queue Jun 18, 2026
Merged via the queue into canary with commit 326de95 Jun 18, 2026
54 checks passed
@sxlijin sxlijin deleted the sam/callbacks-optargs branch June 18, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant