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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +123 -2
  3. data/Rakefile +2 -2
  4. data/docs-site/.gitignore +48 -0
  5. data/docs-site/Gemfile +5 -0
  6. data/docs-site/Gemfile.lock +140 -0
  7. data/docs-site/Rakefile +3 -0
  8. data/docs-site/bridgetown.config.yml +15 -0
  9. data/docs-site/config/initializers.rb +9 -0
  10. data/docs-site/config/puma.rb +9 -0
  11. data/docs-site/config.ru +5 -0
  12. data/docs-site/esbuild.config.js +11 -0
  13. data/docs-site/frontend/javascript/index.js +22 -0
  14. data/docs-site/frontend/styles/index.css +61 -0
  15. data/docs-site/package.json +18 -0
  16. data/docs-site/postcss.config.js +6 -0
  17. data/docs-site/server/roda_app.rb +9 -0
  18. data/docs-site/src/_components/head.liquid +26 -0
  19. data/docs-site/src/_components/nav.liquid +68 -0
  20. data/docs-site/src/_layouts/default.liquid +27 -0
  21. data/docs-site/src/_layouts/doc.liquid +39 -0
  22. data/docs-site/src/advanced-usage.md +598 -0
  23. data/docs-site/src/getting-started.md +170 -0
  24. data/docs-site/src/index.md +183 -0
  25. data/docs-site/src/troubleshooting.md +317 -0
  26. data/docs-site/src/type-mapping.md +236 -0
  27. data/docs-site/tailwind.config.js +85 -0
  28. data/examples/description_parameters.rb +16 -16
  29. data/lib/sorbet_baml/comment_extractor.rb +31 -39
  30. data/lib/sorbet_baml/converter.rb +66 -32
  31. data/lib/sorbet_baml/dependency_resolver.rb +11 -11
  32. data/lib/sorbet_baml/description_extension.rb +5 -5
  33. data/lib/sorbet_baml/description_extractor.rb +8 -10
  34. data/lib/sorbet_baml/dspy_tool_converter.rb +97 -0
  35. data/lib/sorbet_baml/dspy_tool_extensions.rb +23 -0
  36. data/lib/sorbet_baml/enum_extensions.rb +2 -2
  37. data/lib/sorbet_baml/struct_extensions.rb +2 -2
  38. data/lib/sorbet_baml/tool_extensions.rb +23 -0
  39. data/lib/sorbet_baml/type_mapper.rb +35 -37
  40. data/lib/sorbet_baml/version.rb +1 -1
  41. data/lib/sorbet_baml.rb +41 -13
  42. data/sorbet/config +2 -0
  43. data/sorbet/rbi/gems/anthropic@1.5.0.rbi +21252 -0
  44. data/sorbet/rbi/gems/async@2.27.3.rbi +9 -0
  45. data/sorbet/rbi/gems/bigdecimal@3.2.2.rbi +9 -0
  46. data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +424 -0
  47. data/sorbet/rbi/gems/connection_pool@2.5.3.rbi +9 -0
  48. data/sorbet/rbi/gems/console@1.33.0.rbi +9 -0
  49. data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +672 -0
  50. data/sorbet/rbi/gems/dry-core@1.1.0.rbi +1729 -0
  51. data/sorbet/rbi/gems/dry-logger@1.1.0.rbi +1317 -0
  52. data/sorbet/rbi/gems/dspy@0.19.1.rbi +6677 -0
  53. data/sorbet/rbi/gems/ffi@1.17.2.rbi +2174 -0
  54. data/sorbet/rbi/gems/fiber-annotation@0.2.0.rbi +9 -0
  55. data/sorbet/rbi/gems/fiber-local@1.1.0.rbi +9 -0
  56. data/sorbet/rbi/gems/fiber-storage@1.0.1.rbi +9 -0
  57. data/sorbet/rbi/gems/google-protobuf@4.32.0.rbi +9 -0
  58. data/sorbet/rbi/gems/googleapis-common-protos-types@1.20.0.rbi +9 -0
  59. data/sorbet/rbi/gems/informers@1.2.1.rbi +1875 -0
  60. data/sorbet/rbi/gems/io-event@1.12.1.rbi +9 -0
  61. data/sorbet/rbi/gems/metrics@0.13.0.rbi +9 -0
  62. data/sorbet/rbi/gems/onnxruntime@0.10.0.rbi +304 -0
  63. data/sorbet/rbi/gems/openai@0.16.0.rbi +68055 -0
  64. data/sorbet/rbi/gems/opentelemetry-api@1.6.0.rbi +9 -0
  65. data/sorbet/rbi/gems/opentelemetry-common@0.22.0.rbi +9 -0
  66. data/sorbet/rbi/gems/opentelemetry-exporter-otlp@0.30.0.rbi +9 -0
  67. data/sorbet/rbi/gems/opentelemetry-registry@0.4.0.rbi +9 -0
  68. data/sorbet/rbi/gems/opentelemetry-sdk@1.8.1.rbi +9 -0
  69. data/sorbet/rbi/gems/opentelemetry-semantic_conventions@1.11.0.rbi +9 -0
  70. data/sorbet/rbi/gems/polars-df@0.20.0.rbi +9 -0
  71. data/sorbet/rbi/gems/sorbet-result@1.4.0.rbi +242 -0
  72. data/sorbet/rbi/gems/sorbet-schema@0.9.2.rbi +743 -0
  73. data/sorbet/rbi/gems/sorbet-struct-comparable@1.3.0.rbi +48 -0
  74. data/sorbet/rbi/gems/tokenizers@0.5.5.rbi +754 -0
  75. data/sorbet/rbi/gems/traces@0.17.0.rbi +9 -0
  76. data/sorbet/rbi/gems/zeitwerk@2.7.3.rbi +1429 -0
  77. metadata +63 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6ebc9d978b525e29a1a19ef184f073393d6a588e54d84dc2b9fd7034d1fa40c
