braintrust 0.1.1 → 0.1.2

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.
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Vendored from mustache gem v1.1.1
4
+ # https://github.com/mustache/mustache
5
+ # License: MIT
6
+ # Modifications: Namespaced under Braintrust::Vendor
7
+
8
+ # Settings which can be configured for all view classes, a single
9
+ # view class, or a single Mustache instance.
10
+ module Braintrust
11
+ module Vendor
12
+ class Mustache
13
+ def initialize_settings
14
+ @template = nil
15
+ @template_path = nil
16
+ @template_extension = nil
17
+ @template_name = nil
18
+ @template_file = nil
19
+ @raise_on_context_miss = nil
20
+ end
21
+
22
+ def self.initialize_settings
23
+ @template = nil
24
+ @template_path = nil
25
+ @template_extension = nil
26
+ @template_name = nil
27
+ @template_file = nil
28
+ @raise_on_context_miss = nil
29
+ end
30
+
31
+ initialize_settings
32
+
33
+ def self.inherited(subclass)
34
+ subclass.initialize_settings
35
+ end
36
+
37
+ #
38
+ # Template Path
39
+ #
40
+
41
+ # The template path informs your Mustache view where to look for its
42
+ # corresponding template. By default it's the current directory (".")
43
+ #
44
+ # A class named Stat with a template_path of "app/templates" will look
45
+ # for "app/templates/stat.mustache"
46
+
47
+ def self.template_path
48
+ @template_path ||= inheritable_config_for :template_path, "."
49
+ end
50
+
51
+ def self.template_path=(path)
52
+ @template_path = File.expand_path(path)
53
+ @template = nil
54
+ end
55
+
56
+ def template_path
57
+ @template_path ||= self.class.template_path
58
+ end
59
+ alias_method :path, :template_path
60
+
61
+ def template_path=(path)
62
+ @template_path = File.expand_path(path)
63
+ @template = nil
64
+ end
65
+
66
+ # Alias for `template_path`
67
+ def self.path
68
+ template_path
69
+ end
70
+
71
+ # Alias for `template_path`
72
+ def self.path=(path)
73
+ self.template_path = path
74
+ end
75
+
76
+ #
77
+ # Template Extension
78
+ #
79
+
80
+ # A Mustache template's default extension is 'mustache', but this can be changed.
81
+
82
+ def self.template_extension
83
+ @template_extension ||= inheritable_config_for :template_extension, "mustache"
84
+ end
85
+
86
+ def self.template_extension=(template_extension)
87
+ @template_extension = template_extension
88
+ @template = nil
89
+ end
90
+
91
+ def template_extension
92
+ @template_extension ||= self.class.template_extension
93
+ end
94
+
95
+ def template_extension=(template_extension)
96
+ @template_extension = template_extension
97
+ @template = nil
98
+ end
99
+
100
+ #
101
+ # Template Name
102
+ #
103
+
104
+ # The template name is the Mustache template file without any
105
+ # extension or other information. Defaults to `class_name`.
106
+ #
107
+ # You may want to change this if your class is named Stat but you want
108
+ # to re-use another template.
109
+ #
110
+ # class Stat
111
+ # self.template_name = "graphs" # use graphs.mustache
112
+ # end
113
+
114
+ def self.template_name
115
+ @template_name || underscore
116
+ end
117
+
118
+ def self.template_name=(template_name)
119
+ @template_name = template_name
120
+ @template = nil
121
+ end
122
+
123
+ def template_name
124
+ @template_name ||= self.class.template_name
125
+ end
126
+
127
+ def template_name=(template_name)
128
+ @template_name = template_name
129
+ @template = nil
130
+ end
131
+
132
+ #
133
+ # Template File
134
+ #
135
+
136
+ # The template file is the absolute path of the file Mustache will
137
+ # use as its template. By default it's ./class_name.mustache
138
+
139
+ def self.template_file
140
+ @template_file || "#{path}/#{template_name}.#{template_extension}"
141
+ end
142
+
143
+ def self.template_file=(template_file)
144
+ @template_file = template_file
145
+ @template = nil
146
+ end
147
+
148
+ # The template file is the absolute path of the file Mustache will
149
+ # use as its template. By default it's ./class_name.mustache
150
+ def template_file
151
+ @template_file || "#{path}/#{template_name}.#{template_extension}"
152
+ end
153
+
154
+ def template_file=(template_file)
155
+ @template_file = template_file
156
+ @template = nil
157
+ end
158
+
159
+ #
160
+ # Template
161
+ #
162
+
163
+ # The template is the actual string Mustache uses as its template.
164
+ # There is a bit of magic here: what we get back is actually a
165
+ # Mustache::Template object, but you can still safely use `template=`
166
+ # with a string.
167
+
168
+ def self.template
169
+ @template ||= templateify(File.read(template_file))
170
+ end
171
+
172
+ def self.template=(template)
173
+ @template = templateify(template)
174
+ end
175
+
176
+ # The template can be set at the instance level.
177
+ def template
178
+ return @template if @template
179
+
180
+ # If they sent any instance-level options use that instead of the class's.
181
+ if @template_path || @template_extension || @template_name || @template_file
182
+ @template = templateify(File.read(template_file))
183
+ else
184
+ @template = self.class.template
185
+ end
186
+ end
187
+
188
+ def template=(template)
189
+ @template = templateify(template)
190
+ end
191
+
192
+ #
193
+ # Raise on context miss
194
+ #
195
+
196
+ # Should an exception be raised when we cannot find a corresponding method
197
+ # or key in the current context? By default this is false to emulate ctemplate's
198
+ # behavior, but it may be useful to enable when debugging or developing.
199
+ #
200
+ # If set to true and there is a context miss, `Mustache::ContextMiss` will
201
+ # be raised.
202
+
203
+ def self.raise_on_context_miss?
204
+ @raise_on_context_miss
205
+ end
206
+
207
+ def self.raise_on_context_miss=(boolean)
208
+ @raise_on_context_miss = boolean
209
+ end
210
+
211
+ # Instance level version of `Mustache.raise_on_context_miss?`
212
+ def raise_on_context_miss?
213
+ self.class.raise_on_context_miss? || @raise_on_context_miss
214
+ end
215
+
216
+ def raise_on_context_miss=(boolean)
217
+ @raise_on_context_miss = boolean
218
+ end
219
+
220
+ #
221
+ # View Namespace
222
+ #
223
+
224
+ # The constant under which Mustache will look for views when autoloading.
225
+ # By default the view namespace is `Object`, but it might be nice to set
226
+ # it to something like `Hurl::Views` if your app's main namespace is `Hurl`.
227
+
228
+ def self.view_namespace
229
+ @view_namespace ||= inheritable_config_for(:view_namespace, Object)
230
+ end
231
+
232
+ def self.view_namespace=(namespace)
233
+ @view_namespace = namespace
234
+ end
235
+
236
+ #
237
+ # View Path
238
+ #
239
+
240
+ # Mustache searches the view path for .rb files to require when asked to find a
241
+ # view class. Defaults to "."
242
+
243
+ def self.view_path
244
+ @view_path ||= inheritable_config_for(:view_path, ".")
245
+ end
246
+
247
+ def self.view_path=(path)
248
+ @view_path = path
249
+ end
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Vendored from mustache gem v1.1.1
4
+ # https://github.com/mustache/mustache
5
+ # License: MIT
6
+ # Modifications: Namespaced under Braintrust::Vendor
7
+
8
+ require "cgi"
9
+
10
+ require_relative "parser"
11
+ require_relative "generator"
12
+
13
+ module Braintrust
14
+ module Vendor
15
+ class Mustache
16
+ # A Template represents a Mustache template. It compiles and caches
17
+ # a raw string template into something usable.
18
+ #
19
+ # The idea is this: when handed a Mustache template, convert it into
20
+ # a Ruby string by transforming Mustache tags into interpolated
21
+ # Ruby.
22
+ #
23
+ # You shouldn't use this class directly, instead:
24
+ #
25
+ # >> Braintrust::Vendor::Mustache.render(template, hash)
26
+ class Template
27
+ attr_reader :source
28
+
29
+ # Expects a Mustache template as a string along with a template
30
+ # path, which it uses to find partials. Options may be passed.
31
+ def initialize(source, options = {})
32
+ @source = source
33
+ @options = options
34
+ end
35
+
36
+ # Renders the `@source` Mustache template using the given
37
+ # `context`, which should be a simple hash keyed with symbols.
38
+ #
39
+ # The first time a template is rendered, this method is overriden
40
+ # and from then on it is "compiled". Subsequent calls will skip
41
+ # the compilation step and run the Ruby version of the template
42
+ # directly.
43
+ def render(context)
44
+ # Compile our Mustache template into a Ruby string
45
+ compiled = "def render(ctx) #{compile} end"
46
+
47
+ # Here we rewrite ourself with the interpolated Ruby version of
48
+ # our Mustache template so subsequent calls are very fast and
49
+ # can skip the compilation stage.
50
+ instance_eval(compiled, __FILE__, __LINE__ - 1)
51
+
52
+ # Call the newly rewritten version of #render
53
+ render(context)
54
+ end
55
+
56
+ # Does the dirty work of transforming a Mustache template into an
57
+ # interpolation-friendly Ruby string.
58
+ def compile(src = @source)
59
+ Generator.new(@options).compile(tokens(src))
60
+ end
61
+ alias_method :to_s, :compile
62
+
63
+ # Returns an array of tokens for a given template.
64
+ #
65
+ # @return [Array] Array of tokens.
66
+ #
67
+ def tokens(src = @source)
68
+ Parser.new(@options).compile(src)
69
+ end
70
+
71
+ # Returns an array of tags.
72
+ #
73
+ # Tags that belong to sections will be of the form `section1.tag`.
74
+ #
75
+ # @return [Array] Returns an array of tags.
76
+ #
77
+ def tags
78
+ Template.recursor(tokens, []) do |token, section|
79
+ if [:etag, :utag].include?(token[1])
80
+ [new_token = nil, new_section = nil, result = ((section + [token[2][2][0]]).join(".")), stop = true]
81
+ elsif [:section, :inverted_section].include?(token[1])
82
+ [new_token = token[4], new_section = (section + [token[2][2][0]]), result = nil, stop = false]
83
+ else
84
+ [new_token = token, new_section = section, result = nil, stop = false]
85
+ end
86
+ end.flatten.reject(&:nil?).uniq
87
+ end
88
+
89
+ # Returns an array of sections.
90
+ #
91
+ # Sections that belong to other sections will be of the form `section1.childsection`
92
+ #
93
+ # @return [Array] Returns an array of section.
94
+ #
95
+ def sections
96
+ Template.recursor(tokens, []) do |token, section|
97
+ if [:section, :inverted_section].include?(token[1])
98
+ new_section = (section + [token[2][2][0]])
99
+ [new_token = token[4], new_section, result = new_section.join("."), stop = false]
100
+ else
101
+ [new_token = token, new_section = section, result = nil, stop = false]
102
+ end
103
+ end.flatten.reject(&:nil?).uniq
104
+ end
105
+
106
+ # Returns an array of partials.
107
+ #
108
+ # Partials that belong to sections are included, but the section name is not preserved
109
+ #
110
+ # @return [Array] Returns an array of partials.
111
+ #
112
+ def partials
113
+ Template.recursor(tokens, []) do |token, section|
114
+ if token[1] == :partial
115
+ [new_token = token, new_section = section, result = token[2], stop = true]
116
+ else
117
+ [new_token = token, new_section = section, result = nil, stop = false]
118
+ end
119
+ end.flatten.reject(&:nil?).uniq
120
+ end
121
+
122
+ # Simple recursive iterator for tokens
123
+ def self.recursor(toks, section, &block)
124
+ toks.map do |token|
125
+ next unless token.is_a? Array
126
+
127
+ if token.first == :mustache
128
+ new_token, new_section, result, stop = yield(token, section)
129
+ [result] + (stop ? [] : recursor(new_token, new_section, &block))
130
+ else
131
+ recursor(token, section, &block)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Vendored from mustache gem v1.1.1
4
+ # https://github.com/mustache/mustache
5
+ # License: MIT
6
+ # Modifications: Namespaced under Braintrust::Vendor
7
+
8
+ module Braintrust
9
+ module Vendor
10
+ class Mustache
11
+ module Utils
12
+ class String
13
+ def initialize(string)
14
+ @string = string
15
+ end
16
+
17
+ def classify
18
+ @string.split("/").map do |namespace|
19
+ namespace.split(/[-_]/).map do |part|
20
+ part[0] = part.chars.first.upcase
21
+ part
22
+ end.join
23
+ end.join("::")
24
+ end
25
+
26
+ def underscore(view_namespace)
27
+ @string
28
+ .dup
29
+ .split("#{view_namespace}::")
30
+ .last
31
+ .split("::")
32
+ .map do |part|
33
+ part[0] = part[0].downcase
34
+ part.gsub(/[A-Z]/) { |s| "_" << s.downcase }
35
+ end
36
+ .join("/")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Vendored Mustache template engine
4
+ # From mustache gem v1.1.1 - https://github.com/mustache/mustache
5
+ # License: MIT
6
+ #
7
+ # Modifications from original:
8
+ # - Namespaced under Braintrust::Vendor to avoid conflicts
9
+ # - Disabled HTML escaping (LLM prompts don't need HTML entity encoding)
10
+ #
11
+ # This vendored version ensures:
12
+ # - No external dependency required
13
+ # - Consistent behavior across all SDK users
14
+ # - No HTML escaping that would corrupt prompts containing < > & characters
15
+
16
+ require_relative "mustache/mustache"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Braintrust
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/braintrust.rb CHANGED
@@ -5,6 +5,7 @@ require_relative "braintrust/config"
5
5
  require_relative "braintrust/state"
