boxcars 0.10.14 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efe685ae5dc0980e60450b7b5188be1e9a985f0dfb584554c8e7d1bc186e79bd
4
- data.tar.gz: 49bd24692b1f7cf64a5c2cf8018e7966cc74ea5de19bca4c4d5bb88f16085009
3
+ metadata.gz: 06c8b47287c93e2a1f56dbf8b282b41759017e89ce75b4da3b1549fc1fd91bc7
4
+ data.tar.gz: ee8353dceaf1ad652d056c452a89fb39a37f79973ba553204df0ddecc865dec3
5
5
  SHA512:
6
- metadata.gz: d0e324db1f31406286df7581f5ee94a86a528e534d0da7cdd0280c5ec12ee449c4b4c422532da4ff98902cc1761fa631a5d601a666e3498d2657c7b2ae104354
7
- data.tar.gz: 91517a270f913e32f22239d017f88e282a724036f7e0ba1f22d75fea6b8ef490b28291c81e3c4f2ba41054c3d86a28df6ed499231374b929e4967a9825954109
6
+ metadata.gz: 3d0cc047e675833cf40a0cee54e8021c049a6e0157218d76eea525d6d09180724e1390c384ebde247cea9fb7a95b3ee2f869bd2e60c82100992ae54ef12539ef
7
+ data.tar.gz: 0e7d67e1039632f0cada81fbdcb5a1a15f58885a0b579b57bf76340dcb28743834f7f7907355c64c91a0de1d417fbf6eba1bd776cf1c8f77a93335d15412802c
data/.rubocop.yml CHANGED
@@ -10,7 +10,7 @@ plugins:
10
10
 
11
11
 
12
12
  AllCops:
13
- TargetRubyVersion: 3.2
13
+ TargetRubyVersion: 3.3
14
14
  Exclude:
15
15
  - 'bin/{rails,rake}'
16
16
  - 'node_modules/**/*'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.4.8
1
+ 4.0.6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.0.0] - 2026-08-28
6
+
7
+ ### Added
8
+
9
+ - Added Ruby 4.0 to the supported CI test matrix and made Ruby 4.0.6 the default development runtime.
10
+ - Added explicit engine-factory routing for the Cerebras `gpt-oss-120b` and Together AI `Qwen/Qwen2.5-VL-72B-Instruct` model IDs.
11
+
12
+ ### Changed
13
+
14
+ - Raised the minimum supported Ruby version from 3.2 to 3.3, matching the current official OpenAI Ruby SDK.
15
+ - Updated the curated `sonnet` and `opus` aliases to Claude Sonnet 5 and Claude Opus 5.
16
+ - Claude Sonnet 5, Opus 5, and Fable 5 requests now omit unsupported `temperature`, `top_p`, and `top_k` parameters.
17
+
18
+ ### Removed
19
+
20
+ - Removed the deprecated model aliases `anthropic`, `groq`, `deepseek`, `mistral`, `online`, `huge`, `online_huge`, `sonar-huge`, `sonar_huge`, `sonar_pro`, `flash`, `gemini-flash`, `gemini-pro`, `cerebras`, and `qwen`.
21
+ - Removed the obsolete strict-mode configuration used to detect deprecated model aliases. The curated `sonnet`, `opus`, `sonar`, and `sonar-pro` aliases remain supported.
22
+
23
+ ### Maintenance
24
+
25
+ - Declared `logger` as a runtime dependency because Ruby 4 no longer bundles it as a default gem.
26
+ - Refreshed bundled dependencies for Ruby 3.3+ and Ruby 4 compatibility, including OpenAI, PostHog, RuboCop, SQLite, and WebMock, and updated the lockfile to Bundler 4.
27
+
5
28
  ## [0.10.14] - 2026-08-04
6
29
 
7
30
  ### Fixed
data/CLAUDE.md CHANGED
@@ -39,7 +39,7 @@ Orchestrator that runs a series of boxcars using an engine. Three implementation
39
39
  - **XMLTrain** (`lib/boxcars/train/xml_train.rb`) — XML-based structured outputs
40
40
 
41
41
  ### Engine Factory (`lib/boxcars/engines.rb`)
42
- `Boxcars::Engines.engine(model:)` creates the right engine from a model name or alias. Default model: `"gemini-2.5-flash"`. Curated aliases include `"sonnet"`, `"opus"`, `"sonar"`, `"sonar-pro"`. Many legacy aliases are deprecated (see `DEPRECATED_MODEL_ALIASES`).
42
+ `Boxcars::Engines.engine(model:)` creates the right engine from a model name or alias. Default model: `"gemini-2.5-flash"`. Curated aliases are `"sonnet"`, `"opus"`, `"sonar"`, and `"sonar-pro"`; legacy aliases were removed in v1.0.
43
43
 
44
44
  ### Other Key Components
45
45
  - **MCP** (`lib/boxcars/mcp/`) — Model Context Protocol integration for external tool servers
@@ -57,5 +57,5 @@ Orchestrator that runs a series of boxcars using an engine. Three implementation
57
57
 
58
58
  - Rubocop with `rubocop-rspec` and `rubocop-rake` plugins
59
59
  - Max line length: 130 (excluded for specs)
