legionio 1.4.122 → 1.4.123

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/lib/legion/alerts.rb +2 -1
  4. data/lib/legion/api/acp.rb +8 -4
  5. data/lib/legion/api/auth_human.rb +4 -2
  6. data/lib/legion/api/auth_saml.rb +6 -3
  7. data/lib/legion/api/auth_worker.rb +2 -1
  8. data/lib/legion/api/capacity.rb +2 -1
  9. data/lib/legion/api/catalog.rb +6 -3
  10. data/lib/legion/api/events.rb +2 -1
  11. data/lib/legion/api/gaia.rb +2 -1
  12. data/lib/legion/api/governance.rb +2 -1
  13. data/lib/legion/api/graphql/resolvers/extensions.rb +4 -2
  14. data/lib/legion/api/graphql/resolvers/node.rb +4 -2
  15. data/lib/legion/api/graphql/resolvers/tasks.rb +4 -2
  16. data/lib/legion/api/graphql/resolvers/workers.rb +4 -2
  17. data/lib/legion/api/helpers.rb +4 -2
  18. data/lib/legion/api/marketplace.rb +9 -3
  19. data/lib/legion/api/middleware/auth.rb +10 -5
  20. data/lib/legion/api/middleware/rate_limit.rb +2 -1
  21. data/lib/legion/api/org_chart.rb +2 -1
  22. data/lib/legion/api/prompts.rb +2 -1
  23. data/lib/legion/api/transport.rb +6 -3
  24. data/lib/legion/api/workflow.rb +2 -1
  25. data/lib/legion/audit.rb +2 -1
  26. data/lib/legion/catalog.rb +3 -1
  27. data/lib/legion/chat/notification_bridge.rb +2 -1
  28. data/lib/legion/cli/acp_command.rb +3 -1
  29. data/lib/legion/cli/auth_command.rb +7 -1
  30. data/lib/legion/cli/chat/agent_registry.rb +2 -1
  31. data/lib/legion/cli/chat/checkpoint.rb +4 -2
  32. data/lib/legion/cli/chat/context.rb +4 -3
  33. data/lib/legion/cli/chat/extension_tool_loader.rb +4 -2
  34. data/lib/legion/cli/chat/markdown_renderer.rb +2 -1
  35. data/lib/legion/cli/chat/session.rb +2 -1
  36. data/lib/legion/cli/chat/subagent.rb +6 -2
  37. data/lib/legion/cli/chat/tool_registry.rb +4 -3
  38. data/lib/legion/cli/chat/tools/edit_file.rb +1 -0
  39. data/lib/legion/cli/chat/tools/read_file.rb +1 -0
  40. data/lib/legion/cli/chat/tools/run_command.rb +3 -1
  41. data/lib/legion/cli/chat/tools/save_memory.rb +1 -0
  42. data/lib/legion/cli/chat/tools/search_content.rb +7 -3
  43. data/lib/legion/cli/chat/tools/search_files.rb +1 -0
  44. data/lib/legion/cli/chat/tools/search_memory.rb +1 -0
  45. data/lib/legion/cli/chat/tools/spawn_agent.rb +1 -0
  46. data/lib/legion/cli/chat/tools/web_search.rb +2 -0
  47. data/lib/legion/cli/chat/tools/write_file.rb +1 -0
  48. data/lib/legion/cli/chat/web_search.rb +4 -2
  49. data/lib/legion/cli/chat_command.rb +21 -8
  50. data/lib/legion/cli/check/privacy_check.rb +6 -3
  51. data/lib/legion/cli/check_command.rb +4 -3
  52. data/lib/legion/cli/coldstart_command.rb +4 -2
  53. data/lib/legion/cli/config_command.rb +2 -1
  54. data/lib/legion/cli/config_scaffold.rb +2 -1
  55. data/lib/legion/cli/connection.rb +2 -2
  56. data/lib/legion/cli/cost/data_client.rb +2 -1
  57. data/lib/legion/cli/dashboard/data_fetcher.rb +2 -1
  58. data/lib/legion/cli/dashboard_command.rb +1 -0
  59. data/lib/legion/cli/detect_command.rb +2 -1
  60. data/lib/legion/cli/doctor/bundle_check.rb +2 -1
  61. data/lib/legion/cli/doctor/cache_check.rb +2 -1
  62. data/lib/legion/cli/doctor/database_check.rb +2 -1
  63. data/lib/legion/cli/doctor/extensions_check.rb +2 -1
  64. data/lib/legion/cli/doctor/pid_check.rb +2 -1
  65. data/lib/legion/cli/doctor/rabbitmq_check.rb +4 -2
  66. data/lib/legion/cli/doctor/vault_check.rb +2 -1
  67. data/lib/legion/cli/doctor_command.rb +1 -0
  68. data/lib/legion/cli/gaia_command.rb +4 -2
  69. data/lib/legion/cli/init/environment_detector.rb +4 -2
  70. data/lib/legion/cli/lex_cli_manifest.rb +2 -1
  71. data/lib/legion/cli/lex_command.rb +8 -4
  72. data/lib/legion/cli/llm_command.rb +9 -5
  73. data/lib/legion/cli/marketplace_command.rb +2 -1
  74. data/lib/legion/cli/payroll_command.rb +3 -0
  75. data/lib/legion/cli/plan_command.rb +2 -1
  76. data/lib/legion/cli/setup_command.rb +8 -4
  77. data/lib/legion/cli/start.rb +2 -1
  78. data/lib/legion/cli/status.rb +2 -1
  79. data/lib/legion/cli/task_command.rb +6 -3
  80. data/lib/legion/cli/tty_command.rb +1 -0
  81. data/lib/legion/cli/update_command.rb +4 -2
  82. data/lib/legion/cli.rb +10 -4
  83. data/lib/legion/cluster/leader.rb +2 -1
  84. data/lib/legion/cluster/lock.rb +8 -4
  85. data/lib/legion/digital_worker/value_metrics.rb +2 -1
  86. data/lib/legion/docs/site_generator.rb +8 -6
  87. data/lib/legion/extensions/actors/subscription.rb +2 -1
  88. data/lib/legion/extensions/core.rb +2 -2
  89. data/lib/legion/extensions/permissions.rb +6 -3
  90. data/lib/legion/extensions.rb +12 -6
  91. data/lib/legion/graph/builder.rb +2 -1
  92. data/lib/legion/guardrails.rb +2 -1
  93. data/lib/legion/lock.rb +8 -4
  94. data/lib/legion/metrics.rb +2 -1
  95. data/lib/legion/notebook/renderer.rb +2 -1
  96. data/lib/legion/phi/access_log.rb +2 -1
  97. data/lib/legion/phi/erasure.rb +4 -2
  98. data/lib/legion/phi.rb +4 -2
  99. data/lib/legion/process.rb +4 -2
  100. data/lib/legion/process_role.rb +6 -1
  101. data/lib/legion/region/failover.rb +2 -1
  102. data/lib/legion/region.rb +14 -7
  103. data/lib/legion/registry/governance.rb +2 -1
  104. data/lib/legion/registry/persistence.rb +2 -1
  105. data/lib/legion/runner.rb +3 -2
  106. data/lib/legion/service.rb +10 -6
  107. data/lib/legion/telemetry/open_inference.rb +18 -9
  108. data/lib/legion/telemetry/safety_metrics.rb +4 -2
  109. data/lib/legion/telemetry.rb +14 -7
  110. data/lib/legion/tenants.rb +2 -1
  111. data/lib/legion/version.rb +1 -1
  112. data/lib/legion/webhooks.rb +8 -4
  113. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 102a045825ff17747b2724547e3704b958c55b51e77ce846d4dd8146460e8dbb
4
- data.tar.gz: eccf79a4549c7f5bc949c2dc7141dd9b5ff794c85483d6cc414c790b7c867c06
3
+ metadata.gz: 6d78fc201a2601de3ce04849d24c9234c75bd77f6cdb3b46ca700f7cdd6fcc9f
4
+ data.tar.gz: 5746d467cb709dbf02837ebd2d4288dbe137d234c8f6e1e3b3445dcd899d3515
5
5
  SHA512:
6
- metadata.gz: fb2d2613bfd4e539755cf225e5917ff8aec939840f1435c1308c71ecc862617e31e516876ca6dd513dfe5496106296af1421ae9e3b9431871a99594cdbab5d19
7
- data.tar.gz: 383b632d9dbb961d01895b273b19ead0a1742d56dae85a6090a371aec4a995b065b226c5db1768454cbab95db947fd5eea3443fe89979a529fcdb06bf4d6af56
6
+ metadata.gz: 106274f7798ddf16c3da87f2c0ba204e98c0f8c8d9dedf312376fc8cbde8dbac447306cfd76c6cb0a5e210a22db9304fc37f5e3305f1cd80d918514aad80b4b4
7
+ data.tar.gz: 54ebdc455f6f5f86a0564809a67d6f3edffc20b7c3f438956382d32bff16d2b3469f51d4a48c1a30c312edfe0ad2d81abacc4962a96e79e7669d652cb4644605
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Legion Changelog
2
2
 
3
+ ## [1.4.123] - 2026-03-22
4
+
5
+ ### Changed
6
+ - Add logging to silent rescue blocks: all rescue blocks now capture the exception variable and emit `Legion::Logging.debug` or `.warn` calls so errors are visible in logs rather than silently swallowed
7
+
3
8
  ## [1.4.122] - 2026-03-22
4
9
 
5
10
  ### Added
data/lib/legion/alerts.rb CHANGED
@@ -117,7 +117,8 @@ module Legion
117
117
  def load_rules
118
118
  custom = begin
119
119
  Legion::Settings[:alerts][:rules]
120
- rescue StandardError
120
+ rescue StandardError => e
121
+ Legion::Logging.debug "Alerts#load_rules failed to read settings: #{e.message}" if defined?(Legion::Logging)
121
122
  nil
122
123
  end
123
124
  custom && !custom.empty? ? custom : DEFAULT_RULES
@@ -7,12 +7,14 @@ module Legion
7
7
  def build_agent_card
8
8
  name = begin
9
9
  Legion::Settings[:client][:name]
10
- rescue StandardError
10
+ rescue StandardError => e
11
+ Legion::Logging.debug "Acp#build_agent_card failed to read client name: #{e.message}" if defined?(Legion::Logging)
11
12
  'legion'
12
13
  end
13
14
  port = begin
14
15
  settings.port || 4567
15
- rescue StandardError
16
+ rescue StandardError => e
17
+ Legion::Logging.debug "Acp#build_agent_card failed to read port: #{e.message}" if defined?(Legion::Logging)
16
18
  4567
17
19
  end
18
20
  {
@@ -34,7 +36,8 @@ module Legion
34
36
  else
35
37
  []
36
38
  end
37
- rescue StandardError
39
+ rescue StandardError => e
40
+ Legion::Logging.warn "Acp#discover_capabilities failed: #{e.message}" if defined?(Legion::Logging)
38
41
  []
39
42
  end
40
43
 
@@ -42,7 +45,8 @@ module Legion
42
45
  return nil unless defined?(Legion::Data)
43
46
 
44
47
  Legion::Data::Model::Task[id.to_i]&.values
45
- rescue StandardError
48
+ rescue StandardError => e
49
+ Legion::Logging.warn "Acp#find_task failed for id=#{id}: #{e.message}" if defined?(Legion::Logging)
46
50
  nil
47
51
  end
48
52
 
@@ -20,7 +20,8 @@ module Legion
20
20
  return entra if entra.is_a?(Hash)
21
21
 
22
22
  {}
23
- rescue StandardError
23
+ rescue StandardError => e
24
+ Legion::Logging.debug "AuthHuman#resolve_entra_settings failed: #{e.message}" if defined?(Legion::Logging)
24
25
  {}
25
26
  end
26
27
 
@@ -37,7 +38,8 @@ module Legion
37
38
  return nil unless response.is_a?(Net::HTTPSuccess)
38
39
 
39
40
  Legion::JSON.load(response.body)
40
- rescue StandardError
41
+ rescue StandardError => e
42
+ Legion::Logging.warn "AuthHuman#exchange_code failed: #{e.message}" if defined?(Legion::Logging)
41
43
  nil
42
44
  end
43
45
 
@@ -31,7 +31,8 @@ module Legion
31
31
  return saml if saml.is_a?(Hash)
32
32
 
33
33
  {}
34
- rescue StandardError
34
+ rescue StandardError => e
35
+ Legion::Logging.debug "AuthSaml#resolve_saml_config failed: #{e.message}" if defined?(Legion::Logging)
35
36
  {}
36
37
  end
37
38
 
@@ -161,7 +162,8 @@ module Legion
161
162
  names.each do |n|
162
163
  v = attrs.multi(n)
163
164
  return Array(v) if v
164
- rescue StandardError
165
+ rescue StandardError => e
166
+ Legion::Logging.debug "AuthSaml#multi_attr failed for attr=#{n}: #{e.message}" if defined?(Legion::Logging)
165
167
  nil
166
168
  end
167
169
  []
@@ -169,7 +171,8 @@ module Legion
169
171
 
170
172
  def safe_attr(attrs, name)
171
173
  attrs[name]
172
- rescue StandardError
174
+ rescue StandardError => e
175
+ Legion::Logging.debug "AuthSaml#safe_attr failed for name=#{name}: #{e.message}" if defined?(Legion::Logging)
173
176
  nil
174
177
  end
175
178
 
@@ -106,7 +106,8 @@ module Legion
106
106
  return entra if entra.is_a?(Hash)
107
107
 
108
108
  {}
109
- rescue StandardError
109
+ rescue StandardError => e
110
+ Legion::Logging.debug "AuthWorker#resolve_entra_settings failed: #{e.message}" if defined?(Legion::Logging)
110
111
  {}
111
112
  end
112
113
 
@@ -45,7 +45,8 @@ module Legion
45
45
  Legion::Data::Model::DigitalWorker.all.map do |w|
46
46
  { worker_id: w.worker_id, status: w.lifecycle_state }
47
47
  end
48
- rescue StandardError
48
+ rescue StandardError => e
49
+ Legion::Logging.warn "Capacity#fetch_worker_list failed: #{e.message}" if defined?(Legion::Logging)
49
50
  []
50
51
  end
51
52
  end
@@ -45,7 +45,8 @@ module Legion
45
45
  read_paths: declared[:read_paths],
46
46
  write_paths: declared[:write_paths]
47
47
  }
48
- rescue StandardError
48
+ rescue StandardError => e
49
+ Legion::Logging.warn "API#build_catalog_permissions failed for #{name}: #{e.message}" if defined?(Legion::Logging)
49
50
  { sandbox: Legion::Extensions::Permissions.sandbox_path(name), read_paths: [], write_paths: [] }
50
51
  end
51
52
 
@@ -61,7 +62,8 @@ module Legion
61
62
  description: runner.values[:description]
62
63
  }]
63
64
  end
64
- rescue StandardError
65
+ rescue StandardError => e
66
+ Legion::Logging.warn "API#build_catalog_runners failed for #{name}: #{e.message}" if defined?(Legion::Logging)
65
67
  {}
66
68
  end
67
69
 
@@ -74,7 +76,8 @@ module Legion
74
76
  matched.map do |_hash, pattern|
75
77
  { intent: pattern[:intent_text], tool_chain: pattern[:tool_chain], confidence: pattern[:confidence] }
76
78
  end
77
- rescue StandardError
79
+ rescue StandardError => e
80
+ Legion::Logging.warn "API#build_catalog_known_intents failed for #{name}: #{e.message}" if defined?(Legion::Logging)
78
81
  []
79
82
  end
80
83
  end
@@ -58,7 +58,8 @@ module Legion
58
58
  event = queue.pop
59
59
  data = Legion::JSON.dump(event.transform_keys(&:to_s))
60
60
  out << "event: #{event[:event]}\ndata: #{data}\n\n"
61
- rescue IOError, Errno::EPIPE
61
+ rescue IOError, Errno::EPIPE => e
62
+ Legion::Logging.debug "Events SSE stream broken for #{event[:event]}: #{e.message}" if defined?(Legion::Logging)
62
63
  break
63
64
  end
64
65
  ensure
@@ -36,7 +36,8 @@ module Legion
36
36
  return nil unless Legion::Gaia.channel_registry
37
37
 
38
38
  Legion::Gaia.channel_registry.adapter_for(:teams)
39
- rescue StandardError
39
+ rescue StandardError => e
40
+ Legion::Logging.warn "Gaia#teams_adapter failed: #{e.message}" if defined?(Legion::Logging)
40
41
  nil
41
42
  end
42
43
  end
@@ -14,7 +14,8 @@ module Legion
14
14
  require 'legion/extensions/audit/runners/approval_queue'
15
15
  runner = Object.new.extend(Legion::Extensions::Audit::Runners::ApprovalQueue)
16
16
  runner.send(method, **)
17
- rescue LoadError
17
+ rescue LoadError => e
18
+ Legion::Logging.warn "Governance#run_governance_runner failed to load lex-audit: #{e.message}" if defined?(Legion::Logging)
18
19
  halt 503, json_error('service_unavailable', 'lex-audit not available', status_code: 503)
19
20
  end
20
21
  end
@@ -23,7 +23,8 @@ module Legion
23
23
  dataset = Legion::Data::Model::Extension.order(:id)
24
24
  dataset = dataset.where(status: status) if status
25
25
  dataset.all.map { |e| extension_hash(e.values) }
26
- rescue StandardError
26
+ rescue StandardError => e
27
+ Legion::Logging.warn "GraphQL::Extensions#resolve_from_data failed: #{e.message}" if defined?(Legion::Logging)
27
28
  []
28
29
  end
29
30
 
@@ -34,7 +35,8 @@ module Legion
34
35
  entries = entries.map { |e| e.is_a?(Hash) ? e : e.to_h }
35
36
  entries = entries.select { |e| e[:status].to_s == status } if status
36
37
  entries.map { |e| extension_hash(e) }
37
- rescue StandardError
38
+ rescue StandardError => e
39
+ Legion::Logging.warn "GraphQL::Extensions#resolve_from_registry failed: #{e.message}" if defined?(Legion::Logging)
38
40
  []
39
41
  end
40
42
 
@@ -17,7 +17,8 @@ module Legion
17
17
  uptime: uptime,
18
18
  ready: ready
19
19
  }
20
- rescue StandardError
20
+ rescue StandardError => e
21
+ Legion::Logging.warn "GraphQL::Node#resolve failed: #{e.message}" if defined?(Legion::Logging)
21
22
  { name: nil, version: nil, uptime: nil, ready: false }
22
23
  end
23
24
 
@@ -27,7 +28,8 @@ module Legion
27
28
  Legion::Process.started_at
28
29
 
29
30
  (Time.now.utc - Legion::Process.started_at).to_i
30
- rescue StandardError
31
+ rescue StandardError => e
32
+ Legion::Logging.debug "GraphQL::Node#calculate_uptime failed: #{e.message}" if defined?(Legion::Logging)
31
33
  nil
32
34
  end
33
35
 
@@ -11,7 +11,8 @@ module Legion
11
11
  Legion::Data.connection
12
12
 
13
13
  resolve_from_data(status: status, limit: limit)
14
- rescue StandardError
14
+ rescue StandardError => e
15
+ Legion::Logging.warn "GraphQL::Tasks#resolve failed: #{e.message}" if defined?(Legion::Logging)
15
16
  []
16
17
  end
17
18
 
@@ -22,7 +23,8 @@ module Legion
22
23
  dataset = dataset.where(status: status) if status
23
24
  dataset = dataset.limit(limit) if limit
24
25
  dataset.all.map { |t| task_hash(t.values) }
25
- rescue StandardError
26
+ rescue StandardError => e
27
+ Legion::Logging.warn "GraphQL::Tasks#resolve_from_data failed: #{e.message}" if defined?(Legion::Logging)
26
28
  []
27
29
  end
28
30
 
@@ -29,7 +29,8 @@ module Legion
29
29
  dataset = dataset.where(risk_tier: risk_tier) if risk_tier
30
30
  dataset = dataset.limit(limit) if limit
31
31
  dataset.all.map { |w| worker_hash(w.values) }
32
- rescue StandardError
32
+ rescue StandardError => e
33
+ Legion::Logging.warn "GraphQL::Workers#resolve_from_data failed: #{e.message}" if defined?(Legion::Logging)
33
34
  []
34
35
  end
35
36
 
@@ -54,7 +55,8 @@ module Legion
54
55
 
55
56
  worker = Legion::Data::Model::DigitalWorker.first(id: id.to_i)
56
57
  worker ? worker_hash(worker.values) : nil
57
- rescue StandardError
58
+ rescue StandardError => e
59
+ Legion::Logging.warn "GraphQL::Workers#find_from_data failed for id=#{id}: #{e.message}" if defined?(Legion::Logging)
58
60
  nil
59
61
  end
60
62
 
@@ -57,7 +57,8 @@ module Legion
57
57
  return {} if body.nil? || body.empty?
58
58
 
59
59
  Legion::JSON.load(body).transform_keys(&:to_sym)
60
- rescue StandardError
60
+ rescue StandardError => e
61
+ Legion::Logging.warn "API#parse_request_body failed to parse JSON: #{e.message}" if defined?(Legion::Logging)
61
62
  halt 400, json_error('invalid_json', 'request body is not valid JSON', status_code: 400)
62
63
  end
63
64
 
@@ -87,7 +88,8 @@ module Legion
87
88
  .select { |klass| klass < base_class }
88
89
  .map { |klass| { name: klass.name } }
89
90
  .sort_by { |h| h[:name].to_s }
90
- rescue NameError
91
+ rescue NameError => e
92
+ Legion::Logging.debug "API#transport_subclasses failed for #{base_class}: #{e.message}" if defined?(Legion::Logging)
91
93
  []
92
94
  end
93
95
 
@@ -12,7 +12,8 @@ module Legion
12
12
  return nil if date_str.nil? || date_str.empty?
13
13
 
14
14
  Date.parse(date_str.to_s)
15
- rescue ArgumentError
15
+ rescue ArgumentError => e
16
+ Legion::Logging.debug "Marketplace#parse_sunset_date invalid date '#{date_str}': #{e.message}" if defined?(Legion::Logging)
16
17
  nil
17
18
  end
18
19
  end
@@ -54,11 +55,12 @@ module Legion
54
55
  end
55
56
  end
56
57
 
57
- def self.register_review_actions(app) # rubocop:disable Metrics/AbcSize
58
+ def self.register_review_actions(app) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
58
59
  app.post '/api/marketplace/:name/submit' do
59
60
  begin
60
61
  Legion::Registry.submit_for_review(params[:name])
61
62
  rescue ArgumentError => e
63
+ Legion::Logging.warn "API POST /api/marketplace/#{params[:name]}/submit: #{e.message}" if defined?(Legion::Logging)
62
64
  halt 404, { 'Content-Type' => 'application/json' },
63
65
  Legion::JSON.dump({ error: { code: 'not_found', message: e.message } })
64
66
  end
@@ -70,6 +72,7 @@ module Legion
70
72
  begin
71
73
  Legion::Registry.approve(params[:name], notes: body[:notes])
72
74
  rescue ArgumentError => e
75
+ Legion::Logging.warn "API POST /api/marketplace/#{params[:name]}/approve: #{e.message}" if defined?(Legion::Logging)
73
76
  halt 404, { 'Content-Type' => 'application/json' },
74
77
  Legion::JSON.dump({ error: { code: 'not_found', message: e.message } })
75
78
  end
@@ -82,6 +85,7 @@ module Legion
82
85
  begin
83
86
  Legion::Registry.reject(params[:name], reason: body[:reason])
84
87
  rescue ArgumentError => e
88
+ Legion::Logging.warn "API POST /api/marketplace/#{params[:name]}/reject: #{e.message}" if defined?(Legion::Logging)
85
89
  halt 404, { 'Content-Type' => 'application/json' },
86
90
  Legion::JSON.dump({ error: { code: 'not_found', message: e.message } })
87
91
  end
@@ -93,12 +97,14 @@ module Legion
93
97
  body = parse_request_body
94
98
  sunset = begin
95
99
  body[:sunset_date] ? Date.parse(body[:sunset_date].to_s) : nil
96
- rescue ArgumentError
100
+ rescue ArgumentError => e
101
+ Legion::Logging.debug "Marketplace#deprecate invalid sunset_date '#{body[:sunset_date]}': #{e.message}" if defined?(Legion::Logging)
97
102
  nil
98
103
  end
99
104
  begin
100
105
  Legion::Registry.deprecate(params[:name], successor: body[:successor], sunset_date: sunset)
101
106
  rescue ArgumentError => e
107
+ Legion::Logging.warn "API POST /api/marketplace/#{params[:name]}/deprecate: #{e.message}" if defined?(Legion::Logging)
102
108
  halt 404, { 'Content-Type' => 'application/json' },
103
109
  Legion::JSON.dump({ error: { code: 'not_found', message: e.message } })
104
110
  end
@@ -107,7 +107,8 @@ module Legion
107
107
  )
108
108
 
109
109
  { claims: claims, output_token: auth_result[:output_token] }
110
- rescue StandardError
110
+ rescue StandardError => e
111
+ Legion::Logging.warn "Auth#verify_negotiate failed: #{e.message}" if defined?(Legion::Logging)
111
112
  nil
112
113
  end
113
114
 
@@ -120,7 +121,8 @@ module Legion
120
121
  return {} unless defined?(Legion::Settings)
121
122
 
122
123
  Legion::Settings.dig(:kerberos, :role_map) || {}
123
- rescue StandardError
124
+ rescue StandardError => e
125
+ Legion::Logging.debug "Auth#kerberos_role_map failed: #{e.message}" if defined?(Legion::Logging)
124
126
  {}
125
127
  end
126
128
 
@@ -128,7 +130,8 @@ module Legion
128
130
  return :entra unless defined?(Legion::Settings)
129
131
 
130
132
  Legion::Settings.dig(:kerberos, :fallback) || :entra
131
- rescue StandardError
133
+ rescue StandardError => e
134
+ Legion::Logging.debug "Auth#kerberos_fallback failed: #{e.message}" if defined?(Legion::Logging)
132
135
  :entra
133
136
  end
134
137
 
@@ -155,7 +158,8 @@ module Legion
155
158
  return nil unless key
156
159
 
157
160
  Legion::Crypt::JWT.verify(token, verification_key: key)
158
- rescue Legion::Crypt::JWT::Error
161
+ rescue Legion::Crypt::JWT::Error => e
162
+ Legion::Logging.debug "Auth#verify_token failed: #{e.message}" if defined?(Legion::Logging)
159
163
  nil
160
164
  end
161
165
 
@@ -168,7 +172,8 @@ module Legion
168
172
  def unauthorized(message)
169
173
  body = Legion::JSON.dump({ error: { code: 401, message: message }, meta: { timestamp: Time.now.utc.iso8601 } })
170
174
  [401, { 'content-type' => 'application/json' }, [body]]
171
- rescue StandardError
175
+ rescue StandardError => e
176
+ Legion::Logging.warn "Auth#unauthorized JSON serialization failed: #{e.message}" if defined?(Legion::Logging)
172
177
  [401, { 'content-type' => 'application/json' }, ["{\"error\":{\"code\":401,\"message\":\"#{message}\"}}"]]
173
178
  end
174
179
  end
@@ -71,7 +71,8 @@ module Legion
71
71
  status, headers, body = @app.call(env)
72
72
  [status, headers.merge(rate_limit_headers(result)), body]
73
73
  end
74
- rescue StandardError
74
+ rescue StandardError => e
75
+ Legion::Logging.warn "RateLimit#call failed, passing through: #{e.message}" if defined?(Legion::Logging)
75
76
  @app.call(env)
76
77
  end
77
78
 
@@ -31,7 +31,8 @@ module Legion
31
31
  end
32
32
  }
33
33
  end
34
- rescue StandardError
34
+ rescue StandardError => e
35
+ Legion::Logging.warn "OrgChart#build_org_chart failed: #{e.message}" if defined?(Legion::Logging)
35
36
  []
36
37
  end
37
38
  end
@@ -17,7 +17,8 @@ module Legion
17
17
  define_method(:prompt_client) do
18
18
  require 'legion/extensions/prompt/client'
19
19
  Legion::Extensions::Prompt::Client.new
20
- rescue LoadError
20
+ rescue LoadError => e
21
+ Legion::Logging.warn "Prompts#prompt_client failed to load lex-prompt: #{e.message}" if defined?(Legion::Logging)
21
22
  halt 503, json_error('prompt_unavailable', 'lex-prompt is not loaded', status_code: 503)
22
23
  end
23
24
  end
@@ -14,17 +14,20 @@ module Legion
14
14
  app.get '/api/transport' do
15
15
  connected = begin
16
16
  Legion::Settings[:transport][:connected]
17
- rescue StandardError
17
+ rescue StandardError => e
18
+ Legion::Logging.debug "Transport#status failed to read connected setting: #{e.message}" if defined?(Legion::Logging)
18
19
  false
19
20
  end
20
21
  session_open = begin
21
22
  Legion::Transport::Connection.session_open?
22
- rescue StandardError
23
+ rescue StandardError => e
24
+ Legion::Logging.debug "Transport#status failed to check session_open: #{e.message}" if defined?(Legion::Logging)
23
25
  false
24
26
  end
25
27
  channel_open = begin
26
28
  Legion::Transport::Connection.channel_open?
27
- rescue StandardError
29
+ rescue StandardError => e
30
+ Legion::Logging.debug "Transport#status failed to check channel_open: #{e.message}" if defined?(Legion::Logging)
28
31
  false
29
32
  end
30
33
  connector = defined?(Legion::Transport::TYPE) ? Legion::Transport::TYPE.to_s : 'unknown'
@@ -36,7 +36,8 @@ module Legion
36
36
  end
37
37
 
38
38
  { nodes: nodes, edges: edges }
39
- rescue StandardError
39
+ rescue StandardError => e
40
+ Legion::Logging.warn "Workflow#build_relationship_graph failed: #{e.message}" if defined?(Legion::Logging)
40
41
  { nodes: [], edges: [] }
41
42
  end
42
43
  end
data/lib/legion/audit.rb CHANGED
@@ -81,7 +81,8 @@ module Legion
81
81
 
82
82
  def node_name
83
83
  Legion::Settings[:client][:hostname]
84
- rescue StandardError
84
+ rescue StandardError => e
85
+ Legion::Logging.debug "Audit#node_name failed to read hostname: #{e.message}" if defined?(Legion::Logging)
85
86
  'unknown'
86
87
  end
87
88
  end
@@ -24,7 +24,8 @@ module Legion
24
24
  return [] unless defined?(Legion::MCP) && Legion::MCP.respond_to?(:tools)
25
25
 
26
26
  Legion::MCP.tools.map { |t| { name: t[:name], description: t[:description] } }
27
- rescue StandardError
27
+ rescue StandardError => e
28
+ Legion::Logging.warn "Catalog#collect_mcp_tools failed: #{e.message}" if defined?(Legion::Logging)
28
29
  []
29
30
  end
30
31
 
@@ -42,6 +43,7 @@ module Legion
42
43
  end
43
44
  { status: response.code.to_i, body: response.body }
44
45
  rescue StandardError => e
46
+ Legion::Logging.warn "Catalog#post_json failed for #{url}: #{e.message}" if defined?(Legion::Logging)
45
47
  { error: e.message }
46
48
  end
47
49
  end
@@ -69,7 +69,8 @@ module Legion
69
69
  def load_patterns
70
70
  custom = begin
71
71
  Legion::Settings.dig(:chat, :notifications, :patterns)
72
- rescue StandardError
72
+ rescue StandardError => e
73
+ Legion::Logging.debug "NotificationBridge#load_patterns failed to read settings: #{e.message}" if defined?(Legion::Logging)
73
74
  nil
74
75
  end
75
76
  return DEFAULT_PATTERNS unless custom
@@ -29,7 +29,8 @@ module Legion
29
29
  def llm_available?
30
30
  require 'legion/llm'
31
31
  true
32
- rescue LoadError
32
+ rescue LoadError => e
33
+ Legion::Logging.debug("AcpCommand#llm_available? legion-llm not available: #{e.message}") if defined?(Legion::Logging)
33
34
  false
34
35
  end
35
36
 
@@ -38,6 +39,7 @@ module Legion
38
39
  Connection.ensure_settings
39
40
  Connection.ensure_llm
40
41
  rescue StandardError => e