4
- data.tar.gz: f7d5e028fe65a4a4cc9b19c60dc17dd65fd13353634e55201db5189bb457447a
3
+ metadata.gz: eb876085f297285bbd07f7fd02c272417eade6ee6a33bd23632652746b1261d3
4
+ data.tar.gz: 8053e7074130ab128679fbc7a6c88d97fd2f3aaafb5c1637ab98271025fcdf69
5
5
  SHA512:
6
- metadata.gz: 40b4736cc561b5135ee32e08543148c018ea9963e016c6cbb66697cd346ff7cf30f7438d370853c045b40d062a47f38d7aaa1a9c6c8e92f8e7f6721b495966e0
7
- data.tar.gz: 0caf0a19906655bbfae88723bbe5b38301601c1523c3cc3b8dc31a15bf6bdd02ceacb790cf0d4bddf718c1162ba51d7b0fcd08110578616cd7c7ac27272bcd42
6
+ metadata.gz: cb1ef5173f16930f836eac60d64ca3c3e7a98de3b1aed127012f46497b72c09fade60b34d55e9aee40e8966db3d38361706c6d9c5bdb31a1f4af7761501263c6
7
+ data.tar.gz: 695791bb1caee6b763437aa5f5d6688640f5792a482372eb08a5e3da74ce7a007aed166f130945b736bc47bc4030d50a24c38910b99543b5d1ea533538a31119
data/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # sorbet-baml
2
2
 
