lex-llm-ledger 0.3.1 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a69d4ccf5975f45c795e6e54ab6ed59272a269855394bbef4d1149a48bd338e7
4
- data.tar.gz: 60bfc3f268526d0cf427ccfa90f2e230f9e0491fd88584ff685604c93faf63c4
3
+ metadata.gz: 84be271a1d8b2960d1eeef98a01c950ed2d44cab4e2e6d4c8dd6708980d027d4
4
+ data.tar.gz: 6da1a77c998891e3b2e1a5fae24b1109c51715c762b52aa308ebb73abb886188
5
5
  SHA512:
6
- metadata.gz: e166ea0dc31b758dd45d5c1595f6a72c78629b7dfd69d09d9928a699ce14f475658d9bf77f08018608bc98f394532f4c19b5887c3b2649bb1761aecbe2b4b5c8
7
- data.tar.gz: 226be9d0592d67fcca0ff956fe0c62db56a311cc3f6bde5a16523f21801d43079d976a6d6582e2a0f1022396089555495df37ccf81ccfd56ddfd3f2344f9d27f
6
+ metadata.gz: 51705c939e26737dfda07ac40df418887d15550e758b4db28aea1e377579b8c65108614cd5abd1ef6a309696c4b90149d1d3dacce6507011a219b90edb7d3a1e
7
+ data.tar.gz: 163077fbadc935cdeb751645fc59d06a59bf3cd47db7d93d427b721cbdc067f6749c0d6adf6641b1ded3c160c03a252f2382b383d778068b7f59ececcb1b6bb0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.2] - 2026-05-13
4
+
5
+ ### Fixed
6
+ - Keep metering-only writes from creating placeholder conversation messages so later prompt audits can attach the real user and assistant messages without sequence collisions.
7
+ - Use the request reference as the default inference metric idempotency key so metering and prompt audit events enrich the same metric row.
8
+ - Suppress duplicate insert warnings for unique races handled by the official ledger writer while retaining debug-level collision messages.
9
+
3
10
  ## [0.3.1] - 2026-05-13
4
11
 
5
12
  ### Fixed
@@ -184,7 +184,7 @@ module Legion
184
184
  end
185
185
 
186
186
  def official_metric_uuid(payload)
187
- ref = payload[:message_id] || "metric:#{Writers::OfficialRecordWriter.request_ref(payload)}"
187
+ ref = payload[:metric_id] || payload[:metric_ref] || "metric:#{Writers::OfficialRecordWriter.request_ref(payload)}"
188
188
  Writers::OfficialRecordWriter.stable_uuid(ref)
189
189
  end
190
190
 
@@ -19,13 +19,15 @@ module Legion
19
19
 
20
20
  module_function
21
21
 
22
- def insert_row(db, table, attributes, operation:)
22
+ def insert_row(db, table, attributes, operation:, warn_on_unique: true)
23
23
  row_id = db[table].insert(attributes)
24
24
  log.info(log_message('inserted', table, operation, row_id, attributes))
25
25
  row_id
26
26
  rescue Sequel::UniqueConstraintViolation => e
27
- log.warn(log_message('insert_failed', table, operation, nil, attributes,
28
- error_class: e.class, error: e.message))
27
+ if warn_on_unique
28
+ log.warn(log_message('insert_failed', table, operation, nil, attributes,
29
+ error_class: e.class, error: e.message))
30
+ end
29
31
  raise
30
32
  rescue StandardError => e
