Skip to content

Conversation

dexhorthy
Copy link
Contributor

@dexhorthy dexhorthy commented Aug 17, 2025

What problem(s) was I solving?

The BAML runtime needed WebAssembly support to enable browser-based execution. Previously, BAML only supported server-side runtimes (Python, Ruby, Node.js). This PR implements WASM compilation of the FFI layer and creates a TypeScript client that can load and execute BAML functions directly in web browsers.

Screenshot 2025-08-16 at 6 16 02 PM

What user-facing changes did I ship?

  • New WASM build target for the BAML FFI layer that compiles to WebAssembly
  • TypeScript client library (language_client_wasm) for browser environments
  • Browser-compatible async runtime that works with JavaScript's event loop
  • Test harness with multiple HTML test files for validating WASM functionality

How I implemented it

Implemented a 5-phase approach:

  1. WASM Compilation Infrastructure: Added conditional compilation with cfg(target_arch = "wasm32") and wasm-bindgen support
  2. Async Runtime Adaptation: Created platform-agnostic AsyncRuntime that uses Tokio on native and spawn_local on WASM
  3. TypeScript Protobuf Layer: Added encoding/decoding utilities for converting between JavaScript and BAML types
  4. WASM Runtime Client: Built BamlWasmRuntime class with module loading and function invocation
  5. Testing & Integration: Created comprehensive browser test suite with memory management validation

Key technical decisions:

  • Used feature flags (native vs wasm) to conditionally compile platform-specific code
  • Implemented JavaScript callback bridge through window.__baml_callbacks registry
  • Added comprehensive debug logging for WASM-specific code paths
  • Created multiple test HTML files for different scenarios (simple, callbacks, LLM calls)

Built in close collaboration with @hellovai who sat in my apartment and shouted at claude with me all day

plan/Research artifacts in thoughts/ can be removed once they get put in a good location, leaving them in for now

How to verify it

To verify the WASM implementation:

  1. Build WASM module: cd engine/language_client_cffi && ./build_wasm.sh
  2. Build TypeScript client: cd engine/language_client_wasm && npm run build
  3. Start test server: python3 -m http.server 3000 in engine/language_client_wasm
  4. Open browser to http://localhost:3000/test-llm-call.html or http://localhost:3000/test.html
  5. Verify all tests pass in browser console

Current status:

  • ✅ WASM module compiles and loads (11.37 MB)
  • ✅ Runtime creation works with simple BAML functions
  • ✅ Encoding/decoding works for all basic types
  • ✅ Memory management test passes (10 create/destroy cycles)
  • ⚠️ Protobuf serialization using JSON placeholder (production needs real protobuf)
  • ⚠️ Provider configurations need real credentials for full testing

Description for the changelog

Add WebAssembly support for BAML runtime, enabling browser-based execution of BAML functions through a new TypeScript client library

dexhorthy and others added 5 commits August 16, 2025 15:21
- Add comprehensive implementation plan for WASM FFI TypeScript client
- Include 5-phase approach: compilation, async runtime, protobuf, client, testing
- Add original research findings on WASM compatibility
- Mark Phase 1 & 2 as complete with verification steps
Phase 1: WASM Compilation Infrastructure
- Add dual-target compilation support (C FFI + WASM) in Cargo.toml
- Make tokio/tokio-util optional, only for native builds
- Add WASM-specific dependencies (wasm-bindgen, js-sys, web-sys)
- Create build_wasm.sh script for WASM compilation
- Make baml-cli optional to exclude from WASM builds

Phase 2: Async Runtime Adaptation
- Create AsyncRuntime abstraction for platform-agnostic spawning
- Replace direct tokio::runtime usage with AsyncRuntime::spawn_local
- Add conditional compilation for libc types (c_char, c_int, c_void)
- Add WASM-bindgen exports for runtime creation and function calls
- Fix either crate imports for WASM compatibility

Both native and WASM targets now compile successfully:
- Native: cargo build --release
- WASM: cargo build --target wasm32-unknown-unknown --no-default-features --features wasm
- Generated WASM module size: ~11MB
Completed implementation of WASM FFI support for BAML runtime to enable
browser-based execution. This includes:

Phase 1: WASM Compilation Infrastructure
- Updated Cargo.toml with WASM target dependencies
- Created dual-target build system (native + WASM)
- Added build_wasm.sh script for WASM compilation

Phase 2: Async Runtime Adaptation
- Created platform-agnostic AsyncRuntime abstraction
- Replaced Tokio spawns with conditional compilation
- Implemented spawn_local for WASM compatibility

Phase 3: TypeScript Protobuf Layer
- Added TypeScript protobuf generation to build.rs
- Created buf.gen.yaml configuration
- Implemented encode.ts and decode.ts modeled after Go client
- Set up language_client_wasm package structure

Phase 4: WASM Runtime Client
- Implemented BamlWasmRuntime class with module loading
- Added WASM-specific exports to lib.rs
- Created promise-based function calling with callbacks
- Implemented streaming support

Current Status:
- WASM builds successfully (11MB)
- TypeScript compilation working
- Module exports configured
- Ready for Phase 5 browser testing

Known Issues:
- Protobuf serialization using JSON placeholder
- Callback mechanism needs completion
- WASM size needs optimization
- Browser testing pending

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add debug logging to async runtime spawn_local for WASM
- Add comprehensive debugging to FFI function calls
- Improve JavaScript callback invocation through window.__baml_callbacks
- Initialize baml_log directly in init_wasm for proper logging setup
- Add MIT license for language_client_cffi
- Fix callback data serialization to JavaScript arrays
- Update runtime.ts to handle global wasmModule and improve callback mechanism
- Add callbacks.js for JavaScript callback management utilities
- Add proto_utils.ts for protobuf serialization helpers
- Expand test.html with comprehensive test suite including memory management
- Add specialized test files for callback, debug, LLM, and simple scenarios
- Update implementation plan with Phase 5 completion and test results
- Document known limitations and production readiness checklist
Copy link

vercel bot commented Aug 17, 2025

@dexhorthy is attempting to deploy a commit to the Boundary Team on Vercel.

A member of the Team first needs to authorize it.

@dexhorthy dexhorthy changed the title Wasm Initial pass at wasm support via cffi Aug 17, 2025
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