60
- - Target Ruby: 3.2+
60
+ - Target Ruby: 3.3+
61
61
  - Provider gems are optional — core has zero runtime dependencies; providers are loaded on demand via `OptionalDependency`
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- boxcars (0.10.14)
4
+ boxcars (1.0.0)
5
+ logger
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -30,7 +31,6 @@ GEM
30
31
  ast (2.4.3)
31
32
  base64 (0.3.0)
32
33
  bigdecimal (4.1.2)
33
- cgi (0.5.2)
34
34
  concurrent-ruby (1.3.8)
35
35
  connection_pool (3.0.2)
36
36
  crack (1.0.1)
@@ -57,7 +57,7 @@ GEM
57
57
  hnswlib (0.9.3)
58
58
  i18n (1.15.2)
59
59
  concurrent-ruby (~> 1.0)
60
- io-console (0.8.2)
60
+ io-console (0.9.2)
61
61
  irb (1.18.0)
62
62
  pp (>= 0.6.0)
63
63
  prism (>= 1.3.0)
@@ -89,10 +89,9 @@ GEM
89
89
  racc (~> 1.4)
90
90
  nokogiri (1.19.4-x86_64-linux-musl)
91
91
  racc (~> 1.4)
92
- openai (0.77.1)
93
- base64
94
- cgi
95
- connection_pool
92
+ openai (0.83.0)
93
+ connection_pool (>= 2.2.3)
94
+ logger
96
95
  parallel (2.1.0)
97
96
  parser (3.3.12.0)
98
97
  ast (~> 2.4.1)
@@ -105,7 +104,7 @@ GEM
105
104
  pg (1.6.3-x86_64-linux)
106
105
  pg (1.6.3-x86_64-linux-musl)
107
106
  pgvector (0.3.3)
108
- posthog-ruby (3.21.0)
107
+ posthog-ruby (3.23.5)
109
108
  concurrent-ruby (~> 1)
110
109
  pp (0.6.4)
111
110
  prettyprint
@@ -115,7 +114,7 @@ GEM
115
114
  racc (1.8.1)
116
115
  rainbow (3.1.1)
117
116
  rake (13.4.2)
118
- rbs (4.1.2)
117
+ rbs (4.2.0)
119
118
  logger
120
119
  prism (>= 1.6.0)
121
120
  tsort
@@ -125,7 +124,7 @@ GEM
125
124
  rbs (>= 4.0.0)
126
125
  tsort
127
126
  regexp_parser (2.12.0)
128
- reline (0.6.3)
127
+ reline (0.7.0)
129
128
  io-console (~> 0.5)
130
129
  rexml (3.4.4)
131
130
  rspec (3.13.2)
@@ -141,8 +140,8 @@ GEM
141
140
  diff-lcs (>= 1.2.0, < 2.0)
142
141
  rspec-support (~> 3.13.0)
143
142
  rspec-support (3.13.7)
144
- rubocop (1.89.0)
145
- json (~> 2.3)
143
+ rubocop (1.90.0)
144
+ json (>= 2.3)
146
145
  language_server-protocol (~> 3.17.0.2)
147
146
  lint_roller (~> 1.1.0)
148
147
  parallel (>= 1.10)
@@ -170,14 +169,14 @@ GEM
170
169
  securerandom (0.4.1)
171
170
  sequel (5.107.0)
172
171
  bigdecimal
173
- sqlite3 (2.9.5-aarch64-linux-gnu)
174
- sqlite3 (2.9.5-aarch64-linux-musl)
175
- sqlite3 (2.9.5-arm-linux-gnu)
176
- sqlite3 (2.9.5-arm-linux-musl)
177
- sqlite3 (2.9.5-arm64-darwin)
178
- sqlite3 (2.9.5-x86_64-darwin)
179
- sqlite3 (2.9.5-x86_64-linux-gnu)
180
- sqlite3 (2.9.5-x86_64-linux-musl)
172
+ sqlite3 (2.9.6-aarch64-linux-gnu)
173
+ sqlite3 (2.9.6-aarch64-linux-musl)
174
+ sqlite3 (2.9.6-arm-linux-gnu)
175
+ sqlite3 (2.9.6-arm-linux-musl)
176
+ sqlite3 (2.9.6-arm64-darwin)
177
+ sqlite3 (2.9.6-x86_64-darwin)
178
+ sqlite3 (2.9.6-x86_64-linux-gnu)
179
+ sqlite3 (2.9.6-x86_64-linux-musl)
181
180
  timeout (0.6.1)
182
181
  tsort (0.2.0)
183
182
  tzinfo (2.0.6)
@@ -187,7 +186,7 @@ GEM
187
186
  unicode-emoji (4.2.0)
188
187
  uri (1.1.1)
189
188
  vcr (6.4.0)
190
- webmock (3.26.2)
189
+ webmock (3.26.3)
191
190
  addressable (>= 2.8.0)
192
191
  crack (>= 0.3.2)
193
192
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -228,4 +227,4 @@ DEPENDENCIES
228
227
  webmock (~> 3.26.1)
229
228
 
230
229
  BUNDLED WITH
231
- 2.5.20
230
+ 4.0.16
data/README.md CHANGED
@@ -46,6 +46,8 @@ All of these concepts are in a module named Boxcars:
46
46
 
