sorbet-baml 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/sorbet_baml.rb CHANGED
@@ -5,6 +5,12 @@ require "sorbet-runtime"
5
5
  require_relative "sorbet_baml/version"
6
6
  require_relative "sorbet_baml/converter"
7
7
  require_relative "sorbet_baml/type_mapper"
8
+ require_relative "sorbet_baml/dependency_resolver"
9
+ require_relative "sorbet_baml/comment_extractor"
10
+ require_relative "sorbet_baml/description_extractor"
11
+ require_relative "sorbet_baml/description_extension"
12
+ require_relative "sorbet_baml/struct_extensions"
13
+ require_relative "sorbet_baml/enum_extensions"
8
14
 
9
15
  module SorbetBaml
10
16
  class Error < StandardError; end
@@ -23,3 +29,7 @@ module SorbetBaml
23
29
  Converter.from_structs(klasses, options)
24
30
  end
25
31
  end
32
+
33
+ # Extend T::Struct and T::Enum with BAML conversion methods
34
+ T::Struct.extend(SorbetBaml::StructExtensions)
35
+ T::Enum.extend(SorbetBaml::EnumExtensions)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-baml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vicente Reig Rincon de Arellano
@@ -32,18 +32,23 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
+ - ".idea/.gitignore"
36
+ - ".idea/inspectionProfiles/Project_Default.xml"
35
37
  - ".rspec"
36
38
  - CHANGELOG.md
39
+ - CLAUDE.md
37
40
  - LICENSE.txt
38
41
  - README.md
39
42
  - Rakefile
40
- - docs/README.md
41
- - docs/advanced-usage.md
42
- - docs/getting-started.md
43
- - docs/troubleshooting.md
44
- - docs/type-mapping.md
43
+ - examples/description_parameters.rb
45
44
  - lib/sorbet_baml.rb
45
+ - lib/sorbet_baml/comment_extractor.rb
46
46
  - lib/sorbet_baml/converter.rb
47
+ - lib/sorbet_baml/dependency_resolver.rb
48
+ - lib/sorbet_baml/description_extension.rb
49
+ - lib/sorbet_baml/description_extractor.rb
50
+ - lib/sorbet_baml/enum_extensions.rb
51
+ - lib/sorbet_baml/struct_extensions.rb
47
52
  - lib/sorbet_baml/type_mapper.rb
48
53
  - lib/sorbet_baml/version.rb
49
54
  - sig/sorbet/baml.rbs
