From 08c3f99908cb221259eaccd21e89ffe8d43836e1 Mon Sep 17 00:00:00 2001 From: Chris Watts Date: Thu, 9 Jan 2025 12:03:36 -0800 Subject: [PATCH] chore: remove ai generated readme --- engine/README.md | 246 ---------- engine/baml-lib/README.md | 343 -------------- engine/baml-lib/baml-types/README.md | 163 ------- engine/baml-lib/llm-client/README.md | 218 --------- engine/baml-lib/prompt-parser/README.md | 220 --------- engine/baml-runtime/README.md | 326 ------------- engine/baml-schema-wasm/README.md | 196 -------- engine/bstd/README.md | 215 --------- engine/cli/README.md | 298 ------------ engine/language_client_codegen/README.md | 491 -------------------- engine/language_client_python/README.md | 298 ------------ engine/language_client_ruby/README.md | 346 -------------- engine/language_client_typescript/README.md | 313 ------------- 13 files changed, 3673 deletions(-) delete mode 100644 engine/README.md delete mode 100644 engine/baml-lib/README.md delete mode 100644 engine/baml-lib/baml-types/README.md delete mode 100644 engine/baml-lib/llm-client/README.md delete mode 100644 engine/baml-lib/prompt-parser/README.md delete mode 100644 engine/baml-runtime/README.md delete mode 100644 engine/baml-schema-wasm/README.md delete mode 100644 engine/bstd/README.md delete mode 100644 engine/cli/README.md delete mode 100644 engine/language_client_codegen/README.md delete mode 100644 engine/language_client_python/README.md delete mode 100644 engine/language_client_ruby/README.md delete mode 100644 engine/language_client_typescript/README.md diff --git a/engine/README.md b/engine/README.md deleted file mode 100644 index 2beb319cf..000000000 --- a/engine/README.md +++ /dev/null @@ -1,246 +0,0 @@ -# BAML Engine - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The BAML Engine is the core Rust implementation of the BAML (Boundary AI Markup Language) compiler and runtime system. It processes BAML source files (`.baml`) and generates type-safe client SDKs for multiple programming languages, enabling seamless integration with LLM providers like OpenAI and Anthropic. - -> **Note**: This is the engine implementation documentation. For general BAML usage and getting started, see the [main BAML documentation](../README.md). - -## Quick Links -- [Main Project Documentation](../README.md) -- [Contributing Guidelines](../CONTRIBUTING.md) -- [BAML Documentation](https://docs.boundaryml.com) -- [Discord Community](https://discord.gg/BTNBeXGuaS) - -## Overview - -BAML outperforms traditional methods for obtaining structured data from LLMs, even with GPT-3.5, and surpasses models fine-tuned for tool use on the [Berkeley Function Calling Benchmark](https://gorilla.cs.berkeley.edu/leaderboard.html). The engine is responsible for: - -1. **Compilation**: Converting BAML source files into type-safe SDKs -2. **Runtime**: Managing LLM interactions, retries, and streaming -3. **Type Safety**: Ensuring robust parsing and validation of LLM responses -4. **Code Generation**: Producing idiomatic code for multiple languages - -## Architecture Overview - -For a detailed overview of BAML's architecture and design principles, see our [Architecture Documentation](../docs/architecture.md). - -``` -┌─────────────────┐ ┌──────────────────┐ ┌────────────────────┐ -│ BAML Source │ │ BAML Engine │ │ Language Clients │ -│ (.baml) │────▶│ (Rust Compiler) │────▶│ Python/TS/Ruby/... │ -└─────────────────┘ └──────────────────┘ └────────────────────┘ - │ │ - │ │ - ▼ ▼ - ┌──────────────┐ ┌──────────────┐ - │ IR + Types │ │ LLM Provider │ - │ Validation │ │ Runtime │ - └──────────────┘ └──────────────┘ -``` - -## Project Structure - -The engine is organized into several key components: - -### Core Components - -- [**baml-lib/**](baml-lib/README.md) - Core compiler and type system - - Parser and AST handling - - Type system implementation - - Code generation framework - - Intermediate representation (IR) - -- [**baml-runtime/**](baml-runtime/README.md) - Runtime engine - - LLM provider integrations (OpenAI, Anthropic, etc.) - - Function execution and retry logic - - Response streaming and caching - - Error handling and recovery - -- [**bstd/**](bstd/README.md) - Standard library - - Common text processing functions - - JSON manipulation utilities - - Standard type definitions - - Shared runtime utilities - -### Language Clients - -- [**language_client_python/**](language_client_python/README.md) - - PyO3-based Python bindings - - Zero-copy data transfer - - Pydantic model integration - - Async/await support - -- [**language_client_typescript/**](language_client_typescript/README.md) - - Node-API (N-API) bindings - - Promise-based async support - - ESM and CommonJS compatibility - - TypeScript type definitions - -- [**language_client_ruby/**](language_client_ruby/README.md) - - FFI-based Ruby bindings - - Fiber-based async support - - Gem packaging - - Ruby type system integration - -### Web Integration - -- [**baml-schema-wasm/**](baml-schema-wasm/README.md) - - WebAssembly bindings - - Browser-based schema validation - - Streaming response support - - TypeScript integration - -### Code Generation - -- [**language_client_codegen/**](language_client_codegen/README.md) - - Language-specific code generators - - Template system - - Type mappings - - Client SDK generation - -For a comprehensive guide on how code generation works, see our [Code Generation Guide](../docs/code-generation.md). - -## Prerequisites - -Required tools (with installation links): - -- [Rust toolchain](https://rustup.rs/) (latest stable version) -- [mise](https://mise.jdx.dev/getting-started.html) for version management -- [direnv](https://direnv.net/docs/installation.html) for environment management -- [clang](https://clang.llvm.org/get_started.html) for native extensions - -Language-specific requirements: -- Python: `pip install maturin pytest` -- TypeScript: `npm install -g pnpm` -- Ruby: `gem install bundler` -- WebAssembly: `curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh` - -## Quick Start - -1. **Setup Environment**: -```bash -# Install dependencies -brew install mise direnv llvm # macOS -# or -apt install direnv clang # Ubuntu - -# Configure shell -echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc -echo 'eval "$(mise activate zsh)"' >> ~/.zshrc -``` - -2. **Build Engine**: -```bash -cd engine -cargo build -``` - -3. **Run Tests**: -```bash -# Unit tests -cargo test - -# Integration tests -cd ../integ-tests && ./run-tests.sh -``` - -## Development Workflow - -1. **Compiler Development** (baml-lib): - - Modify parser in `baml-lib/src/parser` - - Update type system in `baml-lib/src/types` - - Run `cargo test` in `baml-lib` - -2. **Runtime Development** (baml-runtime): - - Add/modify providers in `baml-runtime/src/providers` - - Update runtime features in `baml-runtime/src/runtime` - - Test with `cargo test` in `baml-runtime` - -3. **Language Client Development**: - - Python: Use `maturin develop` for rapid testing - - TypeScript: Use `pnpm build:debug` for development - - Ruby: Use `bundle exec rake compile` for building - -4. **Integration Testing**: - ```bash - # Full integration test suite - cd ../integ-tests && ./run-tests.sh - - # Language-specific tests - cd ../integ-tests/typescript && pnpm test - cd ../integ-tests/python && pytest - cd ../integ-tests/ruby && bundle exec rake test - ``` - -## Common Development Tasks - -### Adding a New Language Client - -1. Create new directory: `language_client_` -2. Implement FFI/bindings using appropriate tool: - - Python: PyO3 - - TypeScript: Node-API - - Ruby: FFI -3. Add language-specific type conversions -4. Implement async runtime support -5. Add tests and documentation - -### Adding a New LLM Provider - -1. Add provider module in `baml-runtime/src/providers` -2. Implement provider trait -3. Add configuration options -4. Add integration tests -5. Update documentation - -### Modifying the Type System - -1. Update AST definitions in `baml-lib/src/ast` -2. Modify type checker in `baml-lib/src/types` -3. Update code generation templates -4. Add test cases -5. Update documentation - -## Contributing - -1. Read the [main contributing guidelines](../CONTRIBUTING.md) -2. Join our [Discord community](https://discord.gg/BTNBeXGuaS) -3. Check component-specific documentation -4. Submit PRs with appropriate tests - -## Debugging - -Each component has specific debugging instructions in its README. Common tools: - -1. **Rust Debugging**: -```bash -RUST_LOG=debug cargo test -RUST_BACKTRACE=1 cargo run -``` - -2. **Language Client Debugging**: -```bash -# Python -RUST_LOG=debug pytest -vv - -# TypeScript -DEBUG=baml:* pnpm test - -# Ruby -BAML_LOG=debug bundle exec rake test -``` - -3. **Integration Test Debugging**: -```bash -# Enable verbose output -BAML_DEBUG=1 ./run-tests.sh -``` - -## License - -Apache License 2.0 - See [LICENSE](LICENSE) for details \ No newline at end of file diff --git a/engine/baml-lib/README.md b/engine/baml-lib/README.md deleted file mode 100644 index fc1617e0e..000000000 --- a/engine/baml-lib/README.md +++ /dev/null @@ -1,343 +0,0 @@ -# BAML Library - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The BAML Library is the core library for parsing, analyzing, and transforming BAML source code. It provides the foundation for the BAML compiler and language services. - -## Features - -- BAML parser and lexer -- Type system -- AST manipulation -- Code analysis -- Semantic validation -- Error diagnostics -- Language services - -## Architecture - -### Components - -``` -baml-lib/ -├── src/ -│ ├── parser/ # BAML parser implementation -│ │ ├── lexer.rs # Lexical analysis -│ │ ├── grammar.rs # Grammar definition -│ │ └── ast.rs # Abstract Syntax Tree -│ ├── types/ # Type system -│ │ ├── checker.rs # Type checking -│ │ ├── inference.rs # Type inference -│ │ └── validation.rs # Type validation -│ ├── analysis/ # Code analysis -│ │ ├── semantics.rs # Semantic analysis -│ │ └── linting.rs # Linting rules -│ └── services/ # Language services -├── tests/ # Test suite -└── examples/ # Example usage -``` - -### Core Concepts - -1. **Parser** - - Lexical analysis - - Syntax parsing - - AST construction - -2. **Type System** - - Type checking - - Type inference - - Validation rules - -3. **Analysis** - - Semantic analysis - - Code validation - - Error reporting - -## Usage - -### Basic Example - -```rust -use baml_lib::{Parser, TypeChecker, Analyzer}; - -fn main() -> Result<(), Box> { - // Parse BAML source - let source = r#" - class User { - name: string; - age: int; - } - "#; - - let ast = Parser::new().parse(source)?; - - // Type check - let checker = TypeChecker::new(); - checker.check(&ast)?; - - // Analyze - let analyzer = Analyzer::new(); - let diagnostics = analyzer.analyze(&ast)?; - - println!("Diagnostics: {:?}", diagnostics); - Ok(()) -} -``` - -### AST Manipulation - -```rust -use baml_lib::ast::{Node, Visitor}; - -struct MyVisitor; - -impl Visitor for MyVisitor { - fn visit_class(&mut self, class: &mut Class) { - // Manipulate class node - println!("Visiting class: {}", class.name); - - // Visit children - for field in &mut class.fields { - self.visit_field(field); - } - } -} - -let mut visitor = MyVisitor; -ast.accept(&mut visitor); -``` - -## Development - -### Prerequisites - -- Rust toolchain -- LLVM development libraries -- Testing utilities - -### Setup - -```bash -# Install dependencies -cargo build - -# Run tests -cargo test - -# Run examples -cargo run --example parser -``` - -## Adding Features - -### 1. New Syntax Feature - -1. Update grammar: -```rust -// src/parser/grammar.rs - -pub enum Node { - // Add new node type - NewFeature(NewFeatureNode), -} - -pub struct NewFeatureNode { - pub keyword: Token, - pub name: Identifier, - pub body: Block, -} -``` - -2. Add parser implementation: -```rust -// src/parser/parser.rs - -impl Parser { - fn parse_new_feature(&mut self) -> Result { - self.expect(TokenKind::NewFeature)?; - let name = self.parse_identifier()?; - let body = self.parse_block()?; - - Ok(NewFeatureNode { - keyword: self.previous(), - name, - body, - }) - } -} -``` - -### 2. New Type Feature - -1. Add type definition: -```rust -// src/types/types.rs - -#[derive(Debug, Clone)] -pub enum Type { - NewType(NewTypeInfo), -} - -pub struct NewTypeInfo { - pub name: String, - pub constraints: Vec, -} -``` - -2. Implement type checking: -```rust -// src/types/checker.rs - -impl TypeChecker { - fn check_new_type(&mut self, node: &NewTypeNode) -> Result { - let constraints = self.check_constraints(&node.constraints)?; - Ok(Type::NewType(NewTypeInfo { - name: node.name.to_string(), - constraints, - })) - } -} -``` - -## Testing - -### Unit Tests - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parser() { - let source = r#" - class Test { - field: string; - } - "#; - - let ast = Parser::new().parse(source).unwrap(); - assert_eq!(ast.classes.len(), 1); - } -} -``` - -### Integration Tests - -```rust -#[test] -fn test_full_pipeline() { - let source = read_test_file("test.baml"); - let ast = Parser::new().parse(&source).unwrap(); - let checker = TypeChecker::new(); - checker.check(&ast).unwrap(); - let analyzer = Analyzer::new(); - let diagnostics = analyzer.analyze(&ast).unwrap(); - assert!(diagnostics.is_empty()); -} -``` - -## Error Handling - -```rust -#[derive(Debug, Error)] -pub enum LibError { - #[error("Parse error: {0}")] - Parse(String), - - #[error("Type error: {0}")] - Type(String), - - #[error("Analysis error: {0}")] - Analysis(String), -} - -impl Diagnostic for LibError { - fn message(&self) -> String { - match self { - LibError::Parse(msg) => format!("Parse error: {}", msg), - LibError::Type(msg) => format!("Type error: {}", msg), - LibError::Analysis(msg) => format!("Analysis error: {}", msg), - } - } -} -``` - -## Language Services - -### Code Completion - -```rust -use baml_lib::services::completion::{CompletionProvider, Suggestion}; - -impl CompletionProvider { - pub fn get_suggestions( - &self, - source: &str, - position: Position, - ) -> Vec { - let ast = self.parser.parse(source).unwrap(); - let node = ast.node_at(position); - self.suggest_completions(node) - } -} -``` - -### Diagnostics - -```rust -use baml_lib::services::diagnostics::{DiagnosticProvider, Diagnostic}; - -impl DiagnosticProvider { - pub fn get_diagnostics(&self, source: &str) -> Vec { - let ast = self.parser.parse(source).unwrap(); - let mut diagnostics = Vec::new(); - - // Collect syntax errors - diagnostics.extend(ast.errors()); - - // Collect type errors - let checker = TypeChecker::new(); - if let Err(e) = checker.check(&ast) { - diagnostics.push(e.into()); - } - - diagnostics - } -} -``` - -## Best Practices - -1. **Parser Design** - - Handle all edge cases - - Provide clear errors - - Support recovery - -2. **Type System** - - Strict type checking - - Clear validation rules - - Helpful error messages - -3. **Analysis** - - Efficient algorithms - - Useful diagnostics - - Performance optimization - -4. **Testing** - - Unit test coverage - - Integration tests - - Benchmark tests - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow library guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review \ No newline at end of file diff --git a/engine/baml-lib/baml-types/README.md b/engine/baml-lib/baml-types/README.md deleted file mode 100644 index a84024228..000000000 --- a/engine/baml-lib/baml-types/README.md +++ /dev/null @@ -1,163 +0,0 @@ -# BAML Type System - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The type system is responsible for ensuring that LLM outputs match your expected types and schemas. It provides rich type checking, validation, and runtime value representation. - -## Type Hierarchy - -```rust -pub enum FieldType { - Primitive(TypeValue), // string, int, float, bool - Enum(String), // Named enums with variants - Class(String), // Structured data types - List(Box), // Arrays - Map(Box, Box), // Key-value maps - Union(Vec), // Type alternatives - Optional(Box), // Nullable types -} -``` - -## Runtime Values - -```rust -pub enum BamlValue { - String(String), - Int(i64), - Float(f64), - Bool(bool), - Map(BamlMap), // Structured data - List(Vec), // Arrays - Media(BamlMedia), // Images/Audio - Enum(String, String), // Enum variants - Class(String, BamlMap), // Class instances - Null, -} -``` - -## Media Types - -```rust -pub struct BamlMedia { - pub media_type: BamlMediaType, // Image or Audio - pub mime_type: Option, // e.g., "image/png" - pub content: BamlMediaContent, // File, URL, or Base64 -} -``` - -## Development - -### Adding a New Type - -1. Add variant to `FieldType` enum in `field_type/mod.rs` -2. Implement type checking and validation: - ```rust - impl FieldType { - pub fn validate(&self, value: &BamlValue) -> Result<()> { - match (self, value) { - // Type-specific validation rules - } - } - } - ``` -3. Add runtime value support in `BamlValue` -4. Update serialization/deserialization -5. Add test cases in `tests/` - -### Testing - -```bash -# Run all type system tests -cd ./engine - -cargo test -p baml-types - -# Run specific test suite -cargo test -p baml-types field_type -cargo test -p baml-types baml_value -``` - -## Error Handling - -Rich error reporting with source locations: - -```rust -use baml_diagnostics::{Diagnostic, Level}; - -fn report_error(span: Span, message: &str) { - let diagnostic = Diagnostic::new(Level::Error) - .with_message(message) - .with_span(span) - .with_code("E001"); - // Report error with source context -} -``` - -## Examples - -### Basic Types -```baml -class User { - name string - age int - isActive bool - score float -} -``` - -### Enums -```baml -enum Sentiment { - POSITIVE - NEGATIVE - NEUTRAL -} -``` - -### Complex Types -```baml -class Document { - title string - metadata Map - tags string[] - sentiment Sentiment - author User | null -} -``` - -## Integration with Language Clients - -The type system automatically generates appropriate type definitions for each supported language: - -### Python (Pydantic) -```python -class User(BaseModel): - name: str - age: int - is_active: bool - score: float -``` - -### TypeScript -```typescript -interface User { - name: string; - age: number; - isActive: boolean; - score: number; -} -``` - -### Ruby (Sorbet) -```ruby -class User < T::Struct - const :name, String - const :age, Integer - const :is_active, T::Boolean - const :score, Float -end -``` \ No newline at end of file diff --git a/engine/baml-lib/llm-client/README.md b/engine/baml-lib/llm-client/README.md deleted file mode 100644 index c9595f798..000000000 --- a/engine/baml-lib/llm-client/README.md +++ /dev/null @@ -1,218 +0,0 @@ -# BAML LLM Client - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The LLM client manages integrations with various LLM providers, handling authentication, request configuration, and response processing. It provides a unified interface for interacting with different LLM services. - -## Supported Providers - -```rust -pub enum ClientProvider { - OpenAI(OpenAIClientProviderVariant), // Base, Azure, Custom - Anthropic, // Claude models - AwsBedrock, // AWS hosted models - GoogleAi, // Gemini models - Vertex, // PaLM models - Strategy(StrategyClientProvider), // Load balancing -} -``` - -## Authentication - -```rust -pub struct ServiceAccount { - pub token_uri: String, - pub project_id: String, - pub client_email: String, - pub private_key: String, -} - -pub enum AuthMethod { - ApiKey(String), - ServiceAccount(ServiceAccount), - Custom(Box), -} -``` - -## Load Balancing & Resilience - -### Strategies -- Round-robin: Distribute requests across providers -- Fallback: Automatic retry with alternative providers -- Custom role management for different model capabilities - -```baml -// Example configuration -client Resilient_LLM { - provider baml-fallback - options { - strategy [ - GPT4 - Claude - ] - } -} -``` - -### Retry Policies -```baml -retry_policy Resilient { - max_retries 3 - strategy { - type exponential_backoff - initial_delay 1000 - max_delay 30000 - } -} -``` - -## Development - -### Adding a New Provider - -1. Create provider module in `clients/`: - ```rust - pub struct NewProvider { - base_url: StringOr, // API endpoint - api_key: StringOr, // Authentication - model: Option, // Model selection - headers: IndexMap, // Custom headers - properties: IndexMap, // Model parameters - } - ``` - -2. Implement provider traits: - ```rust - impl ClientProvider { - fn create_from(&self, properties: PropertyHandler) -> Result { - let api_key = properties.ensure_api_key(); - let model = properties.ensure_string("model", true); - // Provider-specific setup - } - } - ``` - -3. Add to `ClientProvider` enum and update tests - -### Testing - -```bash -# Test all providers -cargo test -p internal-llm-client - -# Test specific provider -cargo test -p internal-llm-client openai -cargo test -p internal-llm-client anthropic -``` - -## Examples - -### Basic Provider Configuration -```baml -client GPT4 { - provider openai - retry_policy Resilient - options { - model gpt-4 - api_key env.OPENAI_API_KEY - max_tokens 1000 - } -} -``` - -### Azure OpenAI Configuration -```baml -client AzureGPT { - provider openai/azure - options { - model deployment_name - api_key env.AZURE_API_KEY - endpoint env.AZURE_ENDPOINT - } -} -``` - -### AWS Bedrock Configuration -```baml -client Claude3 { - provider aws-bedrock - options { - model anthropic.claude-3-sonnet - region us-west-2 - credentials { - access_key_id env.AWS_ACCESS_KEY_ID - secret_access_key env.AWS_SECRET_ACCESS_KEY - } - } -} -``` - -### Load Balancing Example -```baml -client SmartLLM { - provider baml-strategy - options { - strategy round_robin - providers [ - { - client GPT4 - weight 2 - } - { - client Claude - weight 1 - } - ] - } -} -``` - -## Error Handling - -```rust -#[derive(Debug, Error)] -pub enum LLMError { - #[error("Authentication failed: {0}")] - AuthError(String), - - #[error("Rate limit exceeded: {0}")] - RateLimit(String), - - #[error("Invalid request: {0}")] - InvalidRequest(String), - - #[error("Provider error: {0}")] - ProviderError(String), -} - -impl LLMClient { - pub fn handle_error(&self, error: LLMError) -> Result<()> { - match error { - LLMError::RateLimit(_) => self.retry_with_backoff(), - LLMError::ProviderError(_) => self.try_fallback_provider(), - _ => Err(error), - } - } -} -``` - -## Streaming Support - -```rust -impl LLMClient { - pub async fn stream_completion(&self, request: CompletionRequest) -> Result> { - // Provider-specific streaming implementation - } -} - -// Usage example -let stream = client.stream_completion(request).await?; -tokio::pin!(stream); -while let Some(chunk) = stream.next().await { - println!("Received chunk: {}", chunk); -} -``` \ No newline at end of file diff --git a/engine/baml-lib/prompt-parser/README.md b/engine/baml-lib/prompt-parser/README.md deleted file mode 100644 index 182936b94..000000000 --- a/engine/baml-lib/prompt-parser/README.md +++ /dev/null @@ -1,220 +0,0 @@ -# BAML Template System - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The template system manages prompt templates with variable interpolation, filters, and macros. It uses a Jinja-like syntax for powerful and flexible prompt engineering. - -## Core Components - -### Template Parser -```rust -pub struct TemplateParser { - pub variables: HashSet, // Template variables - pub filters: HashSet, // Custom filters - pub macros: HashMap, // Reusable snippets -} -``` - -### Context Management -```rust -pub struct Context { - pub variables: HashMap, - pub filters: HashMap>, - pub macros: HashMap, - pub env: Environment, -} -``` - -## Features - -### Variable Interpolation -```baml -function ExtractInfo(name: string, age: int) -> PersonInfo { - prompt #" - Extract information about {{ name }}, who is {{ age }} years old. - {{ ctx.output_format }} - "# -} -``` - -### Control Flow -```baml -function GenerateResponse(items: string[]) -> string { - prompt #" - {% for item in items %} - - {{ item }} - {% endfor %} - - {% if items | length > 3 %} - That's quite a list! - {% endif %} - "# -} -``` - -### Custom Filters -```baml -function FormatText(text: string) -> string { - prompt #" - {{ text | lowercase | trim }} - - {% if text | word_count > 100 %} - That's a long text! - {% endif %} - "# -} -``` - -### Macros -```baml -function ComplexPrompt() -> string { - prompt #" - {% macro format_header(title) %} - ===== {{ title | uppercase }} ===== - {% endmacro %} - - {{ format_header("Introduction") }} - Content goes here... - "# -} -``` - -## Development - -### Adding a New Filter - -1. Define the filter function: -```rust -pub struct CustomFilter; - -impl Filter for CustomFilter { - fn apply(&self, value: &Value, args: &[Value]) -> Result { - // Filter implementation - } -} -``` - -2. Register the filter: -```rust -impl Context { - pub fn register_filter(&mut self, name: &str, filter: Box) { - self.filters.insert(name.to_string(), filter); - } -} -``` - -### Adding a New Macro - -1. Define the macro: -```rust -pub struct Macro { - pub name: String, - pub params: Vec, - pub body: Template, -} -``` - -2. Register the macro: -```rust -impl Context { - pub fn register_macro(&mut self, macro_def: Macro) { - self.macros.insert(macro_def.name.clone(), macro_def); - } -} -``` - -## Testing - -```bash -# Run all template tests -cargo test -p prompt-parser - -# Run specific test suites -cargo test -p prompt-parser parser -cargo test -p prompt-parser filters -``` - -## Examples - -### Basic Template -```baml -function Greet(name: string) -> string { - prompt #" - Hello, {{ name }}! - The current time is {{ ctx.now | date_format("%Y-%m-%d") }}. - "# -} -``` - -### Complex Logic -```baml -function AnalyzeData(data: Map) -> Analysis { - prompt #" - {% for key, value in data.items() %} - {% if value > 100 %} - {{ key }} is significantly high at {{ value }}. - {% elif value < 0 %} - {{ key }} is negative at {{ value }}. - {% else %} - {{ key }} is within normal range at {{ value }}. - {% endif %} - {% endfor %} - - {{ ctx.output_format }} - "# -} -``` - -### Environment Variables -```baml -function SecurePrompt() -> string { - prompt #" - Using API key: {{ env.API_KEY | mask }} - Environment: {{ env.ENV_NAME | default("development") }} - "# -} -``` - -### Error Handling -```rust -impl Template { - pub fn render(&self, context: &Context) -> Result { - match self.evaluate(context) { - Ok(result) => Ok(result), - Err(e) => { - // Add source location information - let diagnostic = Diagnostic::new(Level::Error) - .with_message(format!("Template error: {}", e)) - .with_span(self.span); - Err(diagnostic.into()) - } - } - } -} -``` - -## Best Practices - -1. **Variable Naming** - - Use descriptive names - - Follow snake_case convention - - Prefix temporary variables with underscore - -2. **Error Messages** - - Include line numbers - - Provide context about the error - - Suggest possible fixes - -3. **Performance** - - Cache compiled templates - - Minimize string allocations - - Use lazy evaluation when possible - -4. **Security** - - Sanitize user input - - Use environment variables for sensitive data - - Implement proper escaping \ No newline at end of file diff --git a/engine/baml-runtime/README.md b/engine/baml-runtime/README.md deleted file mode 100644 index f9586ab53..000000000 --- a/engine/baml-runtime/README.md +++ /dev/null @@ -1,326 +0,0 @@ -# BAML Runtime - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The BAML Runtime is the core execution engine for BAML, providing a high-performance, type-safe interface for executing LLM functions across multiple providers. - -## Features - -- High-performance Rust implementation -- Multi-provider support (OpenAI, Anthropic, etc.) -- Type-safe function execution -- Streaming support -- Retry and error handling -- Async runtime with Tokio -- Cross-platform support - -## Architecture - -### Components - -``` -baml-runtime/ -├── src/ -│ ├── runtime/ # Core runtime implementation -│ │ ├── engine.rs # Execution engine -│ │ ├── types.rs # Type system -│ │ └── providers/ # LLM provider integrations -│ ├── client/ # Client interface -│ │ ├── builder.rs # Client configuration -│ │ └── options.rs # Runtime options -│ └── error.rs # Error handling -├── tests/ # Test suite -└── examples/ # Usage examples -``` - -### Core Concepts - -1. **Runtime Engine** - - Function execution - - Type validation - - Provider management - -2. **Type System** - - Runtime type checking - - Schema validation - - Type conversions - -3. **Provider Interface** - - Provider abstraction - - Connection management - - Rate limiting - -## Usage - -### Basic Example - -```rust -use baml_runtime::{Runtime, Config}; -use baml_types::Value; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Initialize runtime - let runtime = Runtime::new(Config::default())?; - - // Execute function - let result = runtime - .execute_function("ExtractUserInfo", input) - .await?; - - println!("Result: {:?}", result); - Ok(()) -} -``` - -### Streaming Example - -```rust -use futures::StreamExt; - -async fn stream_response(runtime: &Runtime, input: Value) -> Result<()> { - let mut stream = runtime - .stream_function("StreamingFunction", input) - .await?; - - while let Some(chunk) = stream.next().await { - println!("Chunk: {:?}", chunk?); - } - Ok(()) -} -``` - -### Error Handling - -```rust -use baml_runtime::error::{Error, ProviderError}; - -match runtime.execute_function("MyFunction", input).await { - Ok(result) => println!("Success: {:?}", result), - Err(Error::Provider(e)) => { - println!("Provider error: {}, status: {}", e.message, e.status) - } - Err(Error::Validation(e)) => { - println!("Validation error: {:?}", e.errors) - } - Err(e) => println!("Other error: {}", e), -} -``` - -## Development - -### Prerequisites - -- Rust toolchain (1.70+) -- Cargo -- OpenSSL development libraries -- Protobuf compiler - -### Setup - -```bash -# Install dependencies -cargo build - -# Run tests -cargo test - -# Run examples -cargo run --example basic -``` - -## Adding Features - -### 1. New Provider - -1. Create provider module: -```rust -// src/runtime/providers/new_provider.rs - -use async_trait::async_trait; -use crate::provider::{Provider, ProviderResult}; - -pub struct NewProvider { - client: Client, - config: Config, -} - -#[async_trait] -impl Provider for NewProvider { - async fn execute( - &self, - prompt: String, - options: Options, - ) -> ProviderResult { - // Implementation - } - - async fn stream( - &self, - prompt: String, - options: Options, - ) -> ProviderResult> { - // Implementation - } -} -``` - -2. Add provider factory: -```rust -// src/runtime/provider_factory.rs - -impl ProviderFactory { - pub fn create_provider( - &self, - kind: ProviderKind, - config: Config, - ) -> Result> { - match kind { - ProviderKind::New => Ok(Box::new(NewProvider::new(config)?)), - // ... other providers - } - } -} -``` - -### 2. New Runtime Feature - -1. Add feature interface: -```rust -// src/runtime/features.rs - -pub trait RuntimeFeature: Send + Sync { - fn name(&self) -> &str; - fn initialize(&self, runtime: &Runtime) -> Result<()>; - fn cleanup(&self) -> Result<()>; -} -``` - -2. Implement feature: -```rust -pub struct MyFeature { - config: FeatureConfig, -} - -impl RuntimeFeature for MyFeature { - fn name(&self) -> &str { - "my_feature" - } - - fn initialize(&self, runtime: &Runtime) -> Result<()> { - // Implementation - } - - fn cleanup(&self) -> Result<()> { - // Implementation - } -} -``` - -## Testing - -### Unit Tests - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn test_function_execution() { - let runtime = Runtime::new(Config::default()).unwrap(); - let result = runtime - .execute_function("TestFunction", test_input()) - .await - .unwrap(); - assert_eq!(result.field, "expected"); - } -} -``` - -### Integration Tests - -```rust -#[tokio::test] -async fn test_provider_integration() { - let runtime = setup_test_runtime().await; - let result = runtime - .execute_with_provider( - Provider::OpenAI, - "test prompt", - default_options(), - ) - .await - .unwrap(); - assert!(result.is_valid()); -} -``` - -## Performance - -### Concurrency - -```rust -use futures::future::join_all; - -async fn process_batch( - runtime: &Runtime, - inputs: Vec, -) -> Result> { - let futures: Vec<_> = inputs - .into_iter() - .map(|input| runtime.execute_function("BatchFunction", input)) - .collect(); - - let results = join_all(futures).await; - results.into_iter().collect() -} -``` - -### Connection Pooling - -```rust -use baml_runtime::pool::{Pool, PoolConfig}; - -let pool = Pool::new(PoolConfig { - max_size: 10, - min_idle: 2, - max_lifetime: Duration::from_secs(3600), -}); - -let runtime = Runtime::with_pool(pool); -``` - -## Best Practices - -1. **Error Handling** - - Use custom error types - - Provide detailed error info - - Handle all error cases - -2. **Resource Management** - - Use connection pooling - - Implement proper cleanup - - Handle timeouts - -3. **Testing** - - Write unit tests - - Add integration tests - - Test error cases - -4. **Performance** - - Use async/await - - Pool connections - - Batch operations - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow runtime guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review diff --git a/engine/baml-schema-wasm/README.md b/engine/baml-schema-wasm/README.md deleted file mode 100644 index f1b6eb800..000000000 --- a/engine/baml-schema-wasm/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# BAML WebAssembly Schema - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -WebAssembly bindings for BAML schema validation and runtime, enabling browser-based BAML functionality. - -## Components - -``` -baml-schema-wasm/ -├── src/ -│ ├── lib.rs # Wasm module definitions -│ ├── schema.rs # Schema validation -│ ├── runtime.rs # Browser runtime -│ └── utils.rs # Wasm utilities -├── js/ # JavaScript wrapper -│ ├── index.ts # TypeScript entry -│ └── types.ts # Type definitions -└── tests/ # Wasm tests -``` - -## Features - -- Browser-compatible BAML runtime -- Schema validation in the browser -- TypeScript type definitions -- Streaming response support -- Error handling with stack traces - -## Development - -### Prerequisites - -```bash -# Install wasm-pack -curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - -# Install development tools -npm install -``` - -### Building - -```bash -# Development build -wasm-pack build --dev - -# Release build -wasm-pack build --release --target web -``` - -### Testing - -```bash -# Run Wasm tests -wasm-pack test --node - -# Run browser tests -npm test -``` - -## Schema Validation - -### JavaScript Usage - -```typescript -import { BamlSchema } from '@baml/schema-wasm'; - -const schema = new BamlSchema(` - class User { - name string - age int - } -`); - -const isValid = schema.validate({ - name: "John", - age: 30 -}); -``` - -### Wasm Implementation - -```rust -#[wasm_bindgen] -impl BamlSchema { - pub fn validate(&self, value: JsValue) -> Result { - let value: serde_json::Value = value.into_serde()?; - self.schema.validate(&value) - .map_err(|e| JsError::new(&e.to_string())) - } -} -``` - -## Browser Runtime - -### Streaming Support - -```typescript -import { BamlRuntime } from '@baml/schema-wasm'; - -const runtime = new BamlRuntime(); -const stream = runtime.streamResponse(async function* () { - yield "Hello"; - yield "World"; -}); -``` - -### Implementation - -```rust -#[wasm_bindgen] -impl BamlRuntime { - #[wasm_bindgen(js_name = streamResponse)] - pub fn stream_response(&self) -> Result { - let (tx, rx) = futures::channel::mpsc::channel(32); - let stream = wasm_streams::ReadableStream::from_raw(rx); - Ok(stream.into_raw()) - } -} -``` - -## Error Handling - -```rust -// Convert Rust errors to JavaScript -impl From for JsError { - fn from(err: BamlError) -> Self { - JsError::new(&err.to_string()) - } -} -``` - -## Package Configuration - -### package.json - -```json -{ - "name": "@baml/schema-wasm", - "version": "1.0.0", - "type": "module", - "main": "dist/node/index.js", - "module": "dist/web/index.js", - "types": "dist/index.d.ts", - "files": [ - "dist", - "README.md" - ] -} -``` - -## Browser Integration - -### ESM Usage - -```html - -``` - -## Debugging - -1. **Build Issues**: -```bash -# Clean build -rm -rf pkg/ -wasm-pack build --verbose - -# Check wasm-pack version -wasm-pack --version -``` - -2. **Runtime Issues**: -```bash -# Enable debug logging -RUST_LOG=debug wasm-pack test - -# Check browser console -console.log(BamlSchema.version()); -``` - -3. **Common Problems**: -- WebAssembly support in browser -- Memory management issues -- Cross-origin restrictions diff --git a/engine/bstd/README.md b/engine/bstd/README.md deleted file mode 100644 index f0e68896c..000000000 --- a/engine/bstd/README.md +++ /dev/null @@ -1,215 +0,0 @@ -# BAML Standard Library (bstd) - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -Core utilities and standard functions for the BAML language and runtime. - -## Components - -``` -bstd/ -├── src/ -│ ├── lib.rs # Library entry point -│ ├── functions/ # Standard functions -│ │ ├── text.rs # Text processing -│ │ └── json.rs # JSON handling -│ ├── types/ # Common types -│ └── utils/ # Shared utilities -└── tests/ # Standard library tests -``` - -## Features - -- Common text processing functions -- JSON manipulation utilities -- Standard type definitions -- Shared runtime utilities -- Testing helpers - -## Standard Functions - -### Text Processing - -```rust -pub mod text { - /// Split text into chunks with overlap - pub fn chunk_text(text: &str, chunk_size: usize, overlap: usize) -> Vec { - // Implementation - } - - /// Clean and normalize text - pub fn normalize_text(text: &str) -> String { - // Implementation - } -} -``` - -### JSON Handling - -```rust -pub mod json { - /// Merge multiple JSON objects - pub fn merge_json(objects: &[Value]) -> Result { - // Implementation - } - - /// Extract paths from JSON - pub fn json_paths(value: &Value) -> Vec { - // Implementation - } -} -``` - -## Common Types - -```rust -pub mod types { - /// Common response type - #[derive(Debug, Clone)] - pub struct Response { - pub data: T, - pub metadata: Metadata, - } - - /// Standard error types - #[derive(Debug, Error)] - pub enum StdError { - #[error("Invalid input: {0}")] - InvalidInput(String), - #[error("Processing error: {0}")] - Processing(String), - } -} -``` - -## Development - -### Building - -```bash -# Build library -cargo build - -# Build with all features -cargo build --all-features -``` - -### Testing - -```bash -# Run all tests -cargo test - -# Test specific module -cargo test text:: -``` - -## Usage in BAML Projects - -### In BAML Files - -```baml -import bstd.text.chunk_text - -function ProcessText(text: string) -> string[] { - use chunk_text(chunk_size: 1000, overlap: 100) -} -``` - -### In Rust Code - -```rust -use bstd::{text, json, types}; - -fn process_data(input: &str) -> Result> { - let chunks = text::chunk_text(input, 1000, 100); - // Process chunks -} -``` - -## Adding New Features - -### 1. New Function - -```rust -// src/functions/new_module.rs -pub fn new_function(input: &str) -> Result { - // Implementation -} - -#[cfg(test)] -mod tests { - #[test] - fn test_new_function() { - // Test implementation - } -} -``` - -### 2. New Type - -```rust -// src/types/mod.rs -#[derive(Debug, Clone)] -pub struct NewType { - pub field: String, -} - -impl NewType { - pub fn new(field: String) -> Self { - Self { field } - } -} -``` - -## Testing - -### Unit Tests - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_chunk_text() { - let text = "Hello World"; - let chunks = chunk_text(text, 5, 2); - assert_eq!(chunks.len(), 3); - } -} -``` - -### Integration Tests - -```rust -// tests/integration_test.rs -use bstd::{text, json}; - -#[test] -fn test_text_processing() { - let input = "Test input"; - let result = text::process_pipeline(input); - assert!(result.is_ok()); -} -``` - -## Debugging - -1. **Library Issues**: -```bash -# Enable debug logs -RUST_LOG=debug cargo test - -# Check specific module -RUST_LOG=bstd::text=trace cargo test -``` - -2. **Common Problems**: -- Memory allocation in text processing -- JSON parsing errors -- Type conversion issues \ No newline at end of file diff --git a/engine/cli/README.md b/engine/cli/README.md deleted file mode 100644 index 8a9662958..000000000 --- a/engine/cli/README.md +++ /dev/null @@ -1,298 +0,0 @@ -# BAML CLI - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The BAML CLI is the command-line interface for BAML development, providing tools for code generation, validation, and project management. - -## Features - -- Project initialization -- Code generation -- Type checking -- Schema validation -- Project compilation -- Development server -- Language client generation -- Error reporting - -## Installation - -```bash -# Using cargo -cargo install baml-cli - -# From source -git clone https://github.com/boundaryml/baml -cd baml/engine/cli -cargo install --path . -``` - -## Usage - -### Project Initialization - -```bash -# Create new project -baml init my-project - -# Initialize in existing directory -cd my-project -baml init -``` - -### Code Generation - -```bash -# Generate all clients -baml generate - -# Generate specific language -baml generate python -baml generate typescript -``` - -### Development - -```bash -# Start development server -baml dev - -# Watch for changes -baml dev --watch -``` - -### Validation - -```bash -# Validate BAML files -baml check - -# Type check -baml check --types -``` - -## Project Structure - -``` -cli/ -├── src/ -│ ├── commands/ # CLI commands -│ │ ├── init.rs # Project initialization -│ │ ├── generate.rs # Code generation -│ │ └── dev.rs # Development server -│ ├── config/ # Configuration handling -│ ├── validation/ # Schema validation -│ └── utils/ # Shared utilities -├── templates/ # Project templates -└── examples/ # Example projects -``` - -## Development - -### Prerequisites - -- Rust toolchain -- Cargo -- Project dependencies - -### Setup - -```bash -# Install dependencies -cargo build - -# Run tests -cargo test - -# Run CLI -cargo run -- -``` - -## Adding Features - -### 1. New Command - -1. Create command module: -```rust -// src/commands/new_command.rs - -use clap::Parser; -use crate::command::{Command, CommandResult}; - -#[derive(Parser)] -pub struct NewCommand { - #[clap(long, short)] - option: String, -} - -impl Command for NewCommand { - fn run(&self) -> CommandResult { - // Implementation - } -} -``` - -2. Register command: -```rust -// src/main.rs - -cli.add_command("new-command", NewCommand::new()); -``` - -### 2. New Template - -1. Add template files: -``` -templates/ -└── new-template/ - ├── baml.toml - ├── clients.baml - └── generators.baml -``` - -2. Register template: -```rust -// src/templates/mod.rs - -impl TemplateManager { - pub fn register_template(&mut self, name: &str, path: &Path) { - self.templates.insert(name.to_string(), path.to_path_buf()); - } -} -``` - -## Testing - -### Unit Tests - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_command() { - let cmd = NewCommand::new(); - let result = cmd.run(); - assert!(result.is_ok()); - } -} -``` - -### Integration Tests - -```rust -#[test] -fn test_project_generation() { - let temp_dir = TempDir::new().unwrap(); - let result = Command::new("baml") - .arg("init") - .arg("test-project") - .current_dir(&temp_dir) - .output() - .unwrap(); - assert!(result.status.success()); -} -``` - -## Configuration - -### Project Config - -```toml -# baml.toml - -[project] -name = "my-project" -version = "0.1.0" - -[generation] -output = "./generated" -languages = ["python", "typescript"] - -[providers] -openai = { api_key = "${OPENAI_API_KEY}" } -anthropic = { api_key = "${ANTHROPIC_API_KEY}" } -``` - -### CLI Config - -```toml -# ~/.baml/config.toml - -[default] -api_key = "your-api-key" -output_dir = "./baml_generated" - -[profiles.dev] -api_key = "dev-api-key" -``` - -## Error Handling - -```rust -#[derive(Debug, Error)] -pub enum CliError { - #[error("Invalid configuration: {0}")] - Config(String), - - #[error("Generation failed: {0}")] - Generation(String), - - #[error("Validation error: {0}")] - Validation(String), -} - -impl Command { - fn handle_error(&self, error: CliError) -> ExitCode { - match error { - CliError::Config(msg) => { - eprintln!("Configuration error: {}", msg); - ExitCode::CONFIG_ERROR - } - CliError::Generation(msg) => { - eprintln!("Generation failed: {}", msg); - ExitCode::GENERATION_ERROR - } - CliError::Validation(msg) => { - eprintln!("Validation error: {}", msg); - ExitCode::VALIDATION_ERROR - } - } - } -} -``` - -## Best Practices - -1. **Command Structure** - - Use subcommands - - Provide help text - - Support --version - -2. **Error Handling** - - Use custom errors - - Provide clear messages - - Set exit codes - -3. **Configuration** - - Use config files - - Support env vars - - Validate input - -4. **Testing** - - Test commands - - Mock file system - - Check output - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow CLI guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review \ No newline at end of file diff --git a/engine/language_client_codegen/README.md b/engine/language_client_codegen/README.md deleted file mode 100644 index aadb610f3..000000000 --- a/engine/language_client_codegen/README.md +++ /dev/null @@ -1,491 +0,0 @@ -# BAML Code Generator - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -The BAML Code Generator is responsible for generating type-safe language-specific client SDKs from BAML source files. It provides a flexible template-based system for adding support for new languages and customizing code generation. - -## Features - -- Template-based code generation -- Multi-language support -- Type-safe code generation -- Customizable templates -- Incremental generation -- Source map support -- Formatting integration - -## Code Generation Flow - -```mermaid -graph TD - A[BAML Source Files] --> B[Generator Engine] - B --> C{Language Selection} - - C -->|TypeScript| D[TypeScript Generator] - C -->|Python| E[Python Generator] - C -->|Ruby| F[Ruby Generator] - - D --> G{Framework Selection} - G -->|Next.js| H[Next.js Generator] - G -->|Base TS| I[Base TS Generator] - - subgraph "Template Processing" - J[Load Templates] - K[Process Context] - L[Apply Helpers] - end - - H --> J - I --> J - E --> J - F --> J - - J --> K - K --> L - - L --> M[Generated Code] - - subgraph "Post Processing" - M --> N[Format Code] - N --> O[Generate Source Maps] - O --> P[Write Files] - end - - style B fill:#f9f,stroke:#333,stroke-width:2px - style C fill:#bbf,stroke:#333,stroke-width:2px - style G fill:#bbf,stroke:#333,stroke-width:2px -``` - -### Flow Explanation - -1. **Input Processing** - - BAML source files are read - - AST is generated and validated - -2. **Generator Selection** - - Language-specific generator is chosen - - Framework-specific generator is selected if applicable - -3. **Template Processing** - - Templates are loaded based on language/framework - - Context is prepared with types and metadata - - Helper functions are applied - -4. **Code Generation** - - Templates are rendered with context - - Language-specific formatting is applied - - Source maps are generated - - Files are written to disk - -## Architecture - -### Components - -``` -language_client_codegen/ -├── src/ -│ ├── generator/ # Core generator implementation -│ │ ├── engine.rs # Generation engine -│ │ ├── context.rs # Template context -│ │ └── types.rs # Type system -│ ├── languages/ # Language-specific generators -│ │ ├── python/ # Python generator -│ │ ├── typescript/ # TypeScript generator -│ │ │ ├── mod.rs # Main TypeScript generator -│ │ │ ├── next/ # Next.js specific generation -│ │ │ └── types.rs # TypeScript type mappings -│ │ └── ruby/ # Ruby generator -│ └── templates/ # Template definitions -│ ├── python/ # Python templates -│ ├── typescript/ # TypeScript templates -│ │ ├── base/ # Base TypeScript templates -│ │ └── next/ # Next.js specific templates -│ └── ruby/ # Ruby templates -├── templates/ # Template files -└── examples/ # Example generators -``` - -### Core Concepts - -1. **Generator Engine** - - Template processing - - Context management - - File generation - - Framework-specific output (e.g., Next.js, Express) - -2. **Type System** - - Language mappings - - Type conversion - - Validation rules - - Framework-specific types - -3. **Templates** - - Language templates - - Framework templates (e.g., Next.js Server Actions) - - Partial templates - - Helper functions - -## Framework Support - -### Next.js Integration - -The generator supports Next.js-specific code generation, including React Server Actions: - -```typescript -// Example generated Next.js Server Action -'use server' - -import { baml } from '@/lib/baml' - -export async function myBamlFunction(input: MyInputType) { - return await baml.functions.myFunction(input) -} -``` - -To enable Next.js generation: - -1. Configure TypeScript generator with Next.js options: -```rust -let config = TypeScriptConfig { - framework: Some(Framework::NextJs), - server_actions: true, - ..Default::default() -}; -``` - -2. Use Next.js specific templates: -```rust -generator - .with_template("next/server-action", server_action_template) - .with_template("next/client-wrapper", client_wrapper_template); -``` - -3. Generate code: -```rust -generator - .generate("path/to/baml/files", "app/lib/baml") - .await?; -``` - -### Template Structure - -Next.js templates should follow this structure: - -``` -templates/typescript/next/ -├── server-actions.ts.j2 # Server Action templates -├── client-wrapper.ts.j2 # Client-side wrapper -└── types.ts.j2 # Next.js specific types -``` - -Example server action template: -```handlebars -'use server' - -import { baml } from '@/lib/baml' -import type { {{type_name}} } from './types' - -export async function {{function_name}}( - input: {{input_type}} -): Promise<{{output_type}}> { - return await baml.functions.{{original_name}}(input) -} -``` - -## Usage - -### Basic Example - -```rust -use baml_codegen::{Generator, Config}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Initialize generator - let generator = Generator::new(Config::default())?; - - // Generate code - generator - .generate("path/to/baml/files", "output/dir") - .await?; - - Ok(()) -} -``` - -### Custom Template - -```rust -use baml_codegen::template::{Template, Context}; - -let template = Template::new() - .with_content( - r#" -class {{name}} { - {{#each fields}} - {{type}} {{name}}; - {{/each}} -} -"#, - ) - .with_helpers(helpers); - -generator.register_template("class", template); -``` - -### Language Support - -```rust -use baml_codegen::language::{Language, TypeMapper}; - -struct MyLanguage; - -impl Language for MyLanguage { - fn name(&self) -> &str { - "mylang" - } - - fn file_extension(&self) -> &str { - "ml" - } - - fn type_mapper(&self) -> &dyn TypeMapper { - &MY_TYPE_MAPPER - } -} - -generator.add_language(Box::new(MyLanguage)); -``` - -## Development - -### Prerequisites - -- Rust toolchain -- Language formatters -- Template engine - -### Setup - -```bash -# Install dependencies -cargo build - -# Run tests -cargo test - -# Run examples -cargo run --example custom_generator -``` - -## Adding Features - -### 1. New Language Support - -1. Create language module: -```rust -// src/languages/mylang/mod.rs - -use crate::language::{Language, TypeMapper}; - -pub struct MyLanguage { - config: LanguageConfig, -} - -impl Language for MyLanguage { - fn name(&self) -> &str { - "mylang" - } - - fn generate_type(&self, type_def: &TypeDef) -> Result { - // Implementation - } - - fn generate_client(&self, client_def: &ClientDef) -> Result { - // Implementation - } -} -``` - -2. Add type mappings: -```rust -// src/languages/mylang/types.rs - -pub struct MyTypeMapper; - -impl TypeMapper for MyTypeMapper { - fn map_type(&self, baml_type: &BamlType) -> Result { - match baml_type { - BamlType::String => Ok("string".to_string()), - BamlType::Int => Ok("int".to_string()), - // ... other mappings - } - } -} -``` - -### 2. New Template Helper - -1. Create helper function: -```rust -// src/helpers/custom_helper.rs - -pub fn format_type( - h: &Helper, - _: &Handlebars, - ctx: &Context, -) -> Result { - let type_name = h - .param(0) - .and_then(|v| v.value().as_str()) - .ok_or_else(|| Error::missing_param("type_name"))?; - - Ok(format_type_name(type_name)) -} -``` - -2. Register helper: -```rust -let mut handlebars = Handlebars::new(); -handlebars.register_helper("format_type", Box::new(format_type)); -``` - -### 1. New Framework Support - -1. Create framework module: -```rust -// src/languages/typescript/frameworks/my_framework/mod.rs - -use crate::framework::{Framework, FrameworkGenerator}; - -pub struct MyFramework { - config: FrameworkConfig, -} - -impl Framework for MyFramework { - fn name(&self) -> &str { - "my_framework" - } - - fn generate_endpoint(&self, endpoint_def: &EndpointDef) -> Result { - // Implementation - } - - fn generate_client(&self, client_def: &ClientDef) -> Result { - // Implementation - } -} -``` - -2. Add framework-specific templates: -``` -templates/typescript/my_framework/ -├── endpoint.ts.j2 -├── client.ts.j2 -└── types.ts.j2 -``` - -3. Register framework: -```rust -generator.register_framework("my_framework", Box::new(MyFramework::new(config))); -``` - -## Testing - -### Unit Tests - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_type_generation() { - let generator = setup_test_generator(); - let type_def = test_type_definition(); - let result = generator.generate_type(&type_def).unwrap(); - assert_eq!(result, expected_output()); - } -} -``` - -### Integration Tests - -```rust -#[test] -fn test_full_generation() { - let generator = Generator::new(test_config()).unwrap(); - let result = generator - .generate_all("test/fixtures", "test/output") - .unwrap(); - assert!(result.is_success()); -} -``` - -## Templates - -### Basic Template - -```handlebars -class {{name}} { - {{#each fields}} - private {{type}} {{name}}; - - public {{type}} get{{capitalize name}}() { - return this.{{name}}; - } - - public void set{{capitalize name}}({{type}} {{name}}) { - this.{{name}} = {{name}}; - } - {{/each}} -} -``` - -### Partial Template - -```handlebars -{{#*inline "field_declaration"}} -private {{type}} {{name}}; -{{/inline}} - -class {{name}} { - {{#each fields}} - {{> field_declaration}} - {{/each}} -} -``` - -## Best Practices - -1. **Template Organization** - - Use partial templates - - Keep templates modular - - Use consistent naming - -2. **Type Safety** - - Validate input types - - Handle edge cases - - Add type assertions - -3. **Code Quality** - - Format generated code - - Add source maps - - Include comments - -4. **Testing** - - Test all generators - - Verify output - - Check edge cases - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow code generation guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review diff --git a/engine/language_client_python/README.md b/engine/language_client_python/README.md deleted file mode 100644 index c2ea54b37..000000000 --- a/engine/language_client_python/README.md +++ /dev/null @@ -1,298 +0,0 @@ -# BAML Python Client - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -Native Python bindings for BAML, providing type-safe LLM function calls with full Python type hints and runtime type checking. - -## Features - -- Native Python bindings via PyO3 -- Full Python type hints -- Async support with asyncio -- Streaming responses -- Error handling with type safety -- Python 3.8+ support - -## Installation - -```bash -# Using pip -pip install baml-py - -# Using poetry -poetry add baml-py - -# Development installation -pip install -e . -pip install -r requirements-dev.txt -``` - -## Usage - -### Basic Example -```python -from baml import Baml -from typing import TypedDict - -class UserInfo(TypedDict): - name: str - age: int - email: str - -async def extract_user_info(text: str) -> UserInfo: - # Call BAML function with type safety - result = await Baml.extract_user_info(text) - return result -``` - -### Streaming Example -```python -async def stream_response(text: str): - async for chunk in Baml.streaming_function(text): - print(f"Received chunk: {chunk}") -``` - -### Error Handling -```python -try: - result = await Baml.my_function(text) -except Baml.ProviderError as e: - print(f"Provider error: {e.message}, status: {e.status_code}") -except Baml.ValidationError as e: - print(f"Validation error: {e.errors}") -except Baml.Error as e: - print(f"BAML error: {e}") -``` - -## Development - -### Prerequisites -- Python 3.8+ -- Rust toolchain -- pip or poetry -- maturin - -### Setup -```bash -# Install dependencies -pip install -r requirements-dev.txt - -# Build native module -maturin develop - -# Run tests -pytest -``` - -### Project Structure -``` -language_client_python/ -├── src/ -│ ├── lib.rs # PyO3 bindings -│ ├── types.rs # Type conversions -│ └── async.rs # Asyncio support -├── baml/ -│ ├── __init__.py # Python wrapper -│ ├── types.py # Type definitions -│ └── client.py # Client implementation -├── tests/ # Test suite -└── pyproject.toml # Build configuration -``` - -## Adding Features - -### 1. New Type Definition - -1. Add Python type: -```python -from typing import TypedDict, Optional, List - -class NewType(TypedDict): - field: str - optional_field: Optional[int] - array_field: List[str] -``` - -2. Add Rust binding: -```rust -#[derive(Debug)] -pub struct NewType { - pub field: String, - pub optional_field: Option, - pub array_field: Vec, -} - -impl IntoPy for NewType { - fn into_py(self, py: Python) -> PyObject { - let dict = PyDict::new(py); - dict.set_item("field", self.field).unwrap(); - dict.set_item("optional_field", self.optional_field).unwrap(); - dict.set_item("array_field", self.array_field).unwrap(); - dict.into() - } -} -``` - -### 2. New Function - -1. Add function binding: -```rust -#[pyfunction] -pub fn baml_my_function( - py: Python, - input: String, -) -> PyResult { - // Implementation -} -``` - -2. Add Python wrapper: -```python -from typing import TypeVar, Generic - -T = TypeVar('T') - -class Baml: - @staticmethod - async def my_function(input: str) -> NewType: - result = await _native.baml_my_function(input) - return result -``` - -## Testing - -### Unit Tests -```python -import pytest -from baml import Baml - -def test_function(): - result = Baml.test_function("input") - assert result["field"] == "expected" -``` - -### Integration Tests -```python -@pytest.mark.asyncio -async def test_provider_integration(): - result = await Baml.provider_test("input") - assert result["valid"] is True -``` - -## Error Handling - -```python -class BamlError(Exception): - """Base class for BAML errors.""" - pass - -class ProviderError(BamlError): - """Error from LLM provider.""" - def __init__(self, message: str, status_code: int): - super().__init__(message) - self.status_code = status_code - -class ValidationError(BamlError): - """Error from validation.""" - def __init__(self, errors: List[str]): - super().__init__("Validation failed") - self.errors = errors -``` - -## Performance - -### Async/Await -```python -async def process_batch(inputs: List[str]) -> List[T]: - tasks = [ - Baml.function(input) - for input in inputs - ] - return await asyncio.gather(*tasks) -``` - -### Streaming -```python -async def stream_with_buffer( - text: str, - buffer_size: int = 1000 -) -> None: - buffer: List[str] = [] - async for chunk in Baml.streaming_function(text): - buffer.append(chunk) - if len(buffer) >= buffer_size: - await process_buffer(buffer) - buffer.clear() - - if buffer: - await process_buffer(buffer) -``` - -## Type Safety - -### Type Definitions -```python -from typing import TypedDict, Optional, Dict, Union, Literal - -class UserProfile(TypedDict): - name: str - age: int - email: str - preferences: Dict[str, Union[str, bool]] - -class UserResponse(TypedDict): - profile: UserProfile - status: Literal["active", "inactive"] - last_login: Optional[datetime] - -class BamlOptions(TypedDict, total=False): - timeout: Optional[int] - retries: Optional[int] - headers: Optional[Dict[str, str]] -``` - -### Runtime Type Checking -```python -from typing import runtime_checkable, Protocol - -@runtime_checkable -class HasField(Protocol): - field: str - -def process_type(obj: HasField) -> str: - return obj.field.upper() -``` - -## Best Practices - -1. **Error Handling** - - Use custom error classes - - Provide detailed error info - - Handle all error cases - -2. **Type Safety** - - Use type hints - - Enable runtime checking - - Document type constraints - -3. **Async Usage** - - Use asyncio - - Handle task cancellation - - Manage concurrency - -4. **Testing** - - Write unit tests - - Add integration tests - - Test error cases - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow Python client guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review diff --git a/engine/language_client_ruby/README.md b/engine/language_client_ruby/README.md deleted file mode 100644 index 6da5e777c..000000000 --- a/engine/language_client_ruby/README.md +++ /dev/null @@ -1,346 +0,0 @@ -# BAML Ruby Client - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -Native Ruby bindings for BAML, providing type-safe LLM function calls with Sorbet type checking. - -## Features - -- Native Ruby bindings via FFI -- Sorbet type checking -- Fiber-based async support -- Streaming responses -- Error handling with type safety -- RBS type definitions - -## Installation - -```bash -# Using bundler -bundle add baml-rb - -# Using gem -gem install baml-rb - -# Development installation -bundle install -bundle exec rake compile -``` - -## Usage - -### Basic Example -```ruby -require 'baml' - -# @param text [String] -# @return [UserInfo] -def extract_user_info(text) - # Call BAML function with type safety - result = Baml.extract_user_info(text) - raise TypeError unless result.is_a?(UserInfo) - result -end -``` - -### Streaming Example -```ruby -def stream_response(text) - Baml.streaming_function.stream(text) do |chunk| - puts "Received chunk: #{chunk}" - end -end -``` - -### Error Handling -```ruby -begin - result = Baml.my_function(text) -rescue Baml::ProviderError => e - puts "Provider error: #{e.message}" -rescue Baml::ValidationError => e - puts "Validation error: #{e.errors}" -rescue Baml::Error => e - puts "BAML error: #{e}" -end -``` - -## Development - -### Prerequisites -- Ruby 3.0+ -- Rust toolchain -- Bundler -- Rake - -### Setup -```bash -# Install dependencies -bundle install - -# Build native extension -bundle exec rake compile - -# Run tests -bundle exec rake test -``` - -### Project Structure -``` -language_client_ruby/ -├── ext/ -│ ├── lib.rs # FFI bindings -│ ├── types.rs # Type conversions -│ └── async.rs # Fiber support -├── lib/ -│ ├── baml.rb # Ruby wrapper -│ ├── types.rb # Type definitions -│ └── version.rb # Version info -├── sig/ # RBS type definitions -└── test/ # Test suite -``` - -## Adding Features - -### 1. New Type Definition - -1. Add Ruby class: -```ruby -module Baml - class NewType - extend T::Sig - - sig { returns(String) } - attr_reader :field - - sig { params(field: String).void } - def initialize(field) - @field = field - end - end -end -``` - -2. Add RBS type: -```rbs -module Baml - class NewType - attr_reader field: String - def initialize: (field: String) -> void - end -end -``` - -3. Add Rust binding: -```rust -#[derive(Debug)] -pub struct NewType { - pub field: String, -} - -impl From for Value { - fn from(t: NewType) -> Self { - let hash = Hash::new(); - hash.store( - Symbol::new("field"), - t.field.into(), - ); - hash.into() - } -} -``` - -### 2. New Function - -1. Add function binding: -```rust -#[no_mangle] -pub extern "C" fn baml_my_function( - input: Value, -) -> Value { - // Implementation -} -``` - -2. Add Ruby wrapper: -```ruby -module Baml - extend T::Sig - - sig { params(input: String).returns(NewType) } - def self.my_function(input) - result = Native.baml_my_function(input) - NewType.from_native(result) - end -end -``` - -## Testing - -### Unit Tests -```ruby -require 'test_helper' - -class TestBaml < Minitest::Test - def test_function - result = Baml.test_function('input') - assert_equal 'expected', result.field - end -end -``` - -### Integration Tests -```ruby -class TestProvider < Minitest::Test - def test_provider_integration - result = Baml.provider_test('input') - assert result.valid? - end -end -``` - -## Error Handling - -```ruby -module Baml - class Error < StandardError; end - - class ProviderError < Error - attr_reader :status_code - - def initialize(message, status_code) - super(message) - @status_code = status_code - end - end - - class ValidationError < Error - attr_reader :errors - - def initialize(errors) - super('Validation failed') - @errors = errors - end - end -end -``` - -## Performance - -### Fiber Support -```ruby -def process_many(inputs) - fibers = inputs.map do |input| - Fiber.new do - Baml.function(input) - end - end - fibers.map(&:resume) -end -``` - -### Streaming -```ruby -def stream_with_buffer(text, buffer_size = 1000) - buffer = [] - Baml.streaming_function.stream(text) do |chunk| - buffer << chunk - if buffer.size >= buffer_size - yield buffer - buffer = [] - end - end - yield buffer unless buffer.empty? -end -``` - -## Type Safety - -### Sorbet Types -```ruby -module Baml - class UserProfile - extend T::Sig - - sig { returns(String) } - attr_reader :name - - sig { returns(Integer) } - attr_reader :age - - sig { returns(String) } - attr_reader :email - - sig { returns(T::Hash[Symbol, T.any(String, T::Boolean)]) } - attr_reader :preferences - - sig do - params( - name: String, - age: Integer, - email: String, - preferences: T::Hash[Symbol, T.any(String, T::Boolean)] - ).void - end - def initialize(name:, age:, email:, preferences: {}) - @name = name - @age = age - @email = email - @preferences = preferences - end - end -end -``` - -### RBS Types -```rbs -module Baml - class UserProfile - attr_reader name: String - attr_reader age: Integer - attr_reader email: String - attr_reader preferences: Hash[Symbol, String | bool] - - def initialize: ( - name: String, - age: Integer, - email: String, - ?preferences: Hash[Symbol, String | bool] - ) -> void - end -end -``` - -## Best Practices - -1. **Error Handling** - - Use custom error classes - - Provide detailed error info - - Handle all error cases - -2. **Type Safety** - - Use Sorbet signatures - - Add RBS definitions - - Enable type checking - -3. **Async Usage** - - Use Fibers for concurrency - - Handle thread safety - - Manage resources - -4. **Testing** - - Write unit tests - - Add integration tests - - Test error cases - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow Ruby client guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review \ No newline at end of file diff --git a/engine/language_client_typescript/README.md b/engine/language_client_typescript/README.md deleted file mode 100644 index 3cdb97b22..000000000 --- a/engine/language_client_typescript/README.md +++ /dev/null @@ -1,313 +0,0 @@ -# BAML TypeScript Client - -> **⚠️ IMPORTANT NOTE** -> -> This document was initially generated by an AI assistant and should be taken with a grain of salt. While it provides a good starting point, some information might be inaccurate or outdated. We encourage contributors to manually update this document and remove this note once the content has been verified and corrected by the team. -> -> If you find any inaccuracies or have improvements to suggest, please feel free to submit a PR updating this guide. - -Native TypeScript bindings for BAML, providing type-safe LLM function calls with full TypeScript type checking. - -## Features - -- Native Node.js bindings via N-API -- Full TypeScript type definitions -- Promise-based async support -- Streaming responses -- Error handling with type safety -- ESM and CommonJS support - -## Installation - -```bash -# Using npm -npm install @baml/client - -# Using yarn -yarn add @baml/client - -# Using pnpm -pnpm add @baml/client - -# Development installation -npm install -npm run build -``` - -## Usage - -### Basic Example -```typescript -import { Baml } from '@baml/client'; - -interface UserInfo { - name: string; - age: number; - email: string; -} - -async function extractUserInfo(text: string): Promise { - // Call BAML function with type safety - const result = await Baml.extractUserInfo(text); - return result; -} -``` - -### Streaming Example -```typescript -async function streamResponse(text: string) { - const stream = await Baml.streamingFunction(text); - - for await (const chunk of stream) { - console.log('Received chunk:', chunk); - } -} -``` - -### Error Handling -```typescript -try { - const result = await Baml.myFunction(text); -} catch (error) { - if (error instanceof Baml.ProviderError) { - console.error('Provider error:', error.message, error.statusCode); - } else if (error instanceof Baml.ValidationError) { - console.error('Validation error:', error.errors); - } else if (error instanceof Baml.Error) { - console.error('BAML error:', error); - } -} -``` - -## Development - -### Prerequisites -- Node.js 16+ -- Rust toolchain -- npm or yarn -- node-gyp - -### Setup -```bash -# Install dependencies -npm install - -# Build native module -npm run build - -# Run tests -npm test -``` - -### Project Structure -``` -language_client_typescript/ -├── src/ -│ ├── lib.rs # N-API bindings -│ ├── types.rs # Type conversions -│ └── async.rs # Promise support -├── lib/ -│ ├── index.ts # TypeScript wrapper -│ ├── types.ts # Type definitions -│ └── client.ts # Client implementation -├── test/ # Test suite -└── binding.gyp # Build configuration -``` - -## Adding Features - -### 1. New Type Definition - -1. Add TypeScript interface: -```typescript -export interface NewType { - field: string; - optionalField?: number; - arrayField: string[]; -} -``` - -2. Add Rust binding: -```rust -#[derive(Debug)] -pub struct NewType { - pub field: String, - pub optional_field: Option, - pub array_field: Vec, -} - -impl TryFrom for NewType { - type Error = napi::Error; - - fn try_from(value: JsValue) -> Result { - // Implementation - } -} -``` - -### 2. New Function - -1. Add function binding: -```rust -#[napi] -pub async fn baml_my_function( - env: Env, - input: String, -) -> Result { - // Implementation -} -``` - -2. Add TypeScript wrapper: -```typescript -export class Baml { - static async myFunction(input: string): Promise { - const result = await native.bamlMyFunction(input); - return result as NewType; - } -} -``` - -## Testing - -### Unit Tests -```typescript -import { expect } from 'chai'; -import { Baml } from '../lib'; - -describe('Baml', () => { - it('should process function call', async () => { - const result = await Baml.testFunction('input'); - expect(result.field).to.equal('expected'); - }); -}); -``` - -### Integration Tests -```typescript -describe('Provider Integration', () => { - it('should handle provider calls', async () => { - const result = await Baml.providerTest('input'); - expect(result.valid).to.be.true; - }); -}); -``` - -## Error Handling - -```typescript -export class BamlError extends Error { - constructor(message: string) { - super(message); - this.name = 'BamlError'; - } -} - -export class ProviderError extends BamlError { - constructor( - message: string, - public statusCode: number - ) { - super(message); - this.name = 'ProviderError'; - } -} - -export class ValidationError extends BamlError { - constructor(public errors: string[]) { - super('Validation failed'); - this.name = 'ValidationError'; - } -} -``` - -## Performance - -### Async/Await -```typescript -async function processBatch(inputs: string[]) { - const promises = inputs.map(input => - Baml.function(input) - ); - return Promise.all(promises); -} -``` - -### Streaming -```typescript -async function streamWithBuffer( - text: string, - bufferSize = 1000 -): Promise { - const stream = await Baml.streamingFunction(text); - const buffer: string[] = []; - - for await (const chunk of stream) { - buffer.push(chunk); - if (buffer.length >= bufferSize) { - await processBuffer(buffer); - buffer.length = 0; - } - } - - if (buffer.length > 0) { - await processBuffer(buffer); - } -} -``` - -## Type Safety - -### Type Definitions -```typescript -export interface UserProfile { - name: string; - age: number; - email: string; - preferences: { - [key: string]: string | boolean; - }; -} - -export type UserResponse = { - profile: UserProfile; - status: 'active' | 'inactive'; - lastLogin?: Date; -}; - -export interface BamlOptions { - timeout?: number; - retries?: number; - headers?: Record; -} -``` - -## Best Practices - -1. **Error Handling** - - Use custom error classes - - Provide detailed error info - - Handle all error cases - -2. **Type Safety** - - Use strict TypeScript - - Enable all type checks - - Document type constraints - -3. **Async Usage** - - Use async/await - - Handle Promise rejections - - Manage concurrency - -4. **Testing** - - Write unit tests - - Add integration tests - - Test error cases - -## Contributing - -1. Read [Contributing Guide](../../CONTRIBUTING.md) -2. Follow TypeScript client guidelines -3. Add tests for new features -4. Update documentation -5. Submit PR for review