3
+ [![Gem Version](https://img.shields.io/gem/v/sorbet-baml)](https://rubygems.org/gems/sorbet-baml)
4
+ [![Total Downloads](https://img.shields.io/gem/dt/sorbet-baml)](https://rubygems.org/gems/sorbet-baml)
5
+ [![License](https://img.shields.io/github/license/vicentereig/sorbet-baml)](https://github.com/vicentereig/sorbet-baml/blob/main/LICENSE.txt)
6
+ [![Sorbet Compatible](https://img.shields.io/badge/Sorbet-compatible-blue)](https://sorbet.org)
7
+
3
8
  Ruby-idiomatic conversion from Sorbet types to BAML (Boundary AI Markup Language) for efficient LLM prompting.
4
9
 
5
10
  ## What is this?
@@ -193,6 +198,113 @@ ResearchSubtask.to_baml
193
198
 
194
199
  **Why descriptions matter**: LLMs use field descriptions to understand context and generate more accurate, meaningful data. This is crucial for complex domains where field names alone aren't sufficient.
195
200
 
201
+ ## 🛠️ Tool Type Definitions
202
+
203
+ Generate BAML tool specifications for agentic workflows, function calling, and structured LLM interactions:
204
+
205
+ ### T::Struct-based Tools
206
+
207
+ ```ruby
208
+ class ReplyTool < T::Struct
209
+ # The response message to send back to the user
210
+ const :response, String
211
+ end
212
+
213
+ class SearchTool < T::Struct
214
+ # The search query to execute
215
+ const :query, String
216
+ # Maximum number of results to return
217
+ const :limit, T.nilable(Integer)
218
+ end
219
+
220
+ # Generate BAML tool definitions
221
+ ReplyTool.to_baml_tool
222
+ # =>
223
+ # class ReplyTool {
224
+ # response string @description("The response message to send back to the user")
225
+ # }
226
+
227
+ SearchTool.to_baml_tool
228
+ # =>
229
+ # class SearchTool {
230
+ # query string @description("The search query to execute")
231
+ # limit int? @description("Maximum number of results to return")
232
+ # }
233
+
234
+ # Module API also available
235
+ SorbetBaml.from_tool(ReplyTool)
236
+ ```
237
+
238
+ ### DSPy-style Tools (Optional)
239
+
240
+ When `dspy.rb` is available, automatically convert DSPy tools with rich metadata:
241
+
242
+ ```ruby
243
+ class CalculatorTool < DSPy::Tools::Base
244
+ extend T::Sig
245
+
246
+ tool_name 'calculator'
247
+ tool_description 'Performs basic arithmetic operations'
248
+
249
+ sig { params(operation: String, num1: Float, num2: Float).returns(T.any(Float, String)) }
250
+ def call(operation:, num1:, num2:)
251
+ case operation.downcase
252
+ when 'add' then num1 + num2
253
+ when 'subtract' then num1 - num2
254
+ when 'multiply' then num1 * num2
255
+ when 'divide'
256
+ return "Error: Cannot divide by zero" if num2 == 0
257
+ num1 / num2
258
+ else
259
+ "Error: Unknown operation '#{operation}'. Use add, subtract, multiply, or divide"
260
+ end
261
+ end
262
+ end
263
+
264
+ # Automatic extraction of tool metadata and parameter types
265
+ CalculatorTool.to_baml
266
+ # =>
267
+ # // Performs basic arithmetic operations
268
+ # class calculator {
269
+ # operation string @description("Parameter operation")
270
+ # num1 float @description("Parameter num1")
271
+ # num2 float @description("Parameter num2")
272
+ # }
273
+
274
+ # Optional parameters handled correctly
275
+ class SearchTool < DSPy::Tools::Base
276
+ extend T::Sig
277
+
278
+ tool_name 'search'
279
+ tool_description 'Search for information'
280
+
281
+ sig { params(query: String, limit: T.nilable(Integer)).returns(T::Array[String]) }
282
+ def call(query:, limit: nil)
283
+ # Implementation...
284
+ end
285
+ end
286
+
287
+ SearchTool.to_baml
288
+ # =>
289
+ # // Search for information
290
+ # class search {
291
+ # query string @description("Parameter query")
292
+ # limit int? @description("Parameter limit (optional)")
293
+ # }
294
+
295
+ # Module API also available
296
+ SorbetBaml.from_dspy_tool(CalculatorTool)
297
+ ```
298
+
299
+ **Tool Features:**
300
+ - ✅ **T::Struct tools**: Convert any struct to BAML tool definition
301
+ - ✅ **DSPy integration**: Automatic extraction from DSPy::Tools::Base classes
302
+ - ✅ **Parameter types**: Full Sorbet type support (string, int, float, arrays, maps, etc.)
303
+ - ✅ **Optional parameters**: Automatically detect and mark with `?`
304
+ - ✅ **Descriptions**: Extract from comments (T::Struct) or automatic generation (DSPy)
305
+ - ✅ **Tool metadata**: Names, descriptions, and parameter documentation
306
+ - ✅ **Ruby-idiomatic**: `.to_baml_tool()` and `.to_baml()` methods
307
+
196
308
  ## 🎯 Complete Type Support
197
309
 
198
310
  ### ✅ Fully Supported
@@ -222,6 +334,8 @@ ResearchSubtask.to_baml
222
334
  ### 🚀 Advanced Features
223
335
 
224
336
  - **Ruby-idiomatic API**: Every T::Struct and T::Enum gets `.to_baml` method
337
+ - **Tool definitions**: Generate BAML tool specs for function calling and agentic workflows
338
+ - **DSPy integration**: Automatic tool conversion from DSPy::Tools::Base classes
225
339
  - **Smart defaults**: Field descriptions and dependencies included automatically
226
340
  - **Field descriptions**: Extracts comments from source code for LLM context
227
341
  - **Dependency management**: Automatically includes all referenced types
@@ -249,21 +363,25 @@ ResearchSubtask.to_baml
249
363
 
250
364
  ## 🏁 Production Ready
251
365
 
252
- This gem has reached **feature completeness** for core BAML conversion needs. The Ruby-idiomatic API is stable and thoroughly tested with **50+ test cases** covering all type combinations and edge cases.
366
+ This gem has reached **feature completeness** for core BAML conversion needs. The Ruby-idiomatic API is stable and thoroughly tested with **80+ test cases** covering all type combinations, tool definitions, and edge cases.
253
367
 
254
368
  ### 📊 Quality Metrics
255
369
 
256
370
  - ✅ **100% Test Coverage** - All features comprehensively tested
257
371
  - ✅ **Full Sorbet Type Safety** - Zero type errors throughout codebase
258
- - ✅ **50+ Test Cases** - Covering basic types, complex combinations, and edge cases
372
+ - ✅ **80+ Test Cases** - Covering basic types, complex combinations, tool definitions, and edge cases
259
373
  - ✅ **TDD Development** - All features built test-first
260
374
  - ✅ **Field Descriptions** - Automatic comment extraction for LLM context
375
+ - ✅ **Tool Definitions** - BAML tool specifications for function calling and agentic workflows
376
+ - ✅ **DSPy Integration** - Automatic tool conversion from DSPy::Tools::Base classes
261
377
  - ✅ **Smart Defaults** - Dependencies and descriptions included by default
262
378
  - ✅ **Zero Breaking Changes** - Maintains backward compatibility
263
379
 
264
380
  ### ✅ Complete Feature Set
265
381
 
266
382
  - ✅ **Ruby-idiomatic API**: Every T::Struct and T::Enum gets `.to_baml` method
383
+ - ✅ **Tool definitions**: Generate BAML tool specifications from T::Struct classes
384
+ - ✅ **DSPy integration**: Automatic tool conversion from DSPy::Tools::Base classes
267
385
  - ✅ **Smart defaults**: Field descriptions and dependencies included automatically
268
386
  - ✅ **Field descriptions**: Extract documentation from comments for LLM context
269
387
  - ✅ **Dependency management**: Automatically includes all referenced types
@@ -272,6 +390,7 @@ This gem has reached **feature completeness** for core BAML conversion needs. Th
272
390
 
273
391
  ### 🗺️ Future Enhancements (Optional)
274
392
 
393
+ - [ ] **DSPy-independent tool API**: Tools shouldn't require DSPy, just follow the same API pattern
275
394
  - [ ] **Type aliases**: `T.type_alias { String }` → `type Alias = string`
276
395
  - [ ] **Custom naming**: Convert between snake_case ↔ camelCase
277
396
  - [ ] **CLI tool**: `sorbet-baml convert MyStruct` command
@@ -282,6 +401,8 @@ This gem has reached **feature completeness** for core BAML conversion needs. Th
282
401
 
283
402
  - **v0.0.1** - Initial implementation with basic type support
284
403
  - **v0.1.0** - Complete type system + Ruby-idiomatic API + field descriptions + smart defaults
404
+ - **v0.2.0** - Description parameter support and enhanced field extraction
405
+ - **v0.3.0** - Tool type definitions + DSPy integration + 80+ test cases + comprehensive documentation
285
406
 
286
407
  ## 🌟 Real-World Usage: Autonomous Research Agents
287
408
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
@@ -0,0 +1,48 @@
1
+ # Dependencies
2
+ node_modules/
3
+ .pnp
4
+ .pnp.js
5
+
6
+ # Build outputs
7
+ output/
8
+ dist/
9
+
10
+ # Cache directories
11
+ .bridgetown-cache/
12
+ .tmp/
13
+
14
+ # Environment files
15
+ .env
16
+ .env.local
17
+ .env.development.local
18
+ .env.test.local
19
+ .env.production.local
20
+
21
+ # System files
22
+ .DS_Store
23
+ .DS_Store?
24
+ ._*
25
+ .Spotlight-V100
26
+ .Trashes
27
+ ehthumbs.db
28
+ Thumbs.db
29
+
30
+ # Editor files
31
+ .vscode/
32
+ .idea/
33
+ *.swp
34
+ *.swo
35
+ *~
36
+
37
+ # Log files
38
+ npm-debug.log*
39
+ yarn-debug.log*
40
+ yarn-error.log*
41
+ lerna-debug.log*
42
+
43
+ # Package lock files (keep only one)
44
+ package-lock.json
45
+
46
+ # Ruby
47
+ .bundle/
48
+ vendor/bundle
data/docs-site/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ gem 'bridgetown', '~> 1.3.4'
5
+ gem 'puma', '< 7'
@@ -0,0 +1,140 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activemodel (7.2.2.2)
5
+ activesupport (= 7.2.2.2)
6
+ activesupport (7.2.2.2)
7
+ base64
8
+ benchmark (>= 0.3)
9
+ bigdecimal
10
+ concurrent-ruby (~> 1.0, >= 1.3.1)
11
+ connection_pool (>= 2.2.5)
12
+ drb
13
+ i18n (>= 1.6, < 2)
14
+ logger (>= 1.4.2)
15
+ minitest (>= 5.1)
16
+ securerandom (>= 0.3)
17
+ tzinfo (~> 2.0, >= 2.0.5)
18
+ addressable (2.8.7)
19
+ public_suffix (>= 2.0.2, < 7.0)
20
+ amazing_print (1.8.1)
21
+ base64 (0.3.0)
22
+ benchmark (0.4.1)
23
+ bigdecimal (3.2.2)
24
+ bridgetown (1.3.4)
25
+ bridgetown-builder (= 1.3.4)
26
+ bridgetown-core (= 1.3.4)
27
+ bridgetown-paginate (= 1.3.4)
28
+ bridgetown-builder (1.3.4)
29
+ bridgetown-core (= 1.3.4)
30
+ bridgetown-core (1.3.4)
31
+ activemodel (>= 6.0, < 8.0)
32
+ activesupport (>= 6.0, < 8.0)
33
+ addressable (~> 2.4)
34
+ amazing_print (~> 1.2)
35
+ colorator (~> 1.0)
36
+ csv (~> 3.2)
37
+ erubi (~> 1.9)
38
+ faraday (~> 2.0)
39
+ faraday-follow_redirects (~> 0.3)
40
+ hash_with_dot_access (~> 1.2)
41
+ i18n (~> 1.0)
42
+ kramdown (~> 2.1)
43
+ kramdown-parser-gfm (~> 1.0)
44
+ liquid (>= 5.0, < 5.5)
45
+ listen (~> 3.0)
46
+ rake (>= 13.0)
47
+ roda (~> 3.46)
48
+ rouge (>= 3.0, < 5.0)
49
+ serbea (~> 1.0)
50
+ thor (~> 1.1)
51
+ tilt (~> 2.0)
52
+ zeitwerk (~> 2.5)
53
+ bridgetown-paginate (1.3.4)
54
+ bridgetown-core (= 1.3.4)
55
+ colorator (1.1.0)
56
+ concurrent-ruby (1.3.5)
57
+ connection_pool (2.5.3)
58
+ csv (3.3.5)
59
+ drb (2.2.3)
60
+ erubi (1.13.1)
61
+ faraday (2.13.4)
62
+ faraday-net_http (>= 2.0, < 3.5)
63
+ json
64
+ logger
65
+ faraday-follow_redirects (0.3.0)
66
+ faraday (>= 1, < 3)
67
+ faraday-net_http (3.4.1)
68
+ net-http (>= 0.5.0)
69
+ ffi (1.17.2)
70
+ ffi (1.17.2-aarch64-linux-gnu)
71
+ ffi (1.17.2-aarch64-linux-musl)
72
+ ffi (1.17.2-arm-linux-gnu)
73
+ ffi (1.17.2-arm-linux-musl)
74
+ ffi (1.17.2-arm64-darwin)
75
+ ffi (1.17.2-x86-linux-gnu)
76
+ ffi (1.17.2-x86-linux-musl)
77
+ ffi (1.17.2-x86_64-darwin)
78
+ ffi (1.17.2-x86_64-linux-gnu)
79
+ ffi (1.17.2-x86_64-linux-musl)
80
+ hash_with_dot_access (1.2.0)
81
+ activesupport (>= 5.0.0, < 8.0)
82
+ i18n (1.14.7)
83
+ concurrent-ruby (~> 1.0)
84
+ json (2.13.2)
85
+ kramdown (2.5.1)
86
+ rexml (>= 3.3.9)
87
+ kramdown-parser-gfm (1.1.0)
88
+ kramdown (~> 2.0)
89
+ liquid (5.4.0)
90
+ listen (3.9.0)
91
+ rb-fsevent (~> 0.10, >= 0.10.3)
92
+ rb-inotify (~> 0.9, >= 0.9.10)
93
+ logger (1.7.0)
94
+ minitest (5.25.5)
95
+ net-http (0.6.0)
96
+ uri
97
+ nio4r (2.7.4)
98
+ public_suffix (6.0.2)
99
+ puma (6.6.1)
100
+ nio4r (~> 2.0)
101
+ rack (3.2.0)
102
+ rake (13.3.0)
103
+ rb-fsevent (0.11.2)
104
+ rb-inotify (0.11.1)
105
+ ffi (~> 1.0)
106
+ rexml (3.4.1)
107
+ roda (3.95.0)
108
+ rack
109
+ rouge (4.6.0)
110
+ securerandom (0.4.1)
111
+ serbea (1.0.1)
112
+ activesupport (>= 6.0)
113
+ erubi (>= 1.10)
114
+ tilt (~> 2.0)
115
+ thor (1.4.0)
116
+ tilt (2.6.1)
117
+ tzinfo (2.0.6)
118
+ concurrent-ruby (~> 1.0)
119
+ uri (1.0.3)
120
+ zeitwerk (2.7.3)
121
+
122
+ PLATFORMS
123
+ aarch64-linux-gnu
124
+ aarch64-linux-musl
125
+ arm-linux-gnu
126
+ arm-linux-musl
127
+ arm64-darwin
128
+ ruby
129
+ x86-linux-gnu
130
+ x86-linux-musl
131
+ x86_64-darwin
132
+ x86_64-linux-gnu
133
+ x86_64-linux-musl
134
+
135
+ DEPENDENCIES
136
+ bridgetown (~> 1.3.4)
137
+ puma (< 7)
138
+
139
+ BUNDLED WITH
140
+ 2.6.9
@@ -0,0 +1,3 @@
1
+ require 'bridgetown'
2
+
3
+ Bridgetown.load_tasks
@@ -0,0 +1,15 @@
1
+ # Welcome to Bridgetown!
2
+ #
3
+ # This config file is for settings that affect your whole site, values
4
+ # which you are expected to set up once and rarely edit after that.
5
+
6
+ url: "https://vicentereig.github.io"
7
+ base_path: "/sorbet-baml"
8
+
9
+ permalink: "/:title/"
10
+ template_engine: liquid
11
+
12
+ # Meta information
13
+ title: "sorbet-baml"
14
+ description: "Ruby-idiomatic conversion from Sorbet types to BAML for efficient LLM prompting"
15
+ author: "Vicente Reig"
@@ -0,0 +1,9 @@
1
+ # Bridgetown Configuration
2
+
3
+ # Add frontend asset configurations
4
+ Bridgetown.configure do |config|
5
+ # Configure esbuild
6
+ config.frontend_bundling_path = 'output'
7
+
8
+ # Other configurations can go here
9
+ end
@@ -0,0 +1,9 @@
1
+ if ENV['BRIDGETOWN_ENV'] == 'production'
2
+ bind "tcp://0.0.0.0:#{ENV.fetch('PORT', 4000)}"
3
+ else
4
+ bind "tcp://127.0.0.1:#{ENV.fetch('PORT', 4000)}"
5
+ end
6
+
7
+ environment ENV.fetch('BRIDGETOWN_ENV', 'development')
8
+
9
+ plugin :tmp_restart
@@ -0,0 +1,5 @@
1
+ require 'bridgetown-core/rack/boot'
2
+
3
+ Bridgetown::Rack.boot
4
+
5
+ run RodaApp.freeze.app
@@ -0,0 +1,11 @@
1
+ const esbuildOptions = {
2
+ target: "es2020",
3
+ minify: process.argv.includes("--minify"),
4
+ bundle: true,
5
+ entryPoints: ["frontend/javascript/index.js"],
6
+ outdir: "output/_bridgetown/static",
7
+ entryNames: "index.[hash]",
8
+ publicPath: "/sorbet-baml/_bridgetown/static",
9
+ }
10
+
11
+ module.exports = esbuildOptions
@@ -0,0 +1,22 @@
1
+ import "../styles/index.css"
2
+ import Plausible from 'plausible-tracker'
3
+
4
+ // Initialize Plausible Analytics
5
+ const plausible = Plausible({
6
+ domain: 'vicentereig.github.io'
7
+ })
8
+
9
+ // Track page views automatically
10
+ plausible.trackPageview()
11
+
12
+ // Mobile menu toggle
13
+ document.addEventListener('DOMContentLoaded', function() {
14
+ const mobileMenuButton = document.getElementById('mobile-menu-button');
15
+ const mobileMenu = document.getElementById('mobile-menu');
16
+
17
+ if (mobileMenuButton && mobileMenu) {
18
+ mobileMenuButton.addEventListener('click', function() {
19
+ mobileMenu.classList.toggle('hidden');
20
+ });
21
+ }
22
+ });
@@ -0,0 +1,61 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ html {
7
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
8
+ }
9
+
10
+ body {
11
+ line-height: 1.6;
12
+ color: #374151;
13
+ }
14
+
15
+ h1, h2, h3, h4, h5, h6 {
16
+ font-weight: 600;
17
+ line-height: 1.25;
18
+ }
19
+ }
20
+
21
+ @layer components {
22
+ .nav-link {
23
+ @apply block px-3 py-2 text-gray-700 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors;
24
+ }
25
+
26
+ .nav-link.active {
27
+ @apply text-blue-600 bg-blue-50;
28
+ }
29
+
30
+ .code-block {
31
+ @apply bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto;
32
+ }
33
+
34
+ .prose code {
35
+ @apply text-sm;
36
+ }
37
+
38
+ .prose pre {
39
+ @apply bg-gray-900 text-gray-100;
40
+ }
41
+
42
+ .prose pre code {
43
+ @apply text-gray-100;
44
+ }
45
+ }
46
+
47
+ /* Syntax highlighting */
48
+ .highlight {
49
+ @apply rounded-lg;
50
+ }
51
+
52
+ .highlight pre {
53
+ @apply m-0 p-4 bg-gray-900 text-gray-100 overflow-x-auto;
54
+ }
55
+
56
+ .highlight .k { color: #c678dd; } /* Keyword */
57
+ .highlight .s { color: #98c379; } /* String */
58
+ .highlight .c { color: #5c6370; } /* Comment */
59
+ .highlight .n { color: #e06c75; } /* Name */
60
+ .highlight .nb { color: #61afef; } /* Builtin */
61
+ .highlight .nf { color: #61afef; } /* Function */
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "sorbet-baml-docs",
3
+ "private": true,
4
+ "scripts": {
5
+ "dev": "bridgetown start",
6
+ "build": "bridgetown build"
7
+ },
8
+ "devDependencies": {
9
+ "@tailwindcss/typography": "^0.5.0",
10
+ "autoprefixer": "^10.4.0",
11
+ "esbuild": "^0.19.0",
12
+ "postcss": "^8.4.0",
13
+ "tailwindcss": "^3.3.0"
14
+ },
15
+ "dependencies": {
16
+ "plausible-tracker": "^0.3.9"
17
+ }
18
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,9 @@
1
+ class RodaApp < Bridgetown::Rack::Roda
2
+ route do |r|
3
+ # Handle static assets first
4
+ r.public
5
+
6
+ # Handle Bridgetown routes
7
+ r.bridgetown
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ <title>{% if title %}{{ title }} | {% endif %}{{ site.title }}</title>
2
+ <meta charset="utf-8" />
3
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
4
+ <meta name="description" content="{% if description %}{{ description }}{% else %}{{ site.description }}{% endif %}" />
5
+ <meta name="author" content="{{ site.author }}" />
6
+
7
+ <!-- Open Graph tags -->
8
+ <meta property="og:title" content="{% if title %}{{ title }} | {% endif %}{{ site.title }}" />
9
+ <meta property="og:description" content="{% if description %}{{ description }}{% else %}{{ site.description }}{% endif %}" />
10
+ <meta property="og:type" content="website" />
11
+ <meta property="og:url" content="{{ site.url }}{{ site.base_path }}{{ page.url }}" />
12
+ <meta property="og:site_name" content="{{ site.title }}" />
13
+
14
+ <!-- Twitter Card tags -->
15
+ <meta name="twitter:card" content="summary" />
16
+ <meta name="twitter:title" content="{% if title %}{{ title }} | {% endif %}{{ site.title }}" />
17
+ <meta name="twitter:description" content="{% if description %}{{ description }}{% else %}{{ site.description }}{% endif %}" />
18
+
19
+ <!-- Links -->
20
+ <link rel="canonical" href="{{ site.url }}{{ site.base_path }}{{ page.url }}" />
21
+
22
+ {% if site.base_path %}
23
+ <link rel="stylesheet" href="{{ site.base_path }}/_bridgetown/static/index.QMORYXZK.css">
24
+ {% else %}
25
+ <link rel="stylesheet" href="/_bridgetown/static/index.QMORYXZK.css">
26
+ {% endif %}
@@ -0,0 +1,68 @@
1
+ <nav class="bg-white border-b border-gray-200 sticky top-0 z-50">
2
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
3
+ <div class="flex justify-between h-16">
4
+ <div class="flex items-center">
5
+ <a href="{{ '/' | relative_url }}" class="flex items-center">
6
+ <span class="text-xl font-bold text-gray-900">sorbet-baml</span>
7
+ </a>
8
+ </div>
9
+
10
+ <!-- Desktop navigation -->
11
+ <div class="hidden md:flex items-center space-x-8">
12
+ <a href="{{ '/' | relative_url }}" class="nav-link {% if page.url == '/' %}active{% endif %}">
13
+ Home
14
+ </a>
15
+ <a href="{{ '/getting-started/' | relative_url }}" class="nav-link {% if page.url contains 'getting-started' %}active{% endif %}">
16
+ Getting Started
17
+ </a>
18
+ <a href="{{ '/type-mapping/' | relative_url }}" class="nav-link {% if page.url contains 'type-mapping' %}active{% endif %}">
19
+ Type Mapping
20
+ </a>
21
+ <a href="{{ '/advanced-usage/' | relative_url }}" class="nav-link {% if page.url contains 'advanced-usage' %}active{% endif %}">
22
+ Advanced Usage
23
+ </a>
24
+ <a href="{{ '/troubleshooting/' | relative_url }}" class="nav-link {% if page.url contains 'troubleshooting' %}active{% endif %}">
25
+ Troubleshooting
26
+ </a>
27
+ <a href="https://github.com/vicentereig/sorbet-baml" class="text-gray-500 hover:text-gray-700 p-1" target="_blank" rel="noopener" title="GitHub Repository">
28
+ <svg style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
29
+ <path fill-rule="evenodd" d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z" clip-rule="evenodd"></path>
30
+ </svg>
31
+ </a>
32
+ </div>
33
+
34
+ <!-- Mobile menu button -->
35
+ <div class="md:hidden flex items-center">
36
+ <button type="button" class="text-gray-500 hover:text-gray-700 focus:outline-none focus:text-gray-700" id="mobile-menu-button">
37
+ <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
38
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
39
+ </svg>
40
+ </button>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <!-- Mobile menu -->
46
+ <div class="md:hidden hidden" id="mobile-menu">
47
+ <div class="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white border-t border-gray-200">
48
+ <a href="{{ '/' | relative_url }}" class="nav-link {% if page.url == '/' %}active{% endif %}">
49
+ Home
50
+ </a>
51
+ <a href="{{ '/getting-started/' | relative_url }}" class="nav-link {% if page.url contains 'getting-started' %}active{% endif %}">
52
+ Getting Started
53
+ </a>
54
+ <a href="{{ '/type-mapping/' | relative_url }}" class="nav-link {% if page.url contains 'type-mapping' %}active{% endif %}">
55
+ Type Mapping
56
+ </a>
57
+ <a href="{{ '/advanced-usage/' | relative_url }}" class="nav-link {% if page.url contains 'advanced-usage' %}active{% endif %}">
58
+ Advanced Usage
59
+ </a>
60
+ <a href="{{ '/troubleshooting/' | relative_url }}" class="nav-link {% if page.url contains 'troubleshooting' %}active{% endif %}">
61
+ Troubleshooting
62
+ </a>
63
+ <a href="https://github.com/vicentereig/sorbet-baml" class="nav-link" target="_blank" rel="noopener">
64
+ GitHub
65
+ </a>
66
+ </div>
67
+ </div>
68
+ </nav>