6
6
  require_relative "braintrust/trace"
7
7
  require_relative "braintrust/api"
8
+ require_relative "braintrust/prompt"
8
9
  require_relative "braintrust/internal/experiments"
9
10
  require_relative "braintrust/internal/env"
10
11
  require_relative "braintrust/eval"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: braintrust
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Braintrust
@@ -240,15 +240,27 @@ files:
240
240
  - lib/braintrust/internal/encoding.rb
241
241
  - lib/braintrust/internal/env.rb
242
242
  - lib/braintrust/internal/experiments.rb
243
+ - lib/braintrust/internal/template.rb
243
244
  - lib/braintrust/internal/thread_pool.rb
244
245
  - lib/braintrust/internal/time.rb
245
246
  - lib/braintrust/logger.rb
247
+ - lib/braintrust/prompt.rb
246
248
  - lib/braintrust/setup.rb
247
249
  - lib/braintrust/state.rb
248
250
  - lib/braintrust/trace.rb
249
251
  - lib/braintrust/trace/attachment.rb
250
252
  - lib/braintrust/trace/span_filter.rb
251
253
  - lib/braintrust/trace/span_processor.rb
254
+ - lib/braintrust/vendor/mustache.rb
255
+ - lib/braintrust/vendor/mustache/context.rb
256
+ - lib/braintrust/vendor/mustache/context_miss.rb
257
+ - lib/braintrust/vendor/mustache/enumerable.rb
258
+ - lib/braintrust/vendor/mustache/generator.rb
259
+ - lib/braintrust/vendor/mustache/mustache.rb
260
+ - lib/braintrust/vendor/mustache/parser.rb
261
+ - lib/braintrust/vendor/mustache/settings.rb
262
+ - lib/braintrust/vendor/mustache/template.rb
263
+ - lib/braintrust/vendor/mustache/utils.rb
252
264
  - lib/braintrust/version.rb
253
265
  homepage: https://github.com/braintrustdata/braintrust-sdk-ruby
254
266
  licenses: