lex-llm 0.8.0 → 0.8.5

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -0
  3. data/README.md +34 -0
  4. data/lib/legion/extensions/llm/canonical/chunk.rb +1 -2
  5. data/lib/legion/extensions/llm/canonical/content_block.rb +1 -2
  6. data/lib/legion/extensions/llm/canonical/message.rb +1 -2
  7. data/lib/legion/extensions/llm/canonical/params.rb +3 -5
  8. data/lib/legion/extensions/llm/canonical/request.rb +1 -2
  9. data/lib/legion/extensions/llm/canonical/response.rb +1 -2
  10. data/lib/legion/extensions/llm/canonical/thinking.rb +2 -98
  11. data/lib/legion/extensions/llm/canonical/thinking_config.rb +149 -0
  12. data/lib/legion/extensions/llm/canonical/tool_call.rb +1 -2
  13. data/lib/legion/extensions/llm/canonical.rb +1 -0
  14. data/lib/legion/extensions/llm/connection.rb +1 -1
  15. data/lib/legion/extensions/llm/credential_sources.rb +1 -5
  16. data/lib/legion/extensions/llm/provider/open_ai_compatible.rb +7 -1
  17. data/lib/legion/extensions/llm/responses/tool_arguments.rb +19 -5
  18. data/lib/legion/extensions/llm/version.rb +1 -1
  19. data/lib/legion/extensions/llm.rb +3 -0
  20. data/spec/legion/extensions/llm/canonical/params_spec.rb +0 -2
  21. data/spec/legion/extensions/llm/canonical/thinking/config_spec.rb +222 -0
  22. data/spec/legion/extensions/llm/canonical/thinking_spec.rb +0 -68
  23. data/spec/legion/extensions/llm/conformance/client_translator_examples.rb +1 -2
  24. data/spec/legion/extensions/llm/conformance/fixtures/canonical_fleet_round_trip.json +1 -1
  25. data/spec/legion/extensions/llm/conformance/fixtures/canonical_thinking_request.json +2 -2
  26. data/spec/legion/extensions/llm/conformance/ssot_contract_conformance_spec.rb +2 -4
  27. data/spec/legion/extensions/llm/conformance/ssot_contract_examples.rb +2 -4
  28. data/spec/legion/extensions/llm/connection_tls_spec.rb +103 -0
  29. data/spec/legion/extensions/llm/credential_sources_spec.rb +16 -7
  30. data/spec/legion/extensions/llm/fleet_messages_spec.rb +1 -2
  31. data/spec/legion/extensions/llm/gemspec_spec.rb +1 -2
  32. data/spec/legion/extensions/llm/provider/open_ai_compatible_spec.rb +23 -0
  33. data/spec/legion/extensions/llm/provider_spec.rb +1 -2
  34. data/spec/support/tls_endpoint.rb +92 -0
  35. metadata +5 -1
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+ require 'socket'
5
+ require 'tempfile'
6
+ require 'timeout'
7
+
8
+ module SpecSupport
9
+ # One real HTTPS exchange, using a fresh private CA rather than external trust.
10
+ class TlsEndpoint
11
+ attr_reader :url, :ca_file, :requests
12
+
13
+ def initialize(subject_alt_name: 'IP:127.0.0.1')
14
+ ca_key = OpenSSL::PKey::EC.generate('prime256v1')
15
+ ca = certificate(key: ca_key, name: 'lex-llm test CA')
16
+ ca_extensions = OpenSSL::X509::ExtensionFactory.new
17
+ ca_extensions.subject_certificate = ca
18
+ ca_extensions.issuer_certificate = ca
19
+ ca.add_extension(ca_extensions.create_extension('basicConstraints', 'CA:TRUE', true))
20
+ ca.add_extension(ca_extensions.create_extension('keyUsage', 'keyCertSign,cRLSign', true))
21
+ ca.sign(ca_key, OpenSSL::Digest.new('SHA256'))
22
+
23
+ key = OpenSSL::PKey::EC.generate('prime256v1')
24
+ cert = certificate(key: key, name: 'lex-llm test endpoint')
25
+ cert.issuer = ca.subject
26
+ extensions = OpenSSL::X509::ExtensionFactory.new
27
+ extensions.subject_certificate = cert
28
+ extensions.issuer_certificate = ca
29
+ cert.add_extension(extensions.create_extension('basicConstraints', 'CA:FALSE', true))
30
+ cert.add_extension(extensions.create_extension('keyUsage', 'digitalSignature', true))
31
+ cert.add_extension(extensions.create_extension('extendedKeyUsage', 'serverAuth'))
32
+ cert.add_extension(extensions.create_extension('subjectAltName', subject_alt_name))
33
+ cert.sign(ca_key, OpenSSL::Digest.new('SHA256'))
34
+
35
+ @ca_file = Tempfile.new(['lex-llm-ca', '.pem'])
36
+ @ca_file.write(ca.to_pem)
37
+ @ca_file.flush
38
+ @requests = []
39
+ @listener = TCPServer.new('127.0.0.1', 0)
40
+ @url = "https://127.0.0.1:#{@listener.addr[1]}"
41
+ context = OpenSSL::SSL::SSLContext.new
42
+ context.cert = cert
43
+ context.key = key
44
+ server = OpenSSL::SSL::SSLServer.new(@listener, context)
45
+ @worker = Thread.new { serve(server: server) }
46
+ end
47
+
48
+ def finish
49
+ raise Timeout::Error, 'TLS fixture did not finish its exchange' unless @worker.join(5)
50
+
51
+ @worker.value
52
+ end
53
+
54
+ def close
55
+ @worker&.kill
56
+ @worker&.join
57
+ @listener&.close
58
+ @ca_file&.close!
59
+ end
60
+
61
+ private
62
+
63
+ def certificate(key:, name:)
64
+ cert = OpenSSL::X509::Certificate.new
65
+ cert.version = 2
66
+ cert.serial = OpenSSL::BN.rand(128).to_i
67
+ cert.subject = OpenSSL::X509::Name.parse("/CN=#{name}")
68
+ cert.issuer = cert.subject
69
+ cert.public_key = key
70
+ cert.not_before = Time.now - 60
71
+ cert.not_after = Time.now + 3600
72
+ cert
73
+ end
74
+
75
+ def serve(server:)
76
+ socket = server.accept
77
+ request = +''
78
+ while (line = socket.gets) && line != "\r\n"
79
+ request << line
80
+ end
81
+ return if request.empty?
82
+
83
+ @requests << request
84
+ body = '{"status":"ok"}'
85
+ socket.write("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: #{body.bytesize}\r\nConnection: close\r\n\r\n#{body}")
86
+ rescue OpenSSL::SSL::SSLError => e
87
+ Legion::Logging.debug("TLS fixture handshake rejected: #{e.class}")
88
+ ensure
89
+ socket&.close
90
+ end
91
+ end
92
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - LegionIO
@@ -267,6 +267,7 @@ files:
267
267
  - lib/legion/extensions/llm/canonical/response.rb
