sorbet-baml 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +123 -2
- data/Rakefile +2 -2
- data/docs-site/.gitignore +48 -0
- data/docs-site/Gemfile +5 -0
- data/docs-site/Gemfile.lock +140 -0
- data/docs-site/Rakefile +3 -0
- data/docs-site/bridgetown.config.yml +15 -0
- data/docs-site/config/initializers.rb +9 -0
- data/docs-site/config/puma.rb +9 -0
- data/docs-site/config.ru +5 -0
- data/docs-site/esbuild.config.js +11 -0
- data/docs-site/frontend/javascript/index.js +22 -0
- data/docs-site/frontend/styles/index.css +61 -0
- data/docs-site/package.json +18 -0
- data/docs-site/postcss.config.js +6 -0
- data/docs-site/server/roda_app.rb +9 -0
- data/docs-site/src/_components/head.liquid +26 -0
- data/docs-site/src/_components/nav.liquid +68 -0
- data/docs-site/src/_layouts/default.liquid +27 -0
- data/docs-site/src/_layouts/doc.liquid +39 -0
- data/docs-site/src/advanced-usage.md +598 -0
- data/docs-site/src/getting-started.md +170 -0
- data/docs-site/src/index.md +183 -0
- data/docs-site/src/troubleshooting.md +317 -0
- data/docs-site/src/type-mapping.md +236 -0
- data/docs-site/tailwind.config.js +85 -0
- data/examples/description_parameters.rb +16 -16
- data/lib/sorbet_baml/comment_extractor.rb +31 -39
- data/lib/sorbet_baml/converter.rb +66 -32
- data/lib/sorbet_baml/dependency_resolver.rb +11 -11
- data/lib/sorbet_baml/description_extension.rb +5 -5
- data/lib/sorbet_baml/description_extractor.rb +8 -10
- data/lib/sorbet_baml/dspy_tool_converter.rb +97 -0
- data/lib/sorbet_baml/dspy_tool_extensions.rb +23 -0
- data/lib/sorbet_baml/enum_extensions.rb +2 -2
- data/lib/sorbet_baml/struct_extensions.rb +2 -2
- data/lib/sorbet_baml/tool_extensions.rb +23 -0
- data/lib/sorbet_baml/type_mapper.rb +35 -37
- data/lib/sorbet_baml/version.rb +1 -1
- data/lib/sorbet_baml.rb +41 -13
- data/sorbet/config +2 -0
- data/sorbet/rbi/gems/anthropic@1.5.0.rbi +21252 -0
- data/sorbet/rbi/gems/async@2.27.3.rbi +9 -0
- data/sorbet/rbi/gems/bigdecimal@3.2.2.rbi +9 -0
- data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +424 -0
- data/sorbet/rbi/gems/connection_pool@2.5.3.rbi +9 -0
- data/sorbet/rbi/gems/console@1.33.0.rbi +9 -0
- data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +672 -0
- data/sorbet/rbi/gems/dry-core@1.1.0.rbi +1729 -0
- data/sorbet/rbi/gems/dry-logger@1.1.0.rbi +1317 -0
- data/sorbet/rbi/gems/dspy@0.19.1.rbi +6677 -0
- data/sorbet/rbi/gems/ffi@1.17.2.rbi +2174 -0
- data/sorbet/rbi/gems/fiber-annotation@0.2.0.rbi +9 -0
- data/sorbet/rbi/gems/fiber-local@1.1.0.rbi +9 -0
- data/sorbet/rbi/gems/fiber-storage@1.0.1.rbi +9 -0
- data/sorbet/rbi/gems/google-protobuf@4.32.0.rbi +9 -0
- data/sorbet/rbi/gems/googleapis-common-protos-types@1.20.0.rbi +9 -0
- data/sorbet/rbi/gems/informers@1.2.1.rbi +1875 -0
- data/sorbet/rbi/gems/io-event@1.12.1.rbi +9 -0
- data/sorbet/rbi/gems/metrics@0.13.0.rbi +9 -0
- data/sorbet/rbi/gems/onnxruntime@0.10.0.rbi +304 -0
- data/sorbet/rbi/gems/openai@0.16.0.rbi +68055 -0
- data/sorbet/rbi/gems/opentelemetry-api@1.6.0.rbi +9 -0
- data/sorbet/rbi/gems/opentelemetry-common@0.22.0.rbi +9 -0
- data/sorbet/rbi/gems/opentelemetry-exporter-otlp@0.30.0.rbi +9 -0
- data/sorbet/rbi/gems/opentelemetry-registry@0.4.0.rbi +9 -0
- data/sorbet/rbi/gems/opentelemetry-sdk@1.8.1.rbi +9 -0
- data/sorbet/rbi/gems/opentelemetry-semantic_conventions@1.11.0.rbi +9 -0
- data/sorbet/rbi/gems/polars-df@0.20.0.rbi +9 -0
- data/sorbet/rbi/gems/sorbet-result@1.4.0.rbi +242 -0
- data/sorbet/rbi/gems/sorbet-schema@0.9.2.rbi +743 -0
- data/sorbet/rbi/gems/sorbet-struct-comparable@1.3.0.rbi +48 -0
- data/sorbet/rbi/gems/tokenizers@0.5.5.rbi +754 -0
- data/sorbet/rbi/gems/traces@0.17.0.rbi +9 -0
- data/sorbet/rbi/gems/zeitwerk@2.7.3.rbi +1429 -0
- metadata +63 -2
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: doc
|
|
3
|
+
title: "Getting Started"
|
|
4
|
+
description: "Learn how to install and use sorbet-baml to convert your Sorbet types to BAML for efficient LLM prompting."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Getting Started
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- Ruby 3.2+
|
|
12
|
+
- Sorbet installed in your project
|
|
13
|
+
- Basic familiarity with T::Struct
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Define your autonomous workflow types
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
# Define complex LLM workflow types for research agents
|
|
21
|
+
class TaskType < T::Enum
|
|
22
|
+
enums do
|
|
23
|
+
# Literature review and information gathering
|
|
24
|
+
Research = new('research')
|
|
25
|
+
# Combining multiple sources into coherent insights
|
|
26
|
+
Synthesis = new('synthesis')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class ResearchTask < T::Struct
|
|
31
|
+
# Clear description of the research objective
|
|
32
|
+
const :objective, String
|
|
33
|
+
# Type of research task to be performed
|
|
34
|
+
const :task_type, TaskType
|
|
35
|
+
# Strategic priority ranking (1-5 scale)
|
|
36
|
+
const :priority, Integer
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Convert to BAML
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
require 'sorbet-baml'
|
|
44
|
+
|
|
45
|
+
# Ruby-idiomatic API (recommended)
|
|
46
|
+
ResearchTask.to_baml
|
|
47
|
+
|
|
48
|
+
# Legacy API (still supported)
|
|
49
|
+
baml = SorbetBaml.from_struct(ResearchTask)
|
|
50
|
+
puts baml
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Generated BAML:**
|
|
54
|
+
```baml
|
|
55
|
+
enum TaskType {
|
|
56
|
+
"research" @description("Literature review and information gathering")
|
|
57
|
+
"synthesis" @description("Combining multiple sources into coherent insights")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class ResearchTask {
|
|
61
|
+
objective string @description("Clear description of the research objective")
|
|
62
|
+
task_type TaskType @description("Type of research task to be performed")
|
|
63
|
+
priority int @description("Strategic priority ranking (1-5 scale)")
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 3. Field descriptions are included by default
|
|
68
|
+
|
|
69
|
+
The smart defaults automatically extract field descriptions from your comments:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
class ResearchFindings < T::Struct
|
|
73
|
+
# Detailed analysis results from the research
|
|
74
|
+
const :findings, String
|
|
75
|
+
|
|
76
|
+
# Key actionable insights extracted from findings
|
|
77
|
+
const :key_insights, T::Array[String]
|
|
78
|
+
|
|
79
|
+
# Confidence level in the research quality (1-10)
|
|
80
|
+
const :confidence_score, Integer
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Generate BAML (descriptions included by default!)
|
|
84
|
+
ResearchFindings.to_baml
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Generated BAML with descriptions:**
|
|
88
|
+
```baml
|
|
89
|
+
class ResearchFindings {
|
|
90
|
+
findings string @description("Detailed analysis results from the research")
|
|
91
|
+
key_insights string[] @description("Key actionable insights extracted from findings")
|
|
92
|
+
confidence_score int @description("Confidence level in the research quality (1-10)")
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 4. Use with autonomous research agents
|
|
97
|
+
|
|
98
|
+
Include the BAML definition in your agent prompts:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
baml = ResearchTask.to_baml
|
|
102
|
+
prompt = <<~PROMPT
|
|
103
|
+
You are an autonomous research agent. Analyze the topic "AI in Healthcare" and break it down into strategic research tasks.
|
|
104
|
+
|
|
105
|
+
Schema for your output:
|
|
106
|
+
#{baml}
|
|
107
|
+
|
|
108
|
+
Provide a comprehensive task decomposition in JSON format.
|
|
109
|
+
PROMPT
|
|
110
|
+
|
|
111
|
+
# Use with OpenAI, Anthropic, or any LLM provider
|
|
112
|
+
response = llm_client.chat(prompt)
|
|
113
|
+
result = JSON.parse(response.content)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 5. Generate Tool Definitions
|
|
117
|
+
|
|
118
|
+
Create BAML tool specifications for function calling and agentic workflows:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
# Define tool parameter structures
|
|
122
|
+
class SearchTool < T::Struct
|
|
123
|
+
# The search query to execute
|
|
124
|
+
const :query, String
|
|
125
|
+
# Maximum number of results to return
|
|
126
|
+
const :limit, T.nilable(Integer)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class ReplyTool < T::Struct
|
|
130
|
+
# The response message to send back to the user
|
|
131
|
+
const :response, String
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Generate BAML tool definitions
|
|
135
|
+
SearchTool.to_baml_tool
|
|
136
|
+
ReplyTool.to_baml_tool
|
|
137
|
+
|
|
138
|
+
# Or use module API
|
|
139
|
+
SorbetBaml.from_tool(SearchTool)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Generated BAML Tool Specifications:**
|
|
143
|
+
```baml
|
|
144
|
+
class SearchTool {
|
|
145
|
+
query string @description("The search query to execute")
|
|
146
|
+
limit int? @description("Maximum number of results to return")
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
class ReplyTool {
|
|
150
|
+
response string @description("The response message to send back to the user")
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Perfect for LLM function calling schemas:**
|
|
155
|
+
```ruby
|
|
156
|
+
tools = [SearchTool, ReplyTool].map(&:to_baml_tool).join("\n\n")
|
|
157
|
+
|
|
158
|
+
prompt = <<~PROMPT
|
|
159
|
+
You have access to these tools:
|
|
160
|
+
#{tools}
|
|
161
|
+
|
|
162
|
+
Use the appropriate tool to help the user with their request.
|
|
163
|
+
PROMPT
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Next Steps
|
|
167
|
+
|
|
168
|
+
- [Type Mapping Reference](./type-mapping.md)
|
|
169
|
+
- [Advanced Usage](./advanced-usage.md)
|
|
170
|
+
- [Troubleshooting](./troubleshooting.md)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: "sorbet-baml"
|
|
4
|
+
description: "Ruby-idiomatic conversion from Sorbet types to BAML for efficient LLM prompting. 60% fewer tokens than JSON Schema while maintaining complete type information."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<div class="text-center mb-12">
|
|
8
|
+
<h1 class="text-4xl font-bold text-gray-900 mb-4">sorbet-baml</h1>
|
|
9
|
+
<p class="text-xl text-gray-600 max-w-3xl mx-auto">
|
|
10
|
+
Ruby-idiomatic conversion from Sorbet types to BAML (Boundary AI Markup Language) for efficient LLM prompting.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<div class="flex flex-wrap justify-center gap-4 mt-8">
|
|
14
|
+
<img src="https://img.shields.io/gem/v/sorbet-baml" alt="Gem Version" />
|
|
15
|
+
<img src="https://img.shields.io/gem/dt/sorbet-baml" alt="Total Downloads" />
|
|
16
|
+
<img src="https://img.shields.io/github/license/vicentereig/sorbet-baml" alt="License" />
|
|
17
|
+
<img src="https://img.shields.io/badge/Sorbet-compatible-blue" alt="Sorbet Compatible" />
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="flex flex-wrap justify-center gap-4 mt-6">
|
|
21
|
+
<a href="/sorbet-baml/getting-started/" class="bg-blue-600 text-white px-6 py-3 rounded-lg font-medium hover:bg-blue-700 transition-colors">
|
|
22
|
+
Get Started
|
|
23
|
+
</a>
|
|
24
|
+
<a href="https://github.com/vicentereig/sorbet-baml" class="bg-gray-100 text-gray-700 px-6 py-3 rounded-lg font-medium hover:bg-gray-200 transition-colors">
|
|
25
|
+
View on GitHub
|
|
26
|
+
</a>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## Why BAML?
|
|
31
|
+
|
|
32
|
+
BAML uses approximately **60% fewer tokens** than JSON Schema while maintaining complete type information, making your LLM interactions more efficient and cost-effective.
|
|
33
|
+
|
|
34
|
+
<div class="bg-blue-50 border border-blue-200 rounded-lg p-6 my-8">
|
|
35
|
+
<h3 class="text-lg font-semibold text-blue-900 mb-3">🚀 Token Efficiency Comparison</h3>
|
|
36
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
37
|
+
<div>
|
|
38
|
+
<strong>JSON Schema:</strong> ~680 tokens
|
|
39
|
+
</div>
|
|
40
|
+
<div>
|
|
41
|
+
<strong>BAML:</strong> ~320 tokens <span class="text-blue-600 font-semibold">(53% reduction)</span>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
<p class="text-blue-800 mt-3">
|
|
45
|
+
Real-world comparison from production agentic workflows using complex nested types, enums, and arrays.
|
|
46
|
+
</p>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
## Quick Example
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
# Define a Sorbet struct
|
|
53
|
+
class User < T::Struct
|
|
54
|
+
const :name, String
|
|
55
|
+
const :age, Integer
|
|
56
|
+
const :email, T.nilable(String)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Convert to BAML (Ruby-idiomatic API)
|
|
60
|
+
require 'sorbet-baml'
|
|
61
|
+
User.to_baml
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Generated BAML:**
|
|
65
|
+
```baml
|
|
66
|
+
class User {
|
|
67
|
+
name string
|
|
68
|
+
age int
|
|
69
|
+
email string?
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Key Features
|
|
74
|
+
|
|
75
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-8">
|
|
76
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
77
|
+
<h3 class="font-semibold text-gray-900 mb-2">🎯 Ruby-Idiomatic API</h3>
|
|
78
|
+
<p class="text-gray-600">Every T::Struct and T::Enum gets a natural <code>.to_baml</code> method that feels native to Ruby.</p>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
82
|
+
<h3 class="font-semibold text-gray-900 mb-2">🧠 Smart Defaults</h3>
|
|
83
|
+
<p class="text-gray-600">Field descriptions and dependencies included automatically for better LLM understanding.</p>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
87
|
+
<h3 class="font-semibold text-gray-900 mb-2">📝 Field Descriptions</h3>
|
|
88
|
+
<p class="text-gray-600">Extracts comments from source code to provide crucial context for autonomous agents.</p>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
92
|
+
<h3 class="font-semibold text-gray-900 mb-2">🔗 Dependency Management</h3>
|
|
93
|
+
<p class="text-gray-600">Automatically includes all referenced types with proper topological sorting.</p>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
97
|
+
<h3 class="font-semibold text-gray-900 mb-2">✅ Type-Safe</h3>
|
|
98
|
+
<p class="text-gray-600">Full Sorbet type checking throughout the gem with 100% test coverage.</p>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
102
|
+
<h3 class="font-semibold text-gray-900 mb-2">🛠️ Tool Definitions</h3>
|
|
103
|
+
<p class="text-gray-600">Generate BAML tool specifications for function calling and agentic workflows.</p>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<div class="bg-white p-6 rounded-lg border border-gray-200">
|
|
107
|
+
<h3 class="font-semibold text-gray-900 mb-2">🏁 Production Ready</h3>
|
|
108
|
+
<p class="text-gray-600">Complete type support, dependency management, and comprehensive test coverage.</p>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
## Complete Type Support
|
|
113
|
+
|
|
114
|
+
### Basic Types
|
|
115
|
+
- `String` → `string`
|
|
116
|
+
- `Integer` → `int`
|
|
117
|
+
- `Float` → `float`
|
|
118
|
+
- `T::Boolean` → `bool`
|
|
119
|
+
- `Symbol` → `string`
|
|
120
|
+
- `Date/DateTime/Time` → `string`
|
|
121
|
+
|
|
122
|
+
### Complex Types
|
|
123
|
+
- `T.nilable(T)` → `T?` (optional types)
|
|
124
|
+
- `T::Array[T]` → `T[]` (arrays)
|
|
125
|
+
- `T::Hash[K,V]` → `map<K,V>` (hash maps)
|
|
126
|
+
- `T.any(T1, T2)` → `T1 | T2` (union types)
|
|
127
|
+
|
|
128
|
+
### Structured Types
|
|
129
|
+
- `T::Struct` → `class Name { ... }` (classes with fields)
|
|
130
|
+
- `T::Enum` → `enum Name { "value1" "value2" }` (enums)
|
|
131
|
+
- Nested structs with proper reference handling
|
|
132
|
+
- **Automatic dependency resolution** with topological sorting
|
|
133
|
+
|
|
134
|
+
## Perfect for Agentic Workflows
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
# Define your autonomous research workflow types
|
|
138
|
+
class TaskDecomposition < T::Struct
|
|
139
|
+
# The main research topic being investigated
|
|
140
|
+
const :research_topic, String
|
|
141
|
+
# Target complexity level for the decomposition
|
|
142
|
+
const :complexity_level, ComplexityLevel
|
|
143
|
+
# Autonomously generated list of research subtasks
|
|
144
|
+
const :subtasks, T::Array[String]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Generate BAML for LLM agents
|
|
148
|
+
prompt = <<~PROMPT
|
|
149
|
+
You are an autonomous research agent. Analyze this topic and decompose it.
|
|
150
|
+
|
|
151
|
+
Schema for your output:
|
|
152
|
+
#{TaskDecomposition.to_baml}
|
|
153
|
+
|
|
154
|
+
Topic: "Impact of AI on healthcare delivery systems"
|
|
155
|
+
PROMPT
|
|
156
|
+
|
|
157
|
+
# Use with any LLM provider
|
|
158
|
+
response = llm_client.chat(prompt)
|
|
159
|
+
result = TaskDecomposition.from_json(response.content)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Installation
|
|
163
|
+
|
|
164
|
+
Add to your Gemfile:
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
gem 'sorbet-baml'
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Or install directly:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
gem install sorbet-baml
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
<div class="text-center mt-12">
|
|
179
|
+
<h2 class="text-2xl font-bold text-gray-900 mb-4">Ready to get started?</h2>
|
|
180
|
+
<a href="/sorbet-baml/getting-started/" class="bg-blue-600 text-white px-8 py-3 rounded-lg font-medium hover:bg-blue-700 transition-colors inline-block">
|
|
181
|
+
Read the Getting Started Guide →
|
|
182
|
+
</a>
|
|
183
|
+
</div>
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: doc
|
|
3
|
+
title: "Troubleshooting"
|
|
4
|
+
description: "Common issues and solutions when using sorbet-baml. Find quick fixes for installation, conversion, and usage problems."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Troubleshooting
|
|
8
|
+
|
|
9
|
+
## Common Issues
|
|
10
|
+
|
|
11
|
+
### "undefined method `props' for Class"
|
|
12
|
+
|
|
13
|
+
**Problem**: The class you're trying to convert is not a T::Struct.
|
|
14
|
+
|
|
15
|
+
**Solution**: Ensure your class inherits from `T::Struct`:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
# ❌ Wrong
|
|
19
|
+
class ResearchAgent
|
|
20
|
+
attr_reader :domain_expertise
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# ✅ Correct
|
|
24
|
+
class ResearchAgent < T::Struct
|
|
25
|
+
# Agent's specialized domain of expertise
|
|
26
|
+
const :domain_expertise, String
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Generate BAML (descriptions included by default!)
|
|
30
|
+
ResearchAgent.to_baml
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Generated BAML:**
|
|
34
|
+
```baml
|
|
35
|
+
class ResearchAgent {
|
|
36
|
+
domain_expertise string @description("Agent's specialized domain of expertise")
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Empty output
|
|
41
|
+
|
|
42
|
+
**Problem**: The struct has no properties defined.
|
|
43
|
+
|
|
44
|
+
**Solution**: Define at least one property using `const` or `prop`:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
class ResearchAgent < T::Struct
|
|
48
|
+
# Agent's specialized domain of expertise
|
|
49
|
+
const :domain_expertise, String
|
|
50
|
+
# Maximum concurrent research tasks
|
|
51
|
+
const :task_capacity, Integer
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
ResearchAgent.to_baml
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Generated BAML:**
|
|
58
|
+
```baml
|
|
59
|
+
class ResearchAgent {
|
|
60
|
+
domain_expertise string @description("Agent's specialized domain of expertise")
|
|
61
|
+
task_capacity int @description("Maximum concurrent research tasks")
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Self-referential types work fine
|
|
66
|
+
|
|
67
|
+
**Problem**: You think self-referential types aren't supported.
|
|
68
|
+
|
|
69
|
+
**Solution**: They actually work perfectly! Self-referential types are fully supported:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
class ResearchHierarchy < T::Struct
|
|
73
|
+
# Name of the research domain or subdomain
|
|
74
|
+
const :domain_name, String
|
|
75
|
+
# Parent research domain for hierarchical organization
|
|
76
|
+
const :parent_domain, T.nilable(ResearchHierarchy)
|
|
77
|
+
# Child research subdomains
|
|
78
|
+
const :subdomains, T::Array[ResearchHierarchy]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
ResearchHierarchy.to_baml
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Generated BAML:**
|
|
85
|
+
```baml
|
|
86
|
+
class ResearchHierarchy {
|
|
87
|
+
domain_name string @description("Name of the research domain or subdomain")
|
|
88
|
+
parent_domain ResearchHierarchy? @description("Parent research domain for hierarchical organization")
|
|
89
|
+
subdomains ResearchHierarchy[] @description("Child research subdomains")
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Type-Specific Issues
|
|
94
|
+
|
|
95
|
+
### Arrays not converting correctly
|
|
96
|
+
|
|
97
|
+
Ensure you're using the Sorbet array syntax:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
# ❌ Wrong
|
|
101
|
+
class ResearchAgent < T::Struct
|
|
102
|
+
const :research_methods, Array # Generic Array won't work
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# ✅ Correct
|
|
106
|
+
class ResearchAgent < T::Struct
|
|
107
|
+
# List of research methodologies the agent can employ
|
|
108
|
+
const :research_methods, T::Array[String]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
ResearchAgent.to_baml
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Generated BAML:**
|
|
115
|
+
```baml
|
|
116
|
+
class ResearchAgent {
|
|
117
|
+
research_methods string[] @description("List of research methodologies the agent can employ")
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Optional fields showing as required
|
|
122
|
+
|
|
123
|
+
Make sure to use `T.nilable`:
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
# ❌ Wrong - will be required
|
|
127
|
+
class ResearchAgent < T::Struct
|
|
128
|
+
# Peer review notes
|
|
129
|
+
const :peer_review, String
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# ✅ Correct - will be optional
|
|
133
|
+
class ResearchAgent < T::Struct
|
|
134
|
+
# Optional peer review notes
|
|
135
|
+
const :peer_review, T.nilable(String)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
ResearchAgent.to_baml
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Generated BAML:**
|
|
142
|
+
```baml
|
|
143
|
+
class ResearchAgent {
|
|
144
|
+
peer_review string? @description("Optional peer review notes")
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Union types not working
|
|
149
|
+
|
|
150
|
+
Ensure you're using `T.any` for union types:
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
# ❌ Wrong
|
|
154
|
+
class ResearchConfig < T::Struct
|
|
155
|
+
const :parameter_value, String || Integer # Ruby OR, not Sorbet union
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# ✅ Correct
|
|
159
|
+
class ResearchConfig < T::Struct
|
|
160
|
+
# Configuration parameter supporting multiple value types
|
|
161
|
+
const :parameter_value, T.any(String, Integer)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
ResearchConfig.to_baml
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Generated BAML:**
|
|
168
|
+
```baml
|
|
169
|
+
class ResearchConfig {
|
|
170
|
+
parameter_value string | int @description("Configuration parameter supporting multiple value types")
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Hash types not mapping correctly
|
|
175
|
+
|
|
176
|
+
Use the full `T::Hash[K, V]` syntax:
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
179
|
+
# ❌ Wrong
|
|
180
|
+
class ResearchAgent < T::Struct
|
|
181
|
+
const :agent_metadata, Hash # Generic Hash won't work
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# ✅ Correct
|
|
185
|
+
class ResearchAgent < T::Struct
|
|
186
|
+
# Agent coordination metadata with flexible value types
|
|
187
|
+
const :agent_metadata, T::Hash[String, T.any(String, Integer)]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
ResearchAgent.to_baml
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Generated BAML:**
|
|
194
|
+
```baml
|
|
195
|
+
class ResearchAgent {
|
|
196
|
+
agent_metadata map<string, string | int> @description("Agent coordination metadata with flexible value types")
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Dependency Issues
|
|
201
|
+
|
|
202
|
+
### Missing dependencies in output
|
|
203
|
+
|
|
204
|
+
Dependencies are included by default! Smart defaults make this automatic:
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
207
|
+
class TaskType < T::Enum
|
|
208
|
+
enums do
|
|
209
|
+
# Literature review and information gathering
|
|
210
|
+
Research = new('research')
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
class ResearchTask < T::Struct
|
|
215
|
+
# Clear description of the research objective
|
|
216
|
+
const :objective, String
|
|
217
|
+
# Type of research task to be performed
|
|
218
|
+
const :task_type, TaskType
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# ✅ Smart defaults: outputs both TaskType and ResearchTask automatically
|
|
222
|
+
ResearchTask.to_baml
|
|
223
|
+
|
|
224
|
+
# ❌ Only if you explicitly disable dependencies
|
|
225
|
+
ResearchTask.to_baml(include_dependencies: false)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Generated BAML (with dependencies by default):**
|
|
229
|
+
```baml
|
|
230
|
+
enum TaskType {
|
|
231
|
+
"research" @description("Literature review and information gathering")
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
class ResearchTask {
|
|
235
|
+
objective string @description("Clear description of the research objective")
|
|
236
|
+
task_type TaskType @description("Type of research task to be performed")
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Wrong dependency order
|
|
241
|
+
|
|
242
|
+
The gem automatically handles dependency ordering using topological sorting. Dependencies always come before the types that reference them.
|
|
243
|
+
|
|
244
|
+
## Enum Issues
|
|
245
|
+
|
|
246
|
+
### Enums not converting
|
|
247
|
+
|
|
248
|
+
Ensure you're using the correct T::Enum syntax:
|
|
249
|
+
|
|
250
|
+
```ruby
|
|
251
|
+
# ❌ Wrong
|
|
252
|
+
class ResearchStatus
|
|
253
|
+
ACTIVE = 'active'
|
|
254
|
+
COMPLETED = 'completed'
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# ✅ Correct
|
|
258
|
+
class ResearchStatus < T::Enum
|
|
259
|
+
enums do
|
|
260
|
+
# Research is actively in progress
|
|
261
|
+
Active = new('active')
|
|
262
|
+
# Research has been completed successfully
|
|
263
|
+
Completed = new('completed')
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
ResearchStatus.to_baml
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Generated BAML:**
|
|
271
|
+
```baml
|
|
272
|
+
enum ResearchStatus {
|
|
273
|
+
"active" @description("Research is actively in progress")
|
|
274
|
+
"completed" @description("Research has been completed successfully")
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Getting Help
|
|
279
|
+
|
|
280
|
+
1. Check the [Type Mapping Reference](./type-mapping.md) for complete type support
|
|
281
|
+
2. Review examples in [Getting Started](./getting-started.md) and [Advanced Usage](./advanced-usage.md)
|
|
282
|
+
3. File an issue at https://github.com/vicentereig/sorbet-baml/issues
|
|
283
|
+
|
|
284
|
+
## Advanced Debugging
|
|
285
|
+
|
|
286
|
+
### Inspect Sorbet type information
|
|
287
|
+
|
|
288
|
+
```ruby
|
|
289
|
+
# See what Sorbet sees for your struct
|
|
290
|
+
MyStruct.props
|
|
291
|
+
# => {name: String, age: Integer, ...}
|
|
292
|
+
|
|
293
|
+
# Check if a class is a T::Struct
|
|
294
|
+
MyStruct < T::Struct
|
|
295
|
+
# => true
|
|
296
|
+
|
|
297
|
+
# See enum values
|
|
298
|
+
MyEnum.values
|
|
299
|
+
# => [#<MyEnum:0x... @serialize="value1">, ...]
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Testing your BAML output
|
|
303
|
+
|
|
304
|
+
```ruby
|
|
305
|
+
# Verify the output looks correct (dependencies included by default)
|
|
306
|
+
baml = ResearchTask.to_baml
|
|
307
|
+
puts baml
|
|
308
|
+
|
|
309
|
+
# Check that all expected types are included
|
|
310
|
+
expected_types = ['class ResearchTask', 'enum TaskType']
|
|
311
|
+
expected_types.all? { |type| baml.include?(type) }
|
|
312
|
+
# => true
|
|
313
|
+
|
|
314
|
+
# Verify descriptions are included
|
|
315
|
+
baml.include?('@description')
|
|
316
|
+
# => true
|
|
317
|
+
```
|