47
47
  ## Installation
48
48
 
49
+ Boxcars requires Ruby 3.3 or newer.
50
+
49
51
  Add this line to your application's Gemfile:
50
52
 
51
53
  ```ruby
data/UPGRADING.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Upgrading Boxcars (v0.9 -> v1.0)
2
2
 
3
- This guide covers the migration path for the modernization work added in v0.9 and the planned alias removals in v1.0.
3
+ This guide covers the migration path from Boxcars v0.9 and v0.10 to v1.0.
4
4
 
5
5
  ## Summary
6
6
 
@@ -11,10 +11,15 @@ v0.9 introduces:
11
11
  - JSON Schema support for `JSONEngineBoxcar`
12
12
  - Deprecated model alias warnings with optional strict mode
13
13
 
14
- v1.0 is expected to:
14
+ v1.0:
15
15
 
16
16
  - Remove deprecated model aliases
17
17
  - Prefer explicit model names (with a small curated alias set)
18
+ - Require Ruby 3.3 or newer, with Ruby 4 fully supported
19
+
20
+ ## Ruby 3.3 or Newer Is Required
21
+
22
+ Boxcars 1.0 drops Ruby 3.2 support and requires Ruby 3.3 or newer. Upgrade your Ruby runtime before installing Boxcars 1.0. Applications that must remain on Ruby 3.2 should stay on Boxcars 0.10.x and OpenAI Ruby SDK 0.75.x, the final compatible release line.
18
23
 
19
24
  ## SQL Boxcars Now Default to Read-Only (v0.10.x)
20
25
 
@@ -115,7 +120,7 @@ result.answer
115
120
 
116
121
  ## 1. Model Alias Migration (Do This First)
117
122
 
118
- Deprecated aliases still work in v0.9, but emit one-time warnings.
123
+ The aliases below emitted one-time warnings in v0.9 and v0.10 and are removed in v1.0. Using one now raises `Boxcars::ArgumentError` with an `Unknown model` message.
119
124
 
120
125
  ### Kept curated aliases (not deprecated)
121
126
 
@@ -124,6 +129,10 @@ Deprecated aliases still work in v0.9, but emit one-time warnings.
124
129
  - `sonnet`
125
130
  - `opus`
126
131
 
132
+ In v1.0, `sonnet` targets `claude-sonnet-5` and `opus` targets `claude-opus-5`. These Claude 5 models do not accept
133
+ custom `temperature`, `top_p`, or `top_k` values, so Boxcars removes those options before sending the request. Use an
134
+ explicit older Claude model ID if your application depends on custom sampling values.
135
+
127
136
  ### Replace deprecated aliases
128
137
 
129
138
  - `anthropic` -> `sonnet`
@@ -148,27 +157,14 @@ Prefer explicit model names in app code:
148
157
 
149
158
  ```ruby
150
159
  Boxcars::Engines.engine(model: "gpt-4o")
151
- Boxcars::Engines.engine(model: "claude-sonnet-4-0")
160
+ Boxcars::Engines.engine(model: "claude-sonnet-5")
152
161
  Boxcars::Engines.engine(model: "gemini-2.5-flash")
153
162
  Boxcars::Engines.engine(model: "sonar-pro")
154
163
  ```
155
164
 
156
- ## 2. Enable Strict Alias Mode in CI
157
-
158
- Use this to fail builds when deprecated aliases are used.
159
-
160
- ```ruby
161
- # config/initializers/boxcars.rb
162
- Boxcars.configure do |config|
163
- config.strict_deprecated_model_aliases = ENV["CI"] == "true"
164
- end
165
- ```
166
-
167
- Or enforce globally in tests:
165
+ ## 2. Verify Removed Aliases in CI
168
166
 
169
- ```ruby
170
- Boxcars::Engines.strict_deprecated_aliases = true
171
- ```
167
+ No strict-mode setting is needed in v1.0. Removed aliases fail during engine construction, so normal application tests catch any remaining uses.
172
168
 
173
169
  ## 3. Migrate ReAct/Text Trains to Native Tool Calling (Optional, Recommended)
174
170
 
@@ -260,7 +256,7 @@ boxcar = Boxcars::JSONEngineBoxcar.new(json_schema: schema, json_schema_strict:
260
256
  3. Migrate one workflow from `ZeroShot` to `ToolTrain`.
261
257
  4. Add MCP tools where they simplify app-specific integrations.
262
258
  5. Add JSON Schema to `JSONEngineBoxcar` uses that need reliable structure.
263
- 6. Upgrade to v1.0 after strict mode stays green.
259
+ 6. Upgrade to v1.0 after the application test suite passes with explicit models or curated aliases.
264
260
 
265
261
  ## 7. Known Ongoing Modernization Work
266
262
 
data/boxcars.gemspec CHANGED
@@ -12,9 +12,8 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "You simply set an OpenAI key, give a number of Boxcars to a Train, and magic ensues when you run it."
13
13
  spec.homepage = "https://github.com/BoxcarsAI/boxcars"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 3.2.0"
15
+ spec.required_ruby_version = ">= 3.3.0"
16
16
 
17
- spec.metadata["homepage_uri"] = spec.homepage
18
17
  spec.metadata["source_code_uri"] = spec.homepage
19
18
  spec.metadata["changelog_uri"] = "https://github.com/BoxcarsAI/boxcars/blob/main/CHANGELOG.md"
20
19
  spec.metadata["rubygems_mfa_required"] = "true"
@@ -31,6 +30,8 @@ Gem::Specification.new do |spec|
31
30
  spec.require_paths = ["lib"]
32
31
 
33
32
  # runtime dependencies
33
+ spec.add_dependency "logger"
34
+
34
35
  # Provider/tooling gems are optional and loaded on use.
35
36
 
36
37
  # For more information and examples about making a new gem, checkout our
@@ -93,35 +93,38 @@ perplexity_engine = Boxcars::Engines.engine(model: "sonar")
93
93
  #### Supported Model Aliases
94
94
 
95
95
  **OpenAI Models:**
96
- - Any OpenAI model ID from the [OpenAI pricing/models page](https://developers.openai.com/api/pricing) (for example `"gpt-5-mini"`, `"gpt-5"`, `"o1"`, `"o3"`) creates `Boxcars::Openai` engines
96
+ - Any OpenAI model ID from the [OpenAI pricing/models page](https://developers.openai.com/api/pricing) (for example `"gpt-5.6-sol"`, `"gpt-5.6-terra"`, `"gpt-5.6-luna"`, `"o1"`, or `"o3"`) creates `Boxcars::Openai` engines
97
97
 
98
98
  **Anthropic Models:**
99
- - `"anthropic"`, `"sonnet"` - Creates `Boxcars::Anthropic` with Claude Sonnet
100
- - `"opus"` - Creates `Boxcars::Anthropic` with Claude Opus
99
+ - `"sonnet"` - Creates `Boxcars::Anthropic` with `claude-sonnet-5`
100
+ - `"opus"` - Creates `Boxcars::Anthropic` with `claude-opus-5`
101
+ - `"claude-fable-5"` - Creates `Boxcars::Anthropic` with Claude Fable 5
101
102
  - `"claude-3-5-sonnet"`, etc. - Any model starting with "claude-"
102
103
 
104
+ Use the full model IDs for Sol, Terra, Luna, and Fable; their short names are not Boxcars aliases.
105
+
103
106
  **Groq Models:**
104
- - `"groq"` - Creates `Boxcars::Groq` with Llama 3.3 70B
105
- - `"deepseek"` - Creates `Boxcars::Groq` with DeepSeek R1
106
- - `"mistral"` - Creates `Boxcars::Groq` with Mistral
107
+ - `"llama-3.3-70b-versatile"` - Creates `Boxcars::Groq` with Llama 3.3 70B
107
108
  - Models starting with `"mistral-"`, `"meta-llama/"`, or `"deepseek-"`
108
109
 
109
110
  **Gemini Models:**
110
- - `"flash"`, `"gemini-flash"` - Creates `Boxcars::GeminiAi` with Gemini 2.5 Flash
111
- - `"gemini-pro"` - Creates `Boxcars::GeminiAi` with Gemini 2.5 Pro
112
111
  - Any model starting with `"gemini-"`
113
112
 
114
113
  **Perplexity Models:**
115
- - `"online"`, `"sonar"` - Creates `Boxcars::Perplexityai` with Sonar
116
- - `"sonar-pro"`, `"huge"` - Creates `Boxcars::Perplexityai` with Sonar Pro
114
+ - `"sonar"` - Creates `Boxcars::Perplexityai` with Sonar
115
+ - `"sonar-pro"` - Creates `Boxcars::Perplexityai` with Sonar Pro
117
116
  - Models containing `"-sonar-"`
118
117
 
118
+ **Cerebras Models:**
119
+ - `"gpt-oss-120b"` - Creates `Boxcars::Cerebras`
120
+
119
121
  **Together AI Models:**
120
122
  - `"together-model-name"` - Creates `Boxcars::Together` (strips "together-" prefix)
123
+ - `"Qwen/Qwen2.5-VL-72B-Instruct"` - Creates `Boxcars::Together`
121
124
 
122
- #### Alias Deprecations (Migration to v1.0)
125
+ #### Aliases Removed in v1.0
123
126
 
124
- Some older aliases are still supported but emit a one-time deprecation warning (per process):
127
+ The following aliases were deprecated in v0.9 and v0.10 and are removed in v1.0:
125
128
 
126
129
  - `"anthropic"` (use `"sonnet"`)
127
130
  - `"groq"` (use an explicit model like `"llama-3.3-70b-versatile"`)
@@ -130,26 +133,7 @@ Some older aliases are still supported but emit a one-time deprecation warning (
130
133
  - `"flash"` / `"gemini-flash"` / `"gemini-pro"` (use explicit Gemini models)
131
134
  - `"deepseek"`, `"mistral"`, `"cerebras"`, `"qwen"` (use explicit model names)
132
135
 
133
- `"sonar"` and `"sonar-pro"` remain supported curated aliases.
134
-
135
- Enable strict mode to raise an error instead of warning on deprecated aliases:
136
-
137
- ```ruby
138
- Boxcars.configure do |config|
139
- config.strict_deprecated_model_aliases = true
140
- end
141
-
142
- # or:
143
- Boxcars::Engines.strict_deprecated_aliases = true
144
- ```
145
-
146
- Temporarily silence deprecation warnings during migration:
147
-
148
- ```ruby
149
- Boxcars.configure do |config|
150
- config.emit_deprecation_warnings = false
151
- end
152
- ```
136
+ `"sonnet"`, `"opus"`, `"sonar"`, and `"sonar-pro"` remain supported curated aliases. See [UPGRADING.md](../UPGRADING.md) for the complete replacement table.
153
137
 
154
138
  #### Passing Additional Parameters
155
139
 
@@ -3,7 +3,7 @@
3
3
  # Boxcars is a framework for running a series of tools to get an answer to a question.
4
4
  module Boxcars
5
5
  # A Boxcar that interprets a prompt and executes Active Record code to get answers.
6
- # rubocop:disable Metrics/ClassLength
6
+ # rubocop:disable-next Metrics/ClassLength
7
7
  class ActiveRecord < EngineBoxcar
8
8
  # Default description for this boxcar.
9
9
  ARDESC = "useful for when you need to query a database for an application named %<name>s."
@@ -172,9 +172,8 @@ module Boxcars
172
172
  new_code = new_code.gsub(/\b(puts|print)\b/, '')
173
173
 
174
174
  proc do
175
- # rubocop:disable Security/Eval
175
+ # rubocop:disable-next Security/Eval
176
176
  eval(new_code, binding)
177
- # rubocop:enable Security/Eval
178
177
  end.call
179
178
  end
180
179
 
@@ -288,5 +287,4 @@ module Boxcars
288
287
  output_variables: [:answer])
289
288
  end
290
289
  end
291
- # rubocop:enable Metrics/ClassLength
292
290
  end
@@ -15,8 +15,13 @@ module Boxcars
15
15
  max_tokens: 4096,
16
16
  temperature: 0.1
17
17
  }.freeze
18
- OPUS_4_7_MODEL_PREFIX = "claude-opus-4-7"
19
- OPUS_4_7_UNSUPPORTED_SAMPLING_PARAMS = %i[temperature top_p top_k].freeze
18
+ MODELS_WITHOUT_SAMPLING_PARAMS = %w[
19
+ claude-opus-4-7
20
+ claude-sonnet-5
21
+ claude-opus-5
22
+ claude-fable-5
23
+ ].freeze
24
+ UNSUPPORTED_SAMPLING_PARAMS = %i[temperature top_p top_k].freeze
20
25
 
21
26
  # The default name of the engine.
22
27
  DEFAULT_NAME = "Anthropic engine"
@@ -29,7 +34,7 @@ module Boxcars
29
34
  raise ArgumentError, "unknown keyword: :prompts" if kwargs.key?(:prompts)
30
35
 
31
36
  user_id = kwargs.delete(:user_id)
32
- @llm_params = remove_opus_4_7_unsupported_sampling_params(DEFAULT_PARAMS.merge(kwargs))
37
+ @llm_params = remove_unsupported_sampling_params(DEFAULT_PARAMS.merge(kwargs))
33
38
  super(description:, name:, batch_size: 20, user_id:)
34
39
  end
35
40
 
@@ -85,7 +90,7 @@ module Boxcars
85
90
  params[:stop_sequences] = params.delete(:stop) if params.key?(:stop)
86
91
  params[:system] = params[:messages].shift[:content] if params.dig(:messages, 0, :role) == :system
87
92
  params[:messages].pop if params[:messages].last[:content].nil? || params[:messages].last[:content].strip.empty?
88
- remove_opus_4_7_unsupported_sampling_params(params)
93
+ remove_unsupported_sampling_params(params)
89
94
  combine_assistant(params)
90
95
  end
91
96
 
@@ -114,18 +119,21 @@ module Boxcars
114
119
 
115
120
  private
116
121
 
117
- def remove_opus_4_7_unsupported_sampling_params(params)
118
- return params unless opus_4_7_model?(params[:model] || params["model"])
122
+ def remove_unsupported_sampling_params(params)
123
+ return params unless sampling_params_unsupported?(params[:model] || params["model"])
119
124
 
120
- OPUS_4_7_UNSUPPORTED_SAMPLING_PARAMS.each do |key|
125
+ UNSUPPORTED_SAMPLING_PARAMS.each do |key|
121
126
  params.delete(key)
122
127
  params.delete(key.to_s)
123
128
  end
124
129
  params
125
130
  end
126
131
 
127
- def opus_4_7_model?(model)
128
- model.to_s.start_with?(OPUS_4_7_MODEL_PREFIX)
132
+ def sampling_params_unsupported?(model)
133
+ model_name = model.to_s
134
+ MODELS_WITHOUT_SAMPLING_PARAMS.any? do |base_model|
135
+ model_name == base_model || model_name.start_with?("#{base_model}-")
136
+ end
129
137
  end
130
138
 
131
139
  # Process the raw response from Anthropic API
@@ -356,7 +356,7 @@ module Boxcars
356
356
  when "output_text"
357
357
  content = i["content"]
358
358
  if content.is_a?(Array)
359
- # rubocop:disable Metrics/BlockNesting
359
+ # rubocop:disable-next Metrics/BlockNesting
360
360
  texts << content.filter_map { |c|
361
361
  if c.is_a?(Hash)
362
362
  if c["text"].is_a?(String)
@@ -366,7 +366,6 @@ module Boxcars
366
366
  end
367
367
  end
368
368
  }.join
369
- # rubocop:enable Metrics/BlockNesting
370
369
  elsif content.is_a?(String)
371
370
  texts << content
372
371
  end
@@ -26,7 +26,7 @@ module Boxcars
26
26
  super(description:, name:, batch_size:, user_id:)
27
27
  end
28
28
 
29
- # rubocop:disable Metrics/MethodLength
29
+ # rubocop:disable-next Metrics/MethodLength
30
30
  def client(prompt:, inputs: {}, perplexity_api_key: nil, **kwargs)
31
31
  start_time = Time.now
32
32
  response_data = { response_obj: nil, parsed_json: nil, success: false, error: nil, status_code: nil }
@@ -108,7 +108,6 @@ module Boxcars
108
108
 
109
109
  perplexity_handle_call_outcome(response_data:)
110
110
  end
111
- # rubocop:enable Metrics/MethodLength
112
111
 
113
112
  def default_params
114
113
  @perplexity_params
@@ -6,7 +6,7 @@ require 'securerandom'
6
6
  module Boxcars
7
7
  # Unified observability module that provides PostHog-centric tracking for all engines
8
8
  # Uses standardized $ai_* properties as defined by PostHog's LLM observability spec
9
- # rubocop:disable Metrics/ModuleLength
9
+ # rubocop:disable-next Metrics/ModuleLength
10
10
  module UnifiedObservability
11
11
  private
12
12
 
@@ -486,5 +486,4 @@ module Boxcars
486
486
  (response_data[:response_obj].respond_to?(:status) ? response_data[:response_obj].status : nil)
487
487
  end
488
488
  end
489
- # rubocop:enable Metrics/ModuleLength
490
489
  end
@@ -6,33 +6,12 @@ module Boxcars
6
6
  class Engines
7
7
  VALID_ANSWER_REMOVE_IN = "3.0"
8
8
  DEFAULT_MODEL = "gemini-2.5-flash"
9
- DEPRECATED_MODEL_ALIASES = {
10
- # Generic provider aliases are convenient but ambiguous and make pruning harder.
11
- "anthropic" => { replacement: "sonnet", remove_in: "3.0", reason: "generic provider alias" },
12
- "groq" => { replacement: "llama-3.3-70b-versatile", remove_in: "3.0", reason: "generic provider alias" },
13
- "deepseek" => { replacement: "deepseek-r1-distill-llama-70b", remove_in: "3.0",
14
- reason: "provider-specific shortcut alias" },
15
- "mistral" => { replacement: "mistral-saba-24b", remove_in: "3.0", reason: "provider-specific shortcut alias" },
16
- "online" => { replacement: "sonar", remove_in: "3.0", reason: "ambiguous alias" },
17
- "huge" => { replacement: "sonar-pro", remove_in: "3.0", reason: "ambiguous alias" },
18
- "online_huge" => { replacement: "sonar-pro", remove_in: "3.0", reason: "ambiguous alias" },
19
- "sonar-huge" => { replacement: "sonar-pro", remove_in: "3.0", reason: "legacy alias spelling" },
20
- "sonar_huge" => { replacement: "sonar-pro", remove_in: "3.0", reason: "legacy alias spelling" },
21
- "sonar_pro" => { replacement: "sonar-pro", remove_in: "3.0", reason: "legacy alias spelling" },
22
- "flash" => { replacement: "gemini-2.5-flash", remove_in: "3.0", reason: "generic alias" },
23
- "gemini-flash" => { replacement: "gemini-2.5-flash", remove_in: "3.0", reason: "generic alias" },
24
- "gemini-pro" => { replacement: "gemini-2.5-pro", remove_in: "3.0", reason: "generic alias" },
25
- "cerebras" => { replacement: "gpt-oss-120b", remove_in: "3.0", reason: "generic provider alias" },
26
- "qwen" => { replacement: "Qwen/Qwen2.5-VL-72B-Instruct", remove_in: "3.0", reason: "provider-specific shortcut alias" }
27
- }.freeze
28
9
 
29
10
  @emit_deprecation_warnings = true
30
- @strict_deprecated_aliases = false
31
- @warned_aliases = {}
32
11
  @warned_valid_answer = false
33
12
 
34
13
  class << self
35
- attr_accessor :emit_deprecation_warnings, :strict_deprecated_aliases
14
+ attr_accessor :emit_deprecation_warnings
36
15
  end
37
16
 
38
17
  # Create an engine instance based on the model name
@@ -42,57 +21,40 @@ module Boxcars
42
21
  def self.engine(model: nil, **kw_args)
43
22
  kw_args = Boxcars.configuration.default_model_options.merge(kw_args) if model.nil?
44
23
  model ||= Boxcars.configuration.default_model || DEFAULT_MODEL
45
- emit_alias_deprecation_warning(model)
46
24
  Boxcars.logger&.info { "running api with #{model}" }
47
25
 
48
26
  case model.to_s
27
+ when "gpt-oss-120b"
28
+ Boxcars::Cerebras.new(model:, **kw_args)
49
29
  when /^(gpt-|o\d($|-))/
50
30
  Boxcars::Openai.new(model:, **kw_args)
51
- when "anthropic", "sonnet"
52
- Boxcars::Anthropic.new(model: "claude-sonnet-4-0", **kw_args)
53
- when "opus", "claude-opus-4-0"
54
- Boxcars::Anthropic.new(model: "claude-opus-4-0", **kw_args)
31
+ when "sonnet"
32
+ Boxcars::Anthropic.new(model: "claude-sonnet-5", **kw_args)
33
+ when "opus"
34
+ Boxcars::Anthropic.new(model: "claude-opus-5", **kw_args)
55
35
  when /claude-/
56
36
  Boxcars::Anthropic.new(model:, **kw_args)
57
- when "groq", "llama-3.3-70b-versatile"
37
+ when "llama-3.3-70b-versatile"
58
38
  Boxcars::Groq.new(model: "llama-3.3-70b-versatile", **kw_args)
59
- when "deepseek"
60
- Boxcars::Groq.new(model: "deepseek-r1-distill-llama-70b", **kw_args)
61
- when "mistral"
62
- Boxcars::Groq.new(model: "mistral-saba-24b", **kw_args)
63
39
  when /^mistral-/, %r{^meta-llama/}, /^deepseek-/
64
40
  Boxcars::Groq.new(model:, **kw_args)
65
- when "online", "sonar"
41
+ when "sonar"
66
42
  Boxcars::Perplexityai.new(model: "sonar", **kw_args)
67
- when "huge", "online_huge", "sonar-huge", "sonar_huge", "sonar-pro", "sonar_pro"
43
+ when "sonar-pro"
68
44
  Boxcars::Perplexityai.new(model: "sonar-pro", **kw_args)
69
- when "flash", "gemini-flash"
70
- Boxcars::GeminiAi.new(model: "gemini-2.5-flash", **kw_args)
71
- when "gemini-pro"
72
- Boxcars::GeminiAi.new(model: "gemini-2.5-pro", **kw_args)
73
- when /gemini-/
45
+ when /^gemini-(?!flash$|pro$)/
74
46
  Boxcars::GeminiAi.new(model:, **kw_args)
75
47
  when /-sonar-/
76
48
  Boxcars::Perplexityai.new(model:, **kw_args)
77
49
  when /^together-/
78
50
  Boxcars::Together.new(model: model[9..-1], **kw_args)
79
- when "cerebras"
80
- Boxcars::Cerebras.new(model: "gpt-oss-120b", **kw_args)
81
- when "qwen"
82
- Boxcars::Together.new(model: "Qwen/Qwen2.5-VL-72B-Instruct", **kw_args)
51
+ when "Qwen/Qwen2.5-VL-72B-Instruct"
52
+ Boxcars::Together.new(model:, **kw_args)
83
53
  else
84
54
  raise Boxcars::ArgumentError, "Unknown model: #{model}"
85
55
  end
86
56
  end
87
57
 
88
- def self.deprecated_alias_info(model)
89
- DEPRECATED_MODEL_ALIASES[model.to_s]
90
- end
91
-
92
- def self.deprecated_alias?(model)
93
- !deprecated_alias_info(model).nil?
94
- end
95
-
96
58
  # Create an engine instance optimized for JSON responses
97
59
  # @param model [String] The model name or alias
98
60
  # @param kw_args [Hash] Additional arguments to pass to the engine
@@ -101,7 +63,7 @@ module Boxcars
101
63
  default_options = { temperature: 0.1 }
102
64
  effective_model = model || Boxcars.configuration.default_model || DEFAULT_MODEL
103
65
  name = effective_model.to_s
104
- blocked = name.start_with?("gpt-5", "llama") || name.match?(/sonnet|opus|haiku|sonar/)
66
+ blocked = name.start_with?("gpt-5", "llama", "claude-") || name.match?(/sonnet|opus|haiku|sonar/)
105
67
  default_options[:response_format] = { type: "json_object" } unless blocked
106
68
  options = default_options.merge(kw_args)
107
69
  engine(model:, **options)
@@ -122,40 +84,10 @@ module Boxcars
122
84
  Boxcars::Result.valid_conduct_payload?(answer)
123
85
  end
124
86
 
125
- def self.emit_alias_deprecation_warning(model)
126
- model_name = model.to_s
127
- info = deprecated_alias_info(model_name)
128
- return unless info
129
-
130
- replacement = info[:replacement]
131
- remove_in = info[:remove_in]
132
- reason = info[:reason]
133
- message = "Deprecated model alias #{model_name.inspect} (#{reason}); use #{replacement.inspect} instead"
134
- message += " (planned removal in v#{remove_in})" if remove_in
135
-
136
- raise Boxcars::ArgumentError, "#{message}. Set an explicit model name." if strict_deprecated_aliases_enabled?
137
-
138
- return unless deprecation_warnings_enabled?
139
- return if @warned_aliases[model_name]
140
-
141
- if Boxcars.logger
142
- Boxcars.logger.warn(message)
143
- else
144
- warn(message)
145
- end
146
-
147
- @warned_aliases[model_name] = true
148
- end
149
-
150
87
  def self.reset_deprecation_warnings!
151
- @warned_aliases = {}
152
88
  @warned_valid_answer = false
153
89
  end
154
90
 
155
- def self.strict_deprecated_aliases_enabled?
156
- strict_deprecated_aliases || Boxcars.configuration.strict_deprecated_model_aliases
157
- end
158
-
159
91
  def self.deprecation_warnings_enabled?
160
92
  emit_deprecation_warnings && Boxcars.configuration.emit_deprecation_warnings
161
93
  end
@@ -19,11 +19,10 @@ module Boxcars
19
19
  # compute the prompt parameters with input substitutions (used for chatGPT)
20
20
  # @param inputs [Hash] The inputs to use for the prompt.
21
21
  # @return [Hash] The formatted prompt { messages: ...}
22
- # rubocop:disable Lint/UnusedMethodArgument
22
+ # rubocop:disable-next Lint/UnusedMethodArgument
23
23
  def as_prompt(inputs: nil, prefixes: nil, show_roles: nil)
24
24
  { prompt: format(inputs) }
25
25
  end
26
- # rubocop:enable Lint/UnusedMethodArgument
27
26
 
28
27
  # compute the prompt parameters with input substitutions
29
28
  # @param inputs [Hash] The inputs to use for the prompt.
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Boxcars
4
4
  # The current version of the gem.
5
- VERSION = "0.10.14"
5
+ VERSION = "1.0.0"
6
6
  end
@@ -32,9 +32,8 @@ module Boxcars
32
32
  doc = Nokogiri::XML.parse(xml)
33
33
  if doc.errors.any?
34
34
  Boxcars.debug("XML: #{xml}", :yellow)
35
- # rubocop:disable Lint/Debugger
35
+ # rubocop:disable-next Lint/Debugger
36
36
  debugger if ENV.fetch("DEBUG_XML", false)
37
- # rubocop:enable Lint/Debugger
38
37
  raise XmlError, "XML is not valid: #{doc.errors.map { |e| "#{e.line}:#{e.column} #{e.message}" }}"
39
38
  end
40
39
  XNode.new(doc.root)
@@ -53,9 +52,8 @@ module Boxcars
53
52
  end
54
53
 
55
54
  def xtext(path)
56
- # rubocop:disable Style/SafeNavigationChainLength
55
+ # rubocop:disable-next Style/SafeNavigationChainLength
57
56
  rv = xpath(path)&.text&.gsub(/[[:space:]]+/, " ")&.strip
58
- # rubocop:enable Style/SafeNavigationChainLength
59
57
  return nil if rv.empty?
60
58
 
61
59
  rv
data/lib/boxcars.rb CHANGED
@@ -29,7 +29,7 @@ module Boxcars
29
29
  class Configuration
30
30
  attr_writer :openai_access_token, :serpapi_api_key, :groq_api_key, :cerebras_api_key, :perplexity_api_key
31
31
  attr_accessor :organization_id, :logger, :log_prompts, :log_generated, :default_train, :default_engine, :default_model,
32
- :default_model_options, :observability_backend, :strict_deprecated_model_aliases
32
+ :default_model_options, :observability_backend
33
33
 
34
34
  def initialize
35
35
  @organization_id = nil
@@ -37,7 +37,6 @@ module Boxcars
37
37
  @log_prompts = ENV.fetch("LOG_PROMPTS", false)
38
38
  @log_generated = ENV.fetch("LOG_GEN", false)
39
39
  @default_model_options = {}
40
- @strict_deprecated_model_aliases = false
41
40
  self.emit_deprecation_warnings = true
42
41
  self.openai_official_require_native = ENV.fetch("OPENAI_OFFICIAL_REQUIRE_NATIVE", false)
43
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boxcars
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.14
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francis Sullivan
@@ -9,7 +9,21 @@ authors:
9
9
  bindir: exe
10
10
  cert_chain: []
11
11
  date: 1980-01-02 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logger
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: You simply set an OpenAI key, give a number of Boxcars to a Train, and
14
28
  magic ensues when you run it.
15
29
  email:
@@ -131,7 +145,6 @@ homepage: https://github.com/BoxcarsAI/boxcars
131
145
  licenses:
132
146
  - MIT
133
147
  metadata:
134
- homepage_uri: https://github.com/BoxcarsAI/boxcars
135
148
  source_code_uri: https://github.com/BoxcarsAI/boxcars
136
149
  changelog_uri: https://github.com/BoxcarsAI/boxcars/blob/main/CHANGELOG.md
137
150
  rubygems_mfa_required: 'true'
@@ -142,14 +155,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
155
  requirements:
143
156
  - - ">="
144
157
  - !ruby/object:Gem::Version
145
- version: 3.2.0
158
+ version: 3.3.0
146
159
  required_rubygems_version: !ruby/object:Gem::Requirement
147
160
  requirements:
148
161
  - - ">="
149
162
  - !ruby/object:Gem::Version
150
163
  version: '0'
151
164
  requirements: []
152
- rubygems_version: 3.6.9
165
+ rubygems_version: 4.0.16
153
166
  specification_version: 4
154
167
  summary: Boxcars is a gem that enables you to create new systems with AI composability.
155
168
  Inspired by python langchain.