legion-llm 0.5.19 → 0.5.20

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: ac3514ef943a51cc0f3d2457cc4fa976b63cb2999896626ade1d76dc7c4f7804
4
- data.tar.gz: f71220f0ad03f65436d0e0f6ce0f34a3ecbbb5fc0bda3add29f9dcaa1713b07d
3
+ metadata.gz: f51b096c53558665dbfc074fa203c8624aa79444324cb686759aee35cd568ca6
4
+ data.tar.gz: 95c6a41fa6839d476cff0d60a6b56a1fbc7ad5be4f914f290fc877e0198e50bc
5
5
  SHA512:
6
- metadata.gz: 7112f4a875c4a49f01d2bf30249c44f85e9427722009c7474a3bb303f4f082010e117650bcacddd1ee2a0cd930d45ad043b6374f8050b31046d195975dcdf222
7
- data.tar.gz: f01fd5cfc55684040cc9c312154811a117fb568576f136c9e87fb83c178c89f9ea6eceaf025e7c4f678e182be5d0a76eb7f656ce6b8b552eeb577f3fbe1e737a
6
+ metadata.gz: 33a939afde771b78203d7c84f3fdb9ccbe226907037bc97f86a5650324c089e1034e9de3251ea1deb72d634680b3de6e263a48bbb933648621586598d1244f16
7
+ data.tar.gz: d0f98e6c6dfbee9040953991e8ab3a0de88cd37ed32a352b2d6d0ef52163e120756238d7d5f96c6f00d028b25e778a2076c9012550879fba1b98b06339d5a63e
data/CHANGELOG.md CHANGED
@@ -2,18 +2,24 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ### Added
6
- - `Legion::LLM::Helper` module at `lib/legion/llm/helper.rb` — canonical helper following cache/transport pattern
7
- - Layered defaults: `llm_default_model`, `llm_default_provider`, `llm_default_intent` (LEX-overridable)
8
- - `llm_embed_batch` batch embedding convenience
9
- - `llm_structured`structured JSON output convenience
10
- - `llm_ask` daemon-first single-shot convenience
11
- - `llm_connected?` / `llm_can_embed?` / `llm_routing_enabled?` status helpers
12
- - `llm_cost_estimate` / `llm_cost_summary` / `llm_budget_remaining`cost and budget helpers
13
- - Layered model/provider/intent defaults applied to `llm_chat` and `llm_session`
5
+ ## [0.5.20] - 2026-03-30
6
+
7
+ ### Added
8
+ - `CodexConfigLoader`: auto-imports OpenAI bearer token from `~/.codex/auth.json` when `auth_mode` is `chatgpt` and no existing OpenAI API key is configured (#15)
9
+ - JWT expiry validation expired codex tokens are skipped with a debug log (#15)
10
+ - Non-JWT tokens (plain API keys) accepted without validation (#15)
11
+ - Falls back to vault/settings/env when codex auth file is absent or token is expired (#15)
12
+ - `Legion::LLM::Helper` module at `lib/legion/llm/helper.rb` — canonical helper following cache/transport pattern (#20)
13
+ - Layered defaults: `llm_default_model`, `llm_default_provider`, `llm_default_intent` (LEX-overridable) (#20)
14
+ - `llm_embed_batch` — batch embedding convenience (#20)
15
+ - `llm_structured` — structured JSON output convenience (#20)
16
+ - `llm_ask` — daemon-first single-shot convenience (#20)
17
+ - `llm_connected?` / `llm_can_embed?` / `llm_routing_enabled?` — status helpers (#20)
18
+ - `llm_cost_estimate` / `llm_cost_summary` / `llm_budget_remaining` — cost and budget helpers (#20)
19
+ - Layered model/provider/intent defaults applied to `llm_chat` and `llm_session` (#20)
14
20
 
15
21
  ### Changed
16
- - `lib/legion/llm/helpers/llm.rb` is now a backward-compat shim that includes `Legion::LLM::Helper`
22
+ - `lib/legion/llm/helpers/llm.rb` is now a backward-compat shim that includes `Legion::LLM::Helper` (#20)
17
23
 
18
24
  ## [0.5.18] - 2026-03-29
19
25
 
@@ -58,6 +64,10 @@
58
64
  ## [0.5.14] - 2026-03-27
59
65
 
60
66
  ### Added
67
+ - `CodexConfigLoader`: auto-imports OpenAI bearer token from `~/.codex/auth.json` when `auth_mode` is `chatgpt` and no existing OpenAI API key is configured
68
+ - JWT expiry validation — expired codex tokens are skipped with a debug log
69
+ - Non-JWT tokens (plain API keys) accepted without validation
70
+ - Falls back to vault/settings/env when codex auth file is absent or token is expired
61
71
  - `DaemonClient.inference` method for conversation-level routing — accepts a full `messages:` array and optional `tools:`, `model:`, `provider:`, and `timeout:` keyword args, posts to `POST /api/llm/inference`, and returns a structured `{ status: :ok, data: { content:, tool_calls:, stop_reason:, model:, input_tokens:, output_tokens: } }` hash on success
62
72
  - `http_post` now accepts an optional `timeout:` keyword argument (default `DEFAULT_TIMEOUT = 60`) so callers like `inference` can pass a longer timeout (120s) without affecting existing `chat` calls
63
73
  - `interpret_inference_response` private helper that maps the `/api/llm/inference` HTTP response — 200 returns `:ok` with structured fields, 4xx/5xx follow the same error handling as `interpret_response`
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'json'
5
+
6
+ module Legion
7
+ module LLM
8
+ module CodexConfigLoader
9
+ CODEX_AUTH = File.expand_path('~/.codex/auth.json')
10
+
11
+ module_function
12
+
13
+ def load
14
+ return unless File.exist?(CODEX_AUTH)
15
+
16
+ config = read_json(CODEX_AUTH)
17
+ return if config.empty?
18
+
19
+ apply_codex_config(config)
20
+ end
21
+
22
+ def read_json(path)
23
+ ::JSON.parse(File.read(path), symbolize_names: true)
24
+ rescue StandardError => e
25
+ Legion::Logging.debug("CodexConfigLoader could not read #{path}: #{e.message}") if defined?(Legion::Logging)
26
+ {}
27
+ end
28
+
29
+ def apply_codex_config(config)
30
+ return unless config[:auth_mode] == 'chatgpt'
31
+
32
+ token = config.dig(:tokens, :access_token)
33
+ return unless token.is_a?(String) && !token.empty?
34
+
35
+ unless token_valid?(token)
36
+ Legion::Logging.debug 'CodexConfigLoader: access token is expired, skipping' if defined?(Legion::Logging)
37
+ return
38
+ end
39
+
40
+ providers = Legion::LLM.settings[:providers]
41
+ existing_raw = providers.dig(:openai, :api_key)
42
+ resolved_existing = resolve_env_api_key(existing_raw)
43
+ return unless resolved_existing.nil? || (resolved_existing.respond_to?(:empty?) && resolved_existing.empty?)
44
+
45
+ providers[:openai][:api_key] = token
46
+ Legion::Logging.debug 'Imported OpenAI API key from Codex auth config' if defined?(Legion::Logging)
47
+ end
48
+
49
+ def resolve_env_api_key(value)
50
+ return nil if value.nil?
51
+
52
+ if value.is_a?(String)
53
+ return nil if value.empty?
54
+
55
+ if value.start_with?('env://')
56
+ env_name = value.sub('env://', '')
57
+ env_value = ENV.fetch(env_name, nil)
58
+ return nil if env_value.nil? || env_value.empty?
59
+
60
+ return env_value
61
+ end
62
+
63
+ return value
64
+ end
65
+
66
+ if value.is_a?(Array)
67
+ resolved = value.map { |v| resolve_env_api_key(v) }.compact
68
+ return nil if resolved.empty?
69
+ return resolved.first if resolved.length == 1
70
+
71
+ return resolved
72
+ end
73
+
74
+ value
75
+ end
76
+
77
+ def token_valid?(token)
78
+ parts = token.split('.')
79
+ return true unless parts.length == 3
80
+
81
+ padded = parts[1] + ('=' * ((4 - (parts[1].length % 4)) % 4))
82
+ payload = ::JSON.parse(Base64.urlsafe_decode64(padded), symbolize_names: true)
83
+ exp = payload[:exp]
84
+ return true unless exp.is_a?(Integer)
85
+
86
+ exp > Time.now.to_i
87
+ rescue StandardError => e
88
+ Legion::Logging.debug("CodexConfigLoader: failed to parse access token for exp validation: #{e.class}: #{e.message}") if defined?(Legion::Logging)
89
+ true
90
+ end
91
+ end
92
+ end
93
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module LLM
5
- VERSION = '0.5.19'
5
+ VERSION = '0.5.20'
6
6
  end
7
7
  end
data/lib/legion/llm.rb CHANGED
@@ -45,6 +45,9 @@ module Legion
45
45
  require 'legion/llm/claude_config_loader'
46
46
  ClaudeConfigLoader.load
47
47
 
48
+ require 'legion/llm/codex_config_loader'
49
+ CodexConfigLoader.load
50
+
48
51
  configure_providers
49
52
  run_discovery
50
53
  detect_embedding_capability
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.5.19
4
+ version: 0.5.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -214,6 +214,7 @@ files:
214
214
  - lib/legion/llm/bedrock_bearer_auth.rb
215
215
  - lib/legion/llm/cache.rb
216
216
  - lib/legion/llm/claude_config_loader.rb
217
+ - lib/legion/llm/codex_config_loader.rb
217
218
  - lib/legion/llm/compressor.rb
218
219
  - lib/legion/llm/confidence_score.rb
219
220
  - lib/legion/llm/confidence_scorer.rb