data/docs/README.md DELETED
@@ -1,67 +0,0 @@
1
- # sorbet-baml Documentation
2
-
3
- Developer documentation for the sorbet-baml gem.
4
-
5
- ## For Users
6
-
7
- If you want to use this gem in your project:
8
-
9
- 1. **[Getting Started](./getting-started.md)** - Installation and basic usage
10
- 2. **[Type Mapping Reference](./type-mapping.md)** - Complete type conversion table
11
- 3. **[Advanced Usage](./advanced-usage.md)** - Complex scenarios and integrations
12
- 4. **[Troubleshooting](./troubleshooting.md)** - Common issues and solutions
13
-
14
- ## For Contributors
15
-
16
- If you want to contribute to this gem:
17
-
18
- 1. **[Architecture](./architecture.md)** - How the gem is structured
19
- 2. **[Adding Type Support](./adding-types.md)** - How to add new type mappings
20
- 3. **[Testing Guide](./testing.md)** - How to write and run tests
21
-
22
- ## Quick Example
23
-
24
- ```ruby
25
- # Define a Sorbet struct
26
- class User < T::Struct
27
- const :name, String
28
- const :age, Integer
29
- const :email, T.nilable(String)
30
- end
31
-
32
- # Convert to BAML
33
- require 'sorbet-baml'
34
- puts SorbetBaml.from_struct(User)
35
-
36
- # Output:
37
- # class User {
38
- # name string
39
- # age int
40
- # email string?
41
- # }
42
- ```
43
-
44
- ## Design Goals
45
-
46
- 1. **Simplicity** - Easy to understand and use
47
- 2. **Accuracy** - Correct type mappings
48
- 3. **Efficiency** - Minimal token usage in output
49
- 4. **Compatibility** - Works with existing Sorbet codebases
50
-
51
- ## What This Is Not
52
-
53
- - Not a BAML runtime or executor
54
- - Not a JSON Schema generator (use sorbet-schema for that)
55
- - Not a Sorbet type checker
56
- - Not a serialization library
57
-
58
- ## Why BAML?
59
-
60
- BAML (Boundary AI Markup Language) provides a concise way to define types for LLM consumption. Compared to JSON Schema:
61
-
62
- - ~60% fewer tokens
63
- - More readable
64
- - Better LLM comprehension
65
- - Simpler syntax
66
-
67
- Perfect for prompt engineering and structured output generation.
@@ -1,85 +0,0 @@
1
- # Advanced Usage
2
-
3
- ## Converting Multiple Structs
4
-
5
- When you have related structs, convert them together to maintain relationships:
6
-
7
- ```ruby
8
- class Address < T::Struct
9
- const :street, String
10
- const :city, String
11
- end
12
-
13
- class Company < T::Struct
14
- const :name, String
15
- const :address, Address
16
- end
17
-
18
- class User < T::Struct
19
- const :name, String
20
- const :company, Company
21
- end
22
-
23
- # Convert all at once
24
- baml = SorbetBaml.from_structs([Address, Company, User])
25
- ```
26
-
27
- ## Options
28
-
29
- ### Include Descriptions
30
-
31
- ```ruby
32
- # Future feature - not yet implemented
33
- baml = SorbetBaml.from_struct(User,
34
- include_descriptions: true # Will add @description annotations
35
- )
36
- ```
37
-
38
- ### Custom Indentation
39
-
40
- ```ruby
41
- # Future feature - not yet implemented
42
- baml = SorbetBaml.from_struct(User,
43
- indent_size: 4 # Use 4 spaces instead of 2
44
- )
45
- ```
46
-
47
- ## Working with Existing BAML Projects
48
-
49
- If you're already using BAML, you can generate type definitions to include in your `.baml` files:
50
-
51
- ```ruby
52
- # Generate just the class definition
53
- definition = SorbetBaml.from_struct(MyStruct)
54
-
55
- # Write to a BAML file
56
- File.write("types/my_struct.baml", definition)
57
- ```
58
-
59
- ## Integration with LLM Libraries
60
-
61
- ### With OpenAI
62
-
63
- ```ruby
64
- require 'openai'
65
- require 'sorbet-baml'
66
-
67
- schema = SorbetBaml.from_struct(ResponseFormat)
68
-
69
- response = client.chat(
70
- model: "gpt-4",
71
- messages: [{
72
- role: "system",
73
- content: "You must respond with data matching this BAML schema:\n\n#{schema}"
74
- }, {
75
- role: "user",
76
- content: "Generate a sample user"
77
- }]
78
- )
79
- ```
80
-
81
- ### With DSPy.rb
82
-
83
- ```ruby
84
- # Coming soon - integration with DSPy.rb for automatic schema generation
85
- ```
@@ -1,54 +0,0 @@
1
- # Getting Started
2
-
3
- ## Prerequisites
4
-
5
- - Ruby 3.2+
6
- - Sorbet installed in your project
7
- - Basic familiarity with T::Struct
8
-
9
- ## Quick Start
10
-
11
- ### 1. Define your Sorbet types
12
-
13
- ```ruby
14
- class User < T::Struct
15
- const :id, Integer
16
- const :name, String
17
- const :email, T.nilable(String)
18
- end
19
- ```
20
-
21
- ### 2. Convert to BAML
22
-
23
- ```ruby
24
- require 'sorbet-baml'
25
-
26
- baml = SorbetBaml.from_struct(User)
27
- puts baml
28
- # Output:
29
- # class User {
30
- # id int
31
- # name string
32
- # email string?
33
- # }
34
- ```
35
-
36
- ### 3. Use with your LLM
37
-
38
- Include the BAML definition in your prompt:
39
-
40
- ```ruby
41
- prompt = <<~PROMPT
42
- Generate sample data matching this schema:
43
-
44
- #{baml}
45
-
46
- Return 3 examples.
47
- PROMPT
48
- ```
49
-
50
- ## Next Steps
51
-
52
- - [Type Mapping Reference](./type-mapping.md)
53
- - [Advanced Usage](./advanced-usage.md)
54
- - [Troubleshooting](./troubleshooting.md)
@@ -1,81 +0,0 @@
1
- # Troubleshooting
2
-
3
- ## Common Issues
4
-
5
- ### "undefined method `props' for Class"
6
-
7
- **Problem**: The class you're trying to convert is not a T::Struct.
8
-
9
- **Solution**: Ensure your class inherits from `T::Struct`:
10
-
11
- ```ruby
12
- # ❌ Wrong
13
- class User
14
- attr_reader :name
15
- end
16
-
17
- # ✅ Correct
18
- class User < T::Struct
19
- const :name, String
20
- end
21
- ```
22
-
23
- ### Empty output
24
-
25
- **Problem**: The struct has no properties defined.
26
-
27
- **Solution**: Define at least one property using `const` or `prop`:
28
-
29
- ```ruby
30
- class User < T::Struct
31
- const :name, String # Add properties
32
- end
33
- ```
34
-
35
- ### Circular dependency detected
36
-
37
- **Problem**: Two structs reference each other creating an infinite loop.
38
-
39
- **Solution**: This is not yet supported. Consider flattening the structure or using a different approach.
40
-
41
- ## Type-Specific Issues
42
-
43
- ### Arrays not converting correctly
44
-
45
- Ensure you're using the Sorbet array syntax:
46
-
47
- ```ruby
48
- # ❌ Wrong
49
- const :items, Array
50
-
51
- # ✅ Correct
52
- const :items, T::Array[String]
53
- ```
54
-
55
- ### Optional fields showing as required
56
-
57
- Make sure to use `T.nilable`:
58
-
59
- ```ruby
60
- # ❌ Wrong - will be required
61
- const :email, String
62
-
63
- # ✅ Correct - will be optional
64
- const :email, T.nilable(String)
65
- ```
66
-
67
- ## Getting Help
68
-
69
- 1. Check the [Type Mapping Reference](./type-mapping.md)
70
- 2. Review the examples in [Getting Started](./getting-started.md)
71
- 3. File an issue at https://github.com/vicentereig/sorbet-baml/issues
72
-
73
- ## Debug Mode
74
-
75
- To see detailed conversion information:
76
-
77
- ```ruby
78
- # Future feature - not yet implemented
79
- SorbetBaml.debug = true
80
- baml = SorbetBaml.from_struct(MyStruct)
81
- ```
data/docs/type-mapping.md DELETED
@@ -1,65 +0,0 @@
1
- # Type Mapping Reference
2
-
3
- Complete mapping between Sorbet types and BAML output.
4
-
5
- ## Basic Types
6
-
7
- | Sorbet Type | BAML Output | Example |
8
- |-------------|-------------|---------|
9
- | `String` | `string` | `name string` |
10
- | `Integer` | `int` | `age int` |
11
- | `Float` | `float` | `price float` |
12
- | `T::Boolean` | `bool` | `active bool` |
13
- | `NilClass` | `null` | `null` |
14
- | `Symbol` | `string` | `status string` |
15
-
16
- ## Optional Types
17
-
18
- | Sorbet Type | BAML Output | Example |
19
- |-------------|-------------|---------|
20
- | `T.nilable(String)` | `string?` | `email string?` |
21
- | `T.nilable(Integer)` | `int?` | `age int?` |
22
-
23
- ## Collection Types
24
-
25
- | Sorbet Type | BAML Output | Example |
26
- |-------------|-------------|---------|
27
- | `T::Array[String]` | `string[]` | `tags string[]` |
28
- | `T::Array[T::Struct]` | `StructName[]` | `addresses Address[]` |
29
-
30
- ## Nested Structures
31
-
32
- ```ruby
33
- # Input
34
- class Address < T::Struct
35
- const :street, String
36
- const :city, String
37
- end
38
-
39
- class User < T::Struct
40
- const :name, String
41
- const :address, Address
42
- end
43
-
44
- # Output
45
- class Address {
46
- street string
47
- city string
48
- }
49
-
50
- class User {
51
- name string
52
- address Address
53
- }
54
- ```
55
-
56
- ## Not Yet Supported
57
-
58
- These types will be added in future versions:
59
-
60
- - `T::Hash[K, V]` → `map<K, V>`
61
- - `T.any(Type1, Type2)` → `Type1 | Type2`
62
- - `T::Enum` subclasses → `enum Name { ... }`
63
- - `T.type_alias` → `type Name = ...`
64
- - `T::Set[T]` → `T[]` (with uniqueness note)
65
- - `T::Range[T]` → Will need special handling