42
+ Legion::Logging.warn("AcpCommand#setup_llm failed: #{e.message}") if defined?(Legion::Logging)
41
43
  warn("[lex-acp] LLM setup failed: #{e.message} — running without prompt support")
42
44
  end
43
45
  end
@@ -103,6 +103,7 @@ module Legion
103
103
  response = send_negotiate_request(api_url, token)
104
104
  handle_negotiate_response(response)
105
105
  rescue StandardError => e
106
+ Legion::Logging.error("Auth#kerberos failed: #{e.message}") if defined?(Legion::Logging)
106
107
  say "Kerberos auth error: #{e.message}", :red
107
108
  end
108
109
 
@@ -141,7 +142,12 @@ module Legion
141
142
 
142
143
  def handle_negotiate_response(response)
143
144
  if response.code.to_i == 200
144
- body = ::JSON.parse(response.body) rescue {} # rubocop:disable Style/RescueModifier
145
+ body = begin
146
+ ::JSON.parse(response.body)
147
+ rescue ::JSON::ParserError => e
148
+ Legion::Logging.debug("Auth#handle_negotiate_response JSON parse failed: #{e.message}") if defined?(Legion::Logging)
149
+ {}
150
+ end
145
151
  data = body.is_a?(Hash) ? (body['data'] || body) : {}
146
152
  token_val = data['token']
147
153
  if token_val
@@ -70,7 +70,8 @@ module Legion
70
70
  require 'yaml'
71
71
  YAML.safe_load(content, permitted_classes: [Symbol])
72
72
  end
73
- rescue StandardError
73
+ rescue StandardError => e
74
+ Legion::Logging.debug("AgentRegistry#parse_file failed for #{path}: #{e.message}") if defined?(Legion::Logging)
74
75
  nil
75
76
  end
76
77
 
@@ -107,7 +107,8 @@ module Legion
107
107
  safe_name = entry.path.gsub('/', '_').gsub('\\', '_')
108
108
  backup_path = File.join(storage_dir, "#{@entries.length}_#{safe_name}")
109
109
  File.write(backup_path, entry.content, encoding: 'utf-8')
110
- rescue StandardError
110
+ rescue StandardError => e
111
+ Legion::Logging.warn("Checkpoint#persist_entry failed for #{entry.path}: #{e.message}") if defined?(Legion::Logging)
111
112
  # In-memory fallback is always available via @entries
112
113
  nil
113
114
  end
@@ -117,7 +118,8 @@ module Legion
117
118
 
118
119
  FileUtils.rm_rf(@storage_dir)
119
120
  @storage_dir = nil
120
- rescue StandardError
121
+ rescue StandardError => e
122
+ Legion::Logging.warn("Checkpoint#cleanup_storage failed: #{e.message}") if defined?(Legion::Logging)
121
123
  nil
122
124
  end
123
125
  end
@@ -54,8 +54,8 @@ module Legion
54
54
  end
55
55
  parts << "Extension tools available: #{ext_names.join(', ')}"
56
56
  end
57
- rescue LoadError
58
- # ExtensionToolLoader not available, skip
57
+ rescue LoadError => e
58
+ Legion::Logging.debug("Context#to_system_prompt ExtensionToolLoader not available: #{e.message}") if defined?(Legion::Logging)
59
59
  end
60
60
 
61
61
  extra_dirs.each do |dir|
@@ -99,7 +99,8 @@ module Legion
99
99
 
100
100
  output = `cd #{Shellwords.escape(dir)} && git status --porcelain 2>/dev/null`
101
101
  !output.strip.empty?
102
- rescue StandardError
102
+ rescue StandardError => e
103
+ Legion::Logging.debug("Context#detect_git_dirty failed: #{e.message}") if defined?(Legion::Logging)
103
104
  false
104
105
  end
105
106
 
@@ -51,7 +51,8 @@ module Legion
51
51
  return nil unless defined?(Legion::Settings)
52
52
 
53
53
  Legion::Settings[:extensions]&.[](extension_name.to_sym)
54
- rescue StandardError
54
+ rescue StandardError => e
55
+ Legion::Logging.warn("ExtensionToolLoader#extension_settings failed for #{extension_name}: #{e.message}") if defined?(Legion::Logging)
55
56
  nil
56
57
  end
57
58
 
@@ -82,7 +83,8 @@ module Legion
82
83
  gem_spec = Gem::Specification.find_by_name(info[:gem_name])
83
84
  ext_path = "#{gem_spec.gem_dir}/lib/legion/extensions/#{name}"
84
85
  [name, ext_path]
85
- rescue Gem::MissingSpecError
86
+ rescue Gem::MissingSpecError => e
87
+ Legion::Logging.debug("ExtensionToolLoader#loaded_extension_paths gem not found for #{name}: #{e.message}") if defined?(Legion::Logging)
86
88
  nil
87
89
  end&.compact || []
88
90
  end