ruby_llm-contract 0.2.3 → 0.3.6
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/CHANGELOG.md +64 -0
- data/Gemfile.lock +2 -2
- data/README.md +27 -2
- data/lib/ruby_llm/contract/adapters/response.rb +4 -2
- data/lib/ruby_llm/contract/adapters/ruby_llm.rb +3 -3
- data/lib/ruby_llm/contract/adapters/test.rb +3 -2
- data/lib/ruby_llm/contract/concerns/deep_freeze.rb +23 -0
- data/lib/ruby_llm/contract/concerns/eval_host.rb +11 -2
- data/lib/ruby_llm/contract/contract/schema_validator.rb +70 -3
- data/lib/ruby_llm/contract/eval/baseline_diff.rb +92 -0
- data/lib/ruby_llm/contract/eval/dataset.rb +11 -4
- data/lib/ruby_llm/contract/eval/eval_definition.rb +36 -14
- data/lib/ruby_llm/contract/eval/model_comparison.rb +1 -1
- data/lib/ruby_llm/contract/eval/report.rb +71 -2
- data/lib/ruby_llm/contract/eval/runner.rb +5 -3
- data/lib/ruby_llm/contract/eval/trait_evaluator.rb +6 -0
- data/lib/ruby_llm/contract/eval.rb +1 -0
- data/lib/ruby_llm/contract/pipeline/base.rb +1 -1
- data/lib/ruby_llm/contract/pipeline/result.rb +1 -1
- data/lib/ruby_llm/contract/pipeline/runner.rb +1 -1
- data/lib/ruby_llm/contract/pipeline/trace.rb +3 -2
- data/lib/ruby_llm/contract/prompt/builder.rb +2 -1
- data/lib/ruby_llm/contract/prompt/node.rb +2 -2
- data/lib/ruby_llm/contract/prompt/nodes/example_node.rb +2 -2
- data/lib/ruby_llm/contract/rake_task.rb +31 -4
- data/lib/ruby_llm/contract/rspec/helpers.rb +28 -8
- data/lib/ruby_llm/contract/rspec/pass_eval.rb +23 -2
- data/lib/ruby_llm/contract/step/base.rb +10 -5
- data/lib/ruby_llm/contract/step/dsl.rb +1 -1
- data/lib/ruby_llm/contract/step/limit_checker.rb +1 -1
- data/lib/ruby_llm/contract/step/retry_executor.rb +3 -2
- data/lib/ruby_llm/contract/step/retry_policy.rb +7 -1
- data/lib/ruby_llm/contract/step/runner.rb +10 -2
- data/lib/ruby_llm/contract/step/trace.rb +5 -4
- data/lib/ruby_llm/contract/version.rb +1 -1
- data/lib/ruby_llm/contract.rb +36 -17
- metadata +3 -1
data/lib/ruby_llm/contract.rb
CHANGED
|
@@ -40,25 +40,25 @@ module RubyLLM
|
|
|
40
40
|
@eval_hosts = []
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def load_evals!(
|
|
44
|
-
dirs =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else
|
|
52
|
-
[]
|
|
53
|
-
end
|
|
43
|
+
def load_evals!(*dirs)
|
|
44
|
+
dirs = dirs.flatten.compact
|
|
45
|
+
if dirs.empty? && defined?(::Rails)
|
|
46
|
+
dirs = %w[app/steps/eval app/contracts/eval].filter_map do |path|
|
|
47
|
+
full = ::Rails.root.join(path)
|
|
48
|
+
full.to_s if full.exist?
|
|
49
|
+
end
|
|
50
|
+
end
|
|
54
51
|
|
|
55
52
|
return if dirs.empty?
|
|
56
53
|
|
|
57
|
-
#
|
|
58
|
-
#
|
|
54
|
+
# In Rails, eager-load parent directories so contract classes
|
|
55
|
+
# are available when eval files reference them.
|
|
56
|
+
eager_load_contract_dirs! if defined?(::Rails)
|
|
57
|
+
|
|
58
|
+
# Clear file-sourced evals ONCE, then load ALL dirs.
|
|
59
59
|
Thread.current[:ruby_llm_contract_reloading] = true
|
|
60
60
|
eval_hosts.each do |host|
|
|
61
|
-
host.
|
|
61
|
+
host.clear_file_sourced_evals! if host.respond_to?(:clear_file_sourced_evals!)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
dirs.each do |d|
|
|
@@ -70,10 +70,28 @@ module RubyLLM
|
|
|
70
70
|
|
|
71
71
|
private
|
|
72
72
|
|
|
73
|
-
# Filter
|
|
73
|
+
# Filter stale hosts, deduplicate by name (last wins), prune registry in-place
|
|
74
74
|
def live_eval_hosts
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
# Remove hosts without evals
|
|
76
|
+
@eval_hosts&.reject! { |h| !h.respond_to?(:eval_defined?) || !h.eval_defined? }
|
|
77
|
+
|
|
78
|
+
# Deduplicate: if two classes share a name (reload), keep the latest
|
|
79
|
+
seen = {}
|
|
80
|
+
@eval_hosts&.each { |h| seen[h.name || h.object_id] = h }
|
|
81
|
+
@eval_hosts = seen.values
|
|
82
|
+
|
|
83
|
+
@eval_hosts || []
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def eager_load_contract_dirs!
|
|
87
|
+
%w[app/contracts app/steps].each do |path|
|
|
88
|
+
full = ::Rails.root.join(path)
|
|
89
|
+
next unless full.exist?
|
|
90
|
+
|
|
91
|
+
::Rails.autoloaders.main.eager_load_dir(full.to_s)
|
|
92
|
+
rescue StandardError
|
|
93
|
+
# Zeitwerk not available or dir not managed — skip
|
|
94
|
+
nil
|
|
77
95
|
end
|
|
78
96
|
end
|
|
79
97
|
|
|
@@ -87,6 +105,7 @@ module RubyLLM
|
|
|
87
105
|
end
|
|
88
106
|
end
|
|
89
107
|
|
|
108
|
+
require_relative "contract/concerns/deep_freeze"
|
|
90
109
|
require_relative "contract/concerns/deep_symbolize"
|
|
91
110
|
require_relative "contract/concerns/eval_host"
|
|
92
111
|
require_relative "contract/concerns/trace_equality"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_llm-contract
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justyna
|
|
@@ -82,6 +82,7 @@ files:
|
|
|
82
82
|
- lib/ruby_llm/contract/adapters/response.rb
|
|
83
83
|
- lib/ruby_llm/contract/adapters/ruby_llm.rb
|
|
84
84
|
- lib/ruby_llm/contract/adapters/test.rb
|
|
85
|
+
- lib/ruby_llm/contract/concerns/deep_freeze.rb
|
|
85
86
|
- lib/ruby_llm/contract/concerns/deep_symbolize.rb
|
|
86
87
|
- lib/ruby_llm/contract/concerns/eval_host.rb
|
|
87
88
|
- lib/ruby_llm/contract/concerns/trace_equality.rb
|
|
@@ -97,6 +98,7 @@ files:
|
|
|
97
98
|
- lib/ruby_llm/contract/dsl.rb
|
|
98
99
|
- lib/ruby_llm/contract/errors.rb
|
|
99
100
|
- lib/ruby_llm/contract/eval.rb
|
|
101
|
+
- lib/ruby_llm/contract/eval/baseline_diff.rb
|
|
100
102
|
- lib/ruby_llm/contract/eval/case_result.rb
|
|
101
103
|
- lib/ruby_llm/contract/eval/contract_detail_builder.rb
|
|
102
104
|
- lib/ruby_llm/contract/eval/dataset.rb
|