31
33
  log.error(log_message('insert_failed', table, operation, nil, attributes,
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Ledger
7
- VERSION = '0.3.1'
7
+ VERSION = '0.3.2'
8
8
  end
9
9
  end
10
10
  end
@@ -42,8 +42,7 @@ module Legion
42
42
 
43
43
  db.transaction do
44
44
  conversation = find_or_create_conversation(db, body)
45
- user_message = find_or_create_user_message(db, conversation, body)
46
- request = find_or_create_request(db, conversation, user_message, body)
45
+ request = find_or_create_request(db, conversation, nil, body)
47
46
  response = find_or_create_response(db, request, nil, body)
48
47
  metric = find_or_create_metric(db, request, response, body)
49
48
  result = { result: :ok, request_id: request[:id], response_id: response[:id], metric_id: metric[:id] }
@@ -109,17 +108,14 @@ module Legion
109
108
  def find_or_create_request(db, conversation, latest_message, body)
110
109
  request_id = request_ref(body)
111
110
  existing = db[:llm_message_inference_requests].where(request_ref: request_id).first
112
- if existing
113
- enrich_request!(db, existing, body)
114
- return existing
115
- end
111
+ return enrich_request!(db, existing, body, latest_message) if existing
116
112
 
117
113
  operation = operation(body)
118
114
  caller_refs = caller_identity_refs(db, body)
119
115
  id = insert_with_savepoint(db, :llm_message_inference_requests, {
120
116
  uuid: stable_uuid(request_id),
121
117
  conversation_id: conversation[:id],
122
- latest_message_id: latest_message[:id],
118
+ latest_message_id: latest_message&.dig(:id),
123
119
  caller_principal_id: caller_refs[:principal_id],
124
120
  caller_identity_id: caller_refs[:identity_id],
125
121
  runtime_caller_type: caller_type(body),
@@ -144,10 +140,7 @@ module Legion
144
140
  rescue Sequel::UniqueConstraintViolation => e
145
141
  log.debug("[ledger] request collision resolved request_ref=#{request_id} error=#{e.class}")
146
142
  existing = db[:llm_message_inference_requests].where(request_ref: request_id).first
147
- if existing
148
- enrich_request!(db, existing, body)
149
- return existing
150
- end
143
+ return enrich_request!(db, existing, body, latest_message) if existing
151
144
 
152
145
  raise
153
146
  end
@@ -252,7 +245,7 @@ module Legion
252
245
  end
253
246
 
254
247
  def find_or_create_metric(db, request, response, body)
255
- metric_uuid = stable_uuid(reference(body, :message_id) || "metric:#{request_ref(body)}")
248
+ metric_uuid = stable_uuid(reference(body, :metric_id, :metric_ref) || "metric:#{request_ref(body)}")
256
249
  existing = db[:llm_message_inference_metrics].where(uuid: metric_uuid).first
257
250
  return existing if existing
258
251
 
@@ -287,7 +280,7 @@ module Legion
287
280
  end
288
281
 
289
282
  def insert_row(db, table, attributes, operation:)
290
- Helpers::PersistenceLogging.insert_row(db, table, attributes, operation: operation)
283
+ Helpers::PersistenceLogging.insert_row(db, table, attributes, operation: operation, warn_on_unique: false)
291
284
  end
292
285
 
293
286
  def insert_with_savepoint(db, table, attributes, operation:)
@@ -309,8 +302,9 @@ module Legion
309
302
  db[:llm_messages].where(id: response_message[:id]).update(message_inference_response_id: response[:id])
310
303
  end
311
304
 
312
- def enrich_request!(db, existing, body)
305
+ def enrich_request!(db, existing, body, latest_message = nil)
313
306
  updates = {}
307
+ update_if_missing(updates, existing, :latest_message_id, latest_message&.dig(:id))
314
308
  caller_refs = caller_identity_refs(db, body)
315
309
  updates[:caller_identity_id] = caller_refs[:identity_id] if existing[:caller_identity_id].nil? && caller_refs[:identity_id]
316
310
  updates[:caller_principal_id] = caller_refs[:principal_id] if existing[:caller_principal_id].nil? && caller_refs[:principal_id]
@@ -322,10 +316,11 @@ module Legion
322
316
  msg_count = Array(body.dig(:request, :messages) || body[:messages]).size
323
317
  updates[:context_message_count] = msg_count if existing[:context_message_count].to_i.zero? && msg_count.positive?
324
318
 
325
- return if updates.empty?
319
+ return existing if updates.empty?
326
320
 
327
321
  db[:llm_message_inference_requests].where(id: existing[:id]).update(updates)
328
322
  log.info("[ledger] enriched request id=#{existing[:id]} fields=#{updates.keys.join(',')}")
323
+ existing.merge(updates)
329
324
  end
330
325
 
331
326
  def caller_identity(body)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-llm-ledger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity