legion-llm 0.3.2 → 0.3.3

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: 45ff0d9cdd07ee541c80dbac46e66d37542af95a96a614e31fc4af2c2bdf7833
4
- data.tar.gz: 1562706b98e0e6e301a76dec373cecbcf99a3eb3a8e74a0d258928fbbaaf5be7
3
+ metadata.gz: 7faf26458139d4c0e585e5c30e42602e85402e20abcbe2cd73ef8449ae17f947
4
+ data.tar.gz: 73fecb93dbfd407891e64a4278c21c9e9f7fcc2af8313660de4e075a3195bbc7
5
5
  SHA512:
6
- metadata.gz: e28b6c1e39599d1ecd16a60ff67bf4c7625b2d3cdcb2406b465751640b13d44d8a16e593644a4ee30f0bdcaff577580a19e7577e48a7bb07dc3fcfaaf28b3de9
7
- data.tar.gz: d8fe57b67e87f8035c9c78c9bc8489aea68d75d50e477ca0007cd471cd24254081cf6784d2350d128d721dbbf4e5332340ac8e5d8297e9feffb1efe826b87d11
6
+ metadata.gz: 067c7e99927b675df13517a6ca5aa12b494fdedd8e277e7a42ae060e7597033597fbd0f88f595d5368937ba4a00aa7f6e2e02c14e56d01763f4253eb1cd3f421
7
+ data.tar.gz: 9dc754975461db838b49d1f9826d54a80c7bdf106fa44fa6fe3d3693eefe70a1d503ed5025e551a458b367ab53580c67b7c9cf1fb9ee01e69cd5c2394181f150
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Legion LLM Changelog
2
2
 
3
+ ## [0.3.3] - 2026-03-17
4
+
5
+ ### Added
6
+ - `Router::GatewayInterceptor`: optional gateway routing mode for cloud-tier LLM calls
7
+ - Gateway settings: endpoint, API key, model policy per risk tier, fallback_to_direct
8
+ - Identity header builder: X-Agent-Id, X-Tenant-Id, X-AIRB-Project-Id, X-Risk-Tier
9
+ - Model selection policy: fnmatch-based allowlist per risk tier
10
+ - Wired gateway interceptor into `chat_single` for automatic cloud-tier interception
11
+
3
12
  ## [0.3.2] - 2026-03-16
4
13
 
5
14
  ### Added
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module LLM
5
+ module Router
6
+ module GatewayInterceptor
7
+ module_function
8
+
9
+ def intercept(resolution, context: {})
10
+ return resolution unless gateway_enabled?
11
+ return resolution unless resolution&.tier == :cloud
12
+
13
+ model = resolution.model
14
+ risk_tier = context[:risk_tier]&.to_sym
15
+
16
+ unless model_allowed?(model, risk_tier)
17
+ Legion::Logging.warn "[llm] gateway policy blocked model=#{model} risk_tier=#{risk_tier}"
18
+ return nil
19
+ end
20
+
21
+ Resolution.new(
22
+ tier: :cloud,
23
+ provider: :gateway,
24
+ model: model,
25
+ rule: 'gateway_intercept',
26
+ metadata: { original_provider: resolution.provider }
27
+ )
28
+ end
29
+
30
+ def gateway_enabled?
31
+ settings = gateway_settings
32
+ settings[:enabled] == true && !settings[:endpoint].nil?
33
+ end
34
+
35
+ def model_allowed?(model, risk_tier)
36
+ return true unless risk_tier
37
+
38
+ allowlist = gateway_settings.dig(:model_policy, risk_tier)
39
+ return true unless allowlist.is_a?(Array) && !allowlist.empty?
40
+
41
+ allowlist.any? { |pattern| File.fnmatch?(pattern, model.to_s) }
42
+ end
43
+
44
+ def gateway_headers(context)
45
+ {
46
+ 'X-Agent-Id' => context[:worker_id],
47
+ 'X-Tenant-Id' => context[:tenant_id],
48
+ 'X-AIRB-Project-Id' => context[:airb_project_id],
49
+ 'X-Risk-Tier' => context[:risk_tier]&.to_s,
50
+ 'X-Legion-Task-Id' => context[:task_id]&.to_s
51
+ }.compact
52
+ end
53
+
54
+ def gateway_settings
55
+ llm = Legion::Settings[:llm]
56
+ return {} unless llm.is_a?(Hash)
57
+
58
+ (llm[:gateway] || {}).transform_keys(&:to_sym)
59
+ rescue StandardError
60
+ {}
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -4,6 +4,7 @@ require_relative 'router/resolution'
4
4
  require_relative 'router/rule'
5
5
  require_relative 'router/health_tracker'
6
6
  require_relative 'router/escalation_chain'
7
+ require_relative 'router/gateway_interceptor'
7
8
  require_relative 'discovery/ollama'
8
9
  require_relative 'discovery/system'
9
10
 
@@ -11,7 +11,8 @@ module Legion
11
11
  default_provider: nil,
12
12
  providers: providers,
13
13
  routing: routing_defaults,
14
- discovery: discovery_defaults
14
+ discovery: discovery_defaults,
15
+ gateway: gateway_defaults
15
16
  }
16
17
  end
17
18
 
@@ -47,6 +48,18 @@ module Legion
47
48
  }
48
49
  end
49
50
 
51
+ def self.gateway_defaults
52
+ {
53
+ enabled: false,
54
+ endpoint: nil,
55
+ api_key: nil,
56
+ timeout_seconds: 30,
57
+ model_policy: {},
58
+ headers: {},
59
+ fallback_to_direct: true
60
+ }
61
+ end
62
+
50
63
  def self.providers
51
64
  {
52
65
  bedrock: {
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module LLM
5
- VERSION = '0.3.2'
5
+ VERSION = '0.3.3'
6
6
  end
7
7
  end
data/lib/legion/llm.rb CHANGED
@@ -114,6 +114,7 @@ module Legion
114
114
  if (intent || tier) && Router.routing_enabled?
115
115
  resolution = Router.resolve(intent: intent, tier: tier, model: model, provider: provider)
116
116
  if resolution
117
+ resolution = Router::GatewayInterceptor.intercept(resolution, context: kwargs.fetch(:context, {}))
117
118
  model = resolution.model
118
119
  provider = resolution.provider
119
120
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -99,6 +99,7 @@ files:
99
99
  - lib/legion/llm/quality_checker.rb
100
100
  - lib/legion/llm/router.rb
101
101
  - lib/legion/llm/router/escalation_chain.rb
102
+ - lib/legion/llm/router/gateway_interceptor.rb
102
103
  - lib/legion/llm/router/health_tracker.rb
103
104
  - lib/legion/llm/router/resolution.rb
104
105
  - lib/legion/llm/router/rule.rb