lex-llm-openai 0.3.7 → 0.3.9

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: f49ee94d59da872cc2bb8095bbe619329caecf38f178f1b4c183c626f1f8168c
4
- data.tar.gz: 674527b56d8bb6c72a0052bdad2254356e635926b37a1810bea56563f94418be
3
+ metadata.gz: 808223596350fde35cbbf0145a411842ce1c0a3009d431edd354ce500732666c
4
+ data.tar.gz: 9ed2580c07f4d4b1c35f9b90e8108b4ddbd9f74fa032998447b3639dda67e4db
5
5
  SHA512:
6
- metadata.gz: 7dd8317307365087f1279f25f3c263d5dc57dc7c73487f9073d6c77d8a542f335aaf3ed2a4b176f9aee9a1ec59bd5f6269a2cf27845dff9cb73dd8ddbb898833
7
- data.tar.gz: 88c350e3870a694eabde6c04580191bc11dcc0f48171df3d37c31f91b8b0c97800a411d78f65d0856304e7710b5420f83ee66514c230ba3a22f75f9afe0b062b
6
+ metadata.gz: a07fffb4a8a5652e3b14303102bc2811915efc374b32369f50e1d39a6397d44a8a2b7822aebedd300af37cecb1d447cbf3b517fdf8502138077de149c9e9e9ea
7
+ data.tar.gz: 51f75db914319c8c086d8ca63a0127b6ed79d21ee92dd1a3c25c45bc9082ba0b1fde55792f8e6040e20c247baad09147634b079d953606e3a8031063422ad7f2
data/.rubocop.yml CHANGED
@@ -14,6 +14,8 @@ Metrics/BlockLength:
14
14
  - spec/**/*
15
15
  Metrics/ClassLength:
16
16
  Max: 200
17
+ Metrics/ModuleLength:
18
+ Max: 110
17
19
  Metrics/MethodLength:
18
20
  Enabled: false
19
21
  RSpec/ExampleLength:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.9 - 2026-05-13
4
+
5
+ - Change `default_model` from `gpt-4o` to `gpt-5.5` in provider default settings and instance discovery fallback.
6
+ - Inject `default_model` into all discovered provider instances so every instance has an explicit model default.
7
+ - Add `context_window` to all `CAPABILITY_MAP` entries (gpt-4o=128K, gpt-4.1/gpt-5=1M, o3/o4/o1=200K, text-embedding=8K).
8
+ - Override `fetch_model_detail` to return `context_window` from the capability map instead of issuing a live API call.
9
+ - Use `model_detail` in `build_model_infos` to populate `context_length` from the cached capability map entry.
10
+
11
+ ## 0.3.8 - 2026-05-13
12
+
13
+ - Route OpenAI fleet runner and actor diagnostics through `Legion::Logging::Helper` with debug-level request and enablement context.
14
+ - Report optional actor subscription load failures through `handle_exception` instead of raw warning output.
15
+ - Move routine OpenAI model discovery telemetry to debug-level logging while keeping failure handling structured.
16
+
3
17
  ## 0.3.7 - 2026-05-08
4
18
 
5
19
  - Accept keyword arguments in `list_models` to match the base provider contract called by `discover_offerings`.
@@ -1,18 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- require 'legion/extensions/actors/subscription'
5
- rescue LoadError => e
6
- warn(e.message) if $VERBOSE
3
+ require 'legion/extensions/llm/openai'
4
+ require 'legion/extensions/llm/fleet/provider_responder'
5
+
6
+ unless defined?(Legion::Extensions::Actors::Subscription)
7
+ begin
8
+ require 'legion/extensions/actors/subscription'
9
+ rescue LoadError => e
10
+ Legion::Extensions::Llm::Openai.handle_exception(
11
+ e,
12
+ level: :warn,
13
+ handled: true,
14
+ operation: 'openai.fleet_worker.load_subscription'
15
+ )
16
+ end
7
17
  end
8
18
 
9
19
  unless defined?(Legion::Extensions::Actors::Subscription)
10
20
  raise LoadError, 'LegionIO actor runtime is required for OpenAI fleet worker'
11
21
  end
12
22
 
13
- require 'legion/extensions/llm/openai'
14
- require 'legion/extensions/llm/fleet/provider_responder'
15
-
16
23
  module Legion
17
24
  module Extensions
18
25
  module Llm
@@ -20,6 +27,8 @@ module Legion
20
27
  module Actor
21
28
  # Subscription actor for OpenAI fleet request consumption.
22
29
  class FleetWorker < Legion::Extensions::Actors::Subscription
30
+ include Legion::Logging::Helper
31
+
23
32
  def runner_class
24
33
  'Legion::Extensions::Llm::Openai::Runners::FleetWorker'
25
34
  end
@@ -33,7 +42,13 @@ module Legion
33
42
  end
34
43
 
35
44
  def enabled?
36
- Legion::Extensions::Llm::Fleet::ProviderResponder.enabled_for?(Openai.discover_instances)
45
+ instances = Openai.discover_instances
46
+ enabled = Legion::Extensions::Llm::Fleet::ProviderResponder.enabled_for?(instances)
47
+ log.debug { "OpenAI fleet worker enablement: enabled=#{enabled}, instance_count=#{instances.size}" }
48
+ enabled
49
+ rescue StandardError => e
50
+ handle_exception(e, level: :warn, handled: true, operation: 'openai.fleet_worker.enabled')
51
+ false
37
52
  end
38
53
  end
39
54
  end
@@ -19,42 +19,50 @@ module Legion
19
19
  'gpt-4o' => {
20
20
  capabilities: %i[completion streaming function_calling vision structured_output],
21
21
  modalities_input: %w[text image audio],
22
- modalities_output: %w[text]
22
+ modalities_output: %w[text],
23
+ context_window: 128_000
23
24
  },
24
25
  'gpt-4.1' => {
25
26
  capabilities: %i[completion streaming function_calling vision structured_output],
26
27
  modalities_input: %w[text image],
27
- modalities_output: %w[text]
28
+ modalities_output: %w[text],
29
+ context_window: 1_047_576
28
30
  },
29
31
  'gpt-4' => {
30
32
  capabilities: %i[completion streaming function_calling vision],
31
33
  modalities_input: %w[text image],
32
- modalities_output: %w[text]
34
+ modalities_output: %w[text],
35
+ context_window: 128_000
33
36
  },
34
37
  'gpt-5' => {
35
38
  capabilities: %i[completion streaming function_calling vision structured_output reasoning],
36
39
  modalities_input: %w[text image],
37
- modalities_output: %w[text]
40
+ modalities_output: %w[text],
41
+ context_window: 1_047_576
38
42
  },
39
43
  'o4' => {
40
44
  capabilities: %i[completion streaming function_calling vision reasoning],
41
45
  modalities_input: %w[text image],
42
- modalities_output: %w[text]
46
+ modalities_output: %w[text],
47
+ context_window: 200_000
43
48
  },
44
49
  'o3' => {
45
50
  capabilities: %i[completion streaming function_calling vision reasoning],
46
51
  modalities_input: %w[text image],
47
- modalities_output: %w[text]
52
+ modalities_output: %w[text],
53
+ context_window: 200_000
48
54
  },
49
55
  'o1' => {
50
56
  capabilities: %i[completion streaming function_calling vision reasoning],
51
57
  modalities_input: %w[text image],
52
- modalities_output: %w[text]
58
+ modalities_output: %w[text],
59
+ context_window: 200_000
53
60
  },
54
61
  'text-embedding-' => {
55
62
  capabilities: %i[embedding],
56
63
  modalities_input: %w[text],
57
- modalities_output: %w[embeddings]
64
+ modalities_output: %w[embeddings],
65
+ context_window: 8_191
58
66
  },
59
67
  'omni-moderation' => {
60
68
  capabilities: %i[moderation],
@@ -172,7 +180,7 @@ module Legion
172
180
  def images_url(with: nil, mask: nil) = super
173
181
 
174
182
  def retrieve_model(model)
175
- log.info("Retrieving model: #{model}")
183
+ log.debug { "Retrieving OpenAI model: #{model}" }
176
184
  connection.get("#{models_url}/#{model}").body
177
185
  rescue StandardError => e
178
186
  handle_exception(e, level: :error, handled: true,
@@ -181,10 +189,10 @@ module Legion
181
189
  end
182
190
 
183
191
  def list_models(**)
184
- log.info('Listing OpenAI models')
192
+ log.debug('Listing OpenAI models')
185
193
  raw = connection.get(models_url)
186
194
  models = build_model_infos(raw.body)
187
- log.info("Discovered #{models.size} OpenAI models")
195
+ log.debug { "Discovered #{models.size} OpenAI models; publishing registry availability" }
188
196
  self.class.registry_publisher.publish_models_async(models, readiness: readiness(live: false))
189
197
  models
190
198
  rescue StandardError => e
@@ -199,12 +207,15 @@ module Legion
199
207
  body.fetch('data', []).map do |raw_model|
200
208
  id = raw_model.fetch('id')
201
209
  cap_entry = capability_entry_for(id)
210
+ detail = model_detail(id)
211
+ ctx = detail&.dig(:context_window) || cap_entry[:context_window]
202
212
 
203
213
  Legion::Extensions::Llm::Model::Info.new(
204
214
  id: id,
205
215
  name: id,
206
216
  provider: :openai,
207
217
  capabilities: cap_entry[:capabilities],
218
+ context_length: ctx,
208
219
  modalities_input: cap_entry[:modalities_input],
209
220
  modalities_output: cap_entry[:modalities_output],
210
221
  metadata: {
@@ -220,7 +231,6 @@ module Legion
220
231
  return entry if model_id.start_with?(prefix)
221
232
  end
222
233
 
223
- # Fallback for unknown models: assume chat-capable
224
234
  {
225
235
  capabilities: %i[completion streaming],
226
236
  modalities_input: %w[text],
@@ -228,6 +238,12 @@ module Legion
228
238
  }
229
239
  end
230
240
 
241
+ def fetch_model_detail(model_name)
242
+ entry = capability_entry_for(model_name)
243
+ ctx = entry[:context_window]
244
+ ctx ? { context_window: ctx } : nil
245
+ end
246
+
231
247
  def model_created_at(value)
232
248
  value.is_a?(Numeric) ? Time.at(value).utc : value
233
249
  end
@@ -10,9 +10,16 @@ module Legion
10
10
  module Runners
11
11
  # Runner entrypoint for OpenAI fleet request execution.
12
12
  module FleetWorker
13
+ extend Legion::Logging::Helper
14
+
13
15
  module_function
14
16
 
15
17
  def handle_fleet_request(payload, delivery: nil, properties: nil)
18
+ log.debug do
19
+ "Handling OpenAI fleet request: request_id=#{payload_value(payload, :request_id) || 'unknown'}, " \
20
+ "provider_instance=#{payload_value(payload, :provider_instance) || 'default'}"
21
+ end
22
+
16
23
  Legion::Extensions::Llm::Fleet::ProviderResponder.call(
17
24
  payload: payload,
18
25
  provider_family: Openai::PROVIDER_FAMILY,
@@ -21,6 +28,15 @@ module Legion
21
28
  delivery: delivery,
22
29
  properties: properties
23
30
  )
31
+ rescue StandardError => e
32
+ handle_exception(e, level: :error, handled: true, operation: 'openai.fleet_worker.handle_request')
33
+ raise
34
+ end
35
+
36
+ def payload_value(payload, key)
37
+ return unless payload.respond_to?(:[])
38
+
39
+ payload[key] || payload[key.to_s]
24
40
  end
25
41
  end
26
42
  end
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Openai
7
- VERSION = '0.3.7'
7
+ VERSION = '0.3.9'
8
8
  end
9
9
  end
10
10
  end
@@ -20,7 +20,7 @@ module Legion
20
20
  family: PROVIDER_FAMILY,
21
21
  instance: {
22
22
  endpoint: 'https://api.openai.com',
23
- default_model: 'gpt-4o',
23
+ default_model: 'gpt-5.5',
24
24
  tier: :frontier,
25
25
  transport: :http,
26
26
  credentials: {
@@ -53,6 +53,7 @@ module Legion
53
53
  end
54
54
 
55
55
  def self.discover_instances # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
56
+ log.debug('Discovering OpenAI provider instances')
56
57
  candidates = {}
57
58
 
58
59
  # 1. OPENAI_API_KEY environment variable
@@ -100,8 +101,15 @@ module Legion
100
101
  candidates[name.to_sym] = normalized.merge(tier: :frontier)
101
102
  end
102
103
 
103
- # 8. Dedup
104
- CredentialSources.dedup_credentials(candidates).transform_values { |config| sanitize_instance_config(config) }
104
+ # 8. Dedup + inject default_model
105
+ discovered = CredentialSources.dedup_credentials(candidates).transform_values do |config|
106
+ sanitized = sanitize_instance_config(config)
107
+ sanitized[:default_model] ||= 'gpt-5.5'
108
+ sanitized
109
+ end
110
+ instance_names = discovered.keys.sort_by(&:to_s).join(', ')
111
+ log.debug { "Discovered #{discovered.size} OpenAI provider instance candidate(s): #{instance_names}" }
112
+ discovered
105
113
  end
106
114
 
107
115
  def self.settings_instances(config)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-llm-openai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - LegionIO