268
268
  - lib/legion/extensions/llm/canonical/strict.rb
269
269
  - lib/legion/extensions/llm/canonical/thinking.rb
270
+ - lib/legion/extensions/llm/canonical/thinking_config.rb
270
271
  - lib/legion/extensions/llm/canonical/tool_call.rb
271
272
  - lib/legion/extensions/llm/canonical/tool_definition.rb
272
273
  - lib/legion/extensions/llm/canonical/tool_schema.rb
@@ -342,6 +343,7 @@ files:
342
343
  - spec/legion/extensions/llm/canonical/params_spec.rb
343
344
  - spec/legion/extensions/llm/canonical/request_spec.rb
344
345
  - spec/legion/extensions/llm/canonical/response_spec.rb
346
+ - spec/legion/extensions/llm/canonical/thinking/config_spec.rb
345
347
  - spec/legion/extensions/llm/canonical/thinking_spec.rb
346
348
  - spec/legion/extensions/llm/canonical/tool_call_spec.rb
347
349
  - spec/legion/extensions/llm/canonical/tool_definition_spec.rb
@@ -386,6 +388,7 @@ files:
386
388
  - spec/legion/extensions/llm/connection_close_spec.rb
387
389
  - spec/legion/extensions/llm/connection_logging_spec.rb
388
390
  - spec/legion/extensions/llm/connection_retry_spec.rb
391
+ - spec/legion/extensions/llm/connection_tls_spec.rb
389
392
  - spec/legion/extensions/llm/credential_sources_spec.rb
390
393
  - spec/legion/extensions/llm/error_middleware_spec.rb
391
394
  - spec/legion/extensions/llm/error_spec.rb
@@ -437,6 +440,7 @@ files:
437
440
  - spec/support/rspec_configuration.rb
438
441
  - spec/support/simplecov_configuration.rb
439
442
  - spec/support/ssot_registry_helpers.rb
443
+ - spec/support/tls_endpoint.rb
440
444
  homepage: https://github.com/LegionIO/lex-llm
441
445
  licenses:
442
446
  - MIT