lex-llm 0.1.7 → 0.1.8
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 +7 -0
- data/lib/legion/extensions/llm/chat.rb +3 -2
- data/lib/legion/extensions/llm/models.rb +7 -4
- data/lib/legion/extensions/llm/provider/open_ai_compatible.rb +2 -1
- data/lib/legion/extensions/llm/provider.rb +2 -0
- data/lib/legion/extensions/llm/streaming.rb +6 -6
- data/lib/legion/extensions/llm/version.rb +1 -1
- data/lib/legion/extensions/llm.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d41cf2984b04621d4e0c2a7fa84a7236361a561570b9944358631a76e6699ac9
|
|
4
|
+
data.tar.gz: c84f98866b4f313d240f964d691b6c170d8635f6275ca8c0150b54d6e2d286cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a4516de1ebcab041beeabaf718ea11ed3445a943a3c4bbe388936622690001dec8606a8c26d5850f123950ac1d4a09361c4513a8387615e86cc5ef99af133860
|
|
7
|
+
data.tar.gz: 3d10adbbb6684df81ac7090a4a7c0ebd179803069e74b80e13a626b1cd93d67e9ab955bb5259a2ab638373aaf786217b738536478893fe8983366a2f29ee6e99
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.8 - 2026-04-30
|
|
4
|
+
|
|
5
|
+
- Audit all rescue blocks for handle_exception compliance
|
|
6
|
+
- Add Legion::Logging::Helper to Provider, Chat, and Models for structured exception reporting
|
|
7
|
+
- Replace ad-hoc logger.debug/warn calls in rescue blocks with handle_exception across streaming, chat, models, and provider modules
|
|
8
|
+
- Add require for legion/logging in the main entrypoint
|
|
9
|
+
|
|
3
10
|
## 0.1.7 - 2026-04-30
|
|
4
11
|
|
|
5
12
|
- Add thinking extraction from OpenAI-compatible streaming chunks (reasoning_content, reasoning, think tags)
|
|
@@ -6,6 +6,7 @@ module Legion
|
|
|
6
6
|
# Represents a conversation with an AI model
|
|
7
7
|
class Chat
|
|
8
8
|
include Enumerable
|
|
9
|
+
include Legion::Logging::Helper
|
|
9
10
|
|
|
10
11
|
attr_reader :model, :messages, :tools, :tool_prefs, :params, :headers, :schema
|
|
11
12
|
|
|
@@ -157,8 +158,8 @@ module Legion
|
|
|
157
158
|
if @schema && response.content.is_a?(String) && !response.tool_call?
|
|
158
159
|
begin
|
|
159
160
|
response.content = Legion::JSON.parse(response.content, symbolize_names: false)
|
|
160
|
-
rescue Legion::JSON::ParseError
|
|
161
|
-
|
|
161
|
+
rescue Legion::JSON::ParseError => e
|
|
162
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.chat.complete')
|
|
162
163
|
end
|
|
163
164
|
end
|
|
164
165
|
|
|
@@ -35,6 +35,8 @@ module Legion
|
|
|
35
35
|
].freeze
|
|
36
36
|
|
|
37
37
|
class << self
|
|
38
|
+
include Legion::Logging::Helper
|
|
39
|
+
|
|
38
40
|
def instance
|
|
39
41
|
@instance ||= new
|
|
40
42
|
end
|
|
@@ -51,7 +53,8 @@ module Legion
|
|
|
51
53
|
data = File.exist?(file) ? File.read(file) : '[]'
|
|
52
54
|
models = Legion::JSON.parse(data, symbolize_names: true).map { |model| Model::Info.new(model) }
|
|
53
55
|
filter_models(models)
|
|
54
|
-
rescue Legion::JSON::ParseError
|
|
56
|
+
rescue Legion::JSON::ParseError => e
|
|
57
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.models.read_from_json')
|
|
55
58
|
[]
|
|
56
59
|
end
|
|
57
60
|
|
|
@@ -92,6 +95,8 @@ module Legion
|
|
|
92
95
|
result[:models].concat(provider_class.new(config).list_models)
|
|
93
96
|
result[:fetched_providers] << provider_class.slug
|
|
94
97
|
rescue StandardError => e
|
|
98
|
+
handle_exception(e, level: :warn, handled: true,
|
|
99
|
+
operation: 'llm.models.fetch_provider_models')
|
|
95
100
|
result[:failed] << { name: provider_class.name, slug: provider_class.slug, error: e }
|
|
96
101
|
end
|
|
97
102
|
end
|
|
@@ -170,9 +175,7 @@ module Legion
|
|
|
170
175
|
end
|
|
171
176
|
{ models: models.reject { |model| model.provider.nil? || model.id.nil? }, fetched: true }
|
|
172
177
|
rescue StandardError => e
|
|
173
|
-
|
|
174
|
-
"Failed to fetch models.dev (#{e.class}: #{e.message}). Keeping existing."
|
|
175
|
-
)
|
|
178
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.models.fetch_models_dev')
|
|
176
179
|
{
|
|
177
180
|
models: existing_models.select { |model| model.metadata[:source] == 'models.dev' },
|
|
178
181
|
fetched: false
|
|
@@ -218,7 +218,8 @@ module Legion
|
|
|
218
218
|
return arguments if arguments.is_a?(Hash)
|
|
219
219
|
|
|
220
220
|
Legion::JSON.parse(arguments, symbolize_names: false)
|
|
221
|
-
rescue Legion::JSON::ParseError
|
|
221
|
+
rescue Legion::JSON::ParseError => e
|
|
222
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.provider.parse_tool_arguments')
|
|
222
223
|
{}
|
|
223
224
|
end
|
|
224
225
|
|
|
@@ -6,6 +6,7 @@ module Legion
|
|
|
6
6
|
# Base class for LLM providers.
|
|
7
7
|
class Provider
|
|
8
8
|
include Streaming
|
|
9
|
+
include Legion::Logging::Helper
|
|
9
10
|
|
|
10
11
|
attr_reader :config, :connection
|
|
11
12
|
|
|
@@ -131,6 +132,7 @@ module Legion
|
|
|
131
132
|
response = @connection.get(metadata[:endpoints][:health])
|
|
132
133
|
metadata.merge(ready: configured? && health_ready?(response.body), health: response.body)
|
|
133
134
|
rescue StandardError => e
|
|
135
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.provider.readiness')
|
|
134
136
|
metadata.merge(ready: false, health: { error: e.class.name, message: e.message })
|
|
135
137
|
end
|
|
136
138
|
|
|
@@ -91,8 +91,8 @@ module Legion
|
|
|
91
91
|
buffer << chunk
|
|
92
92
|
error_data = Legion::JSON.parse(buffer, symbolize_names: false)
|
|
93
93
|
handle_parsed_error(error_data, env)
|
|
94
|
-
rescue Legion::JSON::ParseError
|
|
95
|
-
|
|
94
|
+
rescue Legion::JSON::ParseError => e
|
|
95
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.streaming.handle_failed_response')
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
def handle_sse(chunk, parser, env, &)
|
|
@@ -112,7 +112,7 @@ module Legion
|
|
|
112
112
|
|
|
113
113
|
handle_parsed_error(parsed, env)
|
|
114
114
|
rescue Legion::JSON::ParseError => e
|
|
115
|
-
|
|
115
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.streaming.handle_data')
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
def handle_error_event(data, env)
|
|
@@ -123,7 +123,7 @@ module Legion
|
|
|
123
123
|
error_data = Legion::JSON.parse(data, symbolize_names: false)
|
|
124
124
|
[500, error_data['message'] || 'Unknown streaming error']
|
|
125
125
|
rescue Legion::JSON::ParseError => e
|
|
126
|
-
|
|
126
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.streaming.parse_streaming_error')
|
|
127
127
|
[500, "Failed to parse error: #{data}"]
|
|
128
128
|
end
|
|
129
129
|
|
|
@@ -133,11 +133,11 @@ module Legion
|
|
|
133
133
|
ErrorMiddleware.parse_error(provider: self, response: error_response)
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
def parse_error_from_json(data, env,
|
|
136
|
+
def parse_error_from_json(data, env, _error_message)
|
|
137
137
|
parsed_data = Legion::JSON.parse(data, symbolize_names: false)
|
|
138
138
|
handle_parsed_error(parsed_data, env)
|
|
139
139
|
rescue Legion::JSON::ParseError => e
|
|
140
|
-
|
|
140
|
+
handle_exception(e, level: :warn, handled: true, operation: 'llm.streaming.parse_error_from_json')
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
def build_stream_error_response(parsed_data, env, status)
|