legion-tty 0.4.29 → 0.4.30

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: 6f5fae7ebc821ab002ba505d7570c4b3116cd8cb9ebe2fe663aa63e93c5e459e
4
- data.tar.gz: 127da7a51afc0eb408b63dbc32c6c0df7971fc767938a5e2d6ac6c435e6742ae
3
+ metadata.gz: f37085f25b964517a88988f6780ae8d60257356d53d3021567a4f9f0bc43f400
4
+ data.tar.gz: d1b150a3993d20e92eb30d778bbd4fe79c75582ec3ad893668879d5abc70ae76
5
5
  SHA512:
6
- metadata.gz: 97c6604bd14b08983fb7f189be0150e111b69d59b5d55ce0768f72b5fa8612f596979979aed0e2c93a93461c56cfbcb9b37bf1938b8f6a9c41054470331acbcb
7
- data.tar.gz: 36630d28f144a4c15fa08ac9a93f476161be4dc6dc42bc0045cabef31a5e1cfeb11ec01e80875cfb4d628735951bc42d90203959505faed4cf44b03429291bae
6
+ metadata.gz: 810a96e9a0f5a0487e3e39c9d895166f7e04810d63e27ba8ed1761520720c2cdd48755784ebbcedeb88d4e26e4686297ea4ef92777465689ed89423653f07f41
7
+ data.tar.gz: 4be0e4271d6a04f430be490e54952a013f9dce0e5269f9a1211a1437d9124dbd4401887150f0a105b949a3d26f82471e3da5faf69c0384950e2b3cdd690e3c6a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.30] - 2026-03-22
4
+
5
+ ### Fixed
6
+ - Add `Legion::Logging.debug/warn` to all previously silent rescue blocks across lib/ files
7
+ - Add rubocop disable/enable directives for Metrics cops on methods whose complexity increased from logging additions
8
+
3
9
  ## [0.4.29] - 2026-03-20
4
10
 
5
11
  ### Fixed
@@ -19,7 +19,8 @@ module Legion
19
19
  opts = parse_argv(argv)
20
20
  app = new(**opts)
21
21
  app.start
22
- rescue Interrupt
22
+ rescue Interrupt => e
23
+ Legion::Logging.debug("app interrupted: #{e.message}") if defined?(Legion::Logging)
23
24
  app&.shutdown
24
25
  end
25
26
 
@@ -91,7 +92,8 @@ module Legion
91
92
  def setup_llm
92
93
  boot_legion_subsystems
93
94
  @llm_chat = try_settings_llm
94
- rescue StandardError
95
+ rescue StandardError => e
96
+ Legion::Logging.warn("setup_llm failed: #{e.message}") if defined?(Legion::Logging)
95
97
  @llm_chat = nil
96
98
  end
97
99
 
@@ -113,7 +115,8 @@ module Legion
113
115
  }.compact
114
116
  File.write(identity_path, ::JSON.generate(identity))
115
117
  @config = load_config
116
- rescue StandardError
118
+ rescue StandardError => e
119
+ Legion::Logging.warn("rescan_environment failed: #{e.message}") if defined?(Legion::Logging)
117
120
  nil
118
121
  end
119
122
  end
@@ -132,6 +135,7 @@ module Legion
132
135
 
133
136
  private
134
137
 
138
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
135
139
  def boot_legion_subsystems
136
140
  # Follow the same init order as Legion::Service:
137
141
  # 1. logging 2. settings 3. crypt 4. resolve secrets 5. LLM merge
@@ -148,19 +152,26 @@ module Legion
148
152
  require 'legion/crypt'
149
153
  Legion::Crypt.start unless Legion::Crypt.instance_variable_get(:@started)
150
154
  Legion::Settings.resolve_secrets! if Legion::Settings.respond_to?(:resolve_secrets!)
151
- rescue LoadError, StandardError
155
+ rescue LoadError => e
156
+ Legion::Logging.debug("legion/crypt not available: #{e.message}") if defined?(Legion::Logging)
157
+ nil
158
+ rescue StandardError => e
159
+ Legion::Logging.warn("crypt/secrets setup failed: #{e.message}") if defined?(Legion::Logging)
152
160
  nil
153
161
  end
154
162
 
155
163
  begin
156
164
  require 'legion/llm'
157
165
  Legion::Settings.merge_settings(:llm, Legion::LLM::Settings.default)
158
- rescue LoadError
166
+ rescue LoadError => e
167
+ Legion::Logging.debug("legion/llm not available: #{e.message}") if defined?(Legion::Logging)
159
168
  nil
160
169
  end
161
- rescue LoadError
170
+ rescue LoadError => e
171
+ Legion::Logging.debug("legion subsystem load failed: #{e.message}") if defined?(Legion::Logging)
162
172
  nil
163
173
  end
174
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
164
175
 
165
176
  def settings_search_path
166
177
  [
@@ -181,7 +192,8 @@ module Legion
181
192
  return nil unless provider
182
193
 
183
194
  Legion::LLM.chat(provider: provider)
184
- rescue StandardError
195
+ rescue StandardError => e
196
+ Legion::Logging.warn("try_settings_llm failed: #{e.message}") if defined?(Legion::Logging)
185
197
  nil
186
198
  end
187
199
 
@@ -246,7 +258,8 @@ module Legion
246
258
  return {} unless File.exist?(path)
247
259
 
248
260
  deep_symbolize(::JSON.parse(File.read(path)))
249
- rescue ::JSON::ParserError, Errno::ENOENT
261
+ rescue ::JSON::ParserError, Errno::ENOENT => e
262
+ Legion::Logging.warn("load_credentials failed: #{e.message}") if defined?(Legion::Logging)
250
263
  {}
251
264
  end
252
265
 
@@ -262,7 +275,8 @@ module Legion
262
275
  return {} unless File.exist?(path)
263
276
 
264
277
  deep_symbolize(::JSON.parse(File.read(path)))
265
- rescue ::JSON::ParserError, Errno::ENOENT
278
+ rescue ::JSON::ParserError, Errno::ENOENT => e
279
+ Legion::Logging.warn("load_config failed: #{e.message}") if defined?(Legion::Logging)
266
280
  {}
267
281
  end
268
282
 
@@ -104,7 +104,8 @@ module Legion
104
104
  return 0 unless data.is_a?(Hash)
105
105
 
106
106
  data['total_count'] || 0
107
- rescue StandardError
107
+ rescue StandardError => e
108
+ Legion::Logging.debug("count_commits failed: #{e.message}") if defined?(Legion::Logging)
108
109
  0
109
110
  end
110
111
 
@@ -326,7 +327,8 @@ module Legion
326
327
  http = build_http(uri)
327
328
  response = http.request(build_request(uri))
328
329
  ::JSON.parse(response.body)
329
- rescue StandardError
330
+ rescue StandardError => e
331
+ Legion::Logging.debug("api_get failed: #{e.message}") if defined?(Legion::Logging)
330
332
  nil
331
333
  end
332
334
 
@@ -53,6 +53,7 @@ module Legion
53
53
  { name: name, model: model, status: :ok, latency_ms: latency }
54
54
  rescue StandardError => e
55
55
  latency = ((Time.now - start_time) * 1000).round
56
+ Legion::Logging.debug("ping_provider #{name} failed: #{e.message}") if defined?(Legion::Logging)
56
57
  { name: name, model: model, status: :error, latency_ms: latency, error: e.message }
57
58
  end
58
59
  end
@@ -89,10 +89,12 @@ module Legion
89
89
 
90
90
  def port_open?(host, port)
91
91
  ::Socket.tcp(host, port, connect_timeout: 1) { true }
92
- rescue StandardError
92
+ rescue StandardError => e
93
+ Legion::Logging.debug("port_open? #{host}:#{port} failed: #{e.message}") if defined?(Legion::Logging)
93
94
  false
94
95
  end
95
96
 
97
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
96
98
  def collect_repos(base, depth = 0)
97
99
  return [] unless File.directory?(base)
98
100
  return [build_repo_entry(base)] if File.directory?(File.join(base, '.git'))
@@ -103,12 +105,15 @@ module Legion
103
105
 
104
106
  child_path = File.join(base, child)
105
107
  acc.concat(collect_repos(child_path, depth + 1)) if File.directory?(child_path)
106
- rescue StandardError
108
+ rescue StandardError => e
109
+ Legion::Logging.debug("collect_repos child failed: #{e.message}") if defined?(Legion::Logging)
107
110
  next
108
111
  end
109
- rescue StandardError
112
+ rescue StandardError => e
113
+ Legion::Logging.debug("collect_repos failed: #{e.message}") if defined?(Legion::Logging)
110
114
  []
111
115
  end
116
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
112
117
 
113
118
  def build_repo_entry(path)
114
119
  { path: path, name: File.basename(path), remote: git_remote(path),
@@ -118,14 +123,16 @@ module Legion
118
123
  def git_remote(path)
119
124
  out = `git -C #{path.shellescape} remote get-url origin 2>/dev/null`.strip
120
125
  out.empty? ? nil : out
121
- rescue StandardError
126
+ rescue StandardError => e
127
+ Legion::Logging.debug("git_remote failed: #{e.message}") if defined?(Legion::Logging)
122
128
  nil
123
129
  end
124
130
 
125
131
  def git_branch(path)
126
132
  out = `git -C #{path.shellescape} rev-parse --abbrev-ref HEAD 2>/dev/null`.strip
127
133
  out.empty? ? nil : out
128
- rescue StandardError
134
+ rescue StandardError => e
135
+ Legion::Logging.debug("git_branch failed: #{e.message}") if defined?(Legion::Logging)
129
136
  nil
130
137
  end
131
138
 
@@ -144,7 +151,8 @@ module Legion
144
151
  next [] unless File.exist?(full)
145
152
 
146
153
  File.readlines(full, encoding: 'utf-8', chomp: true).last(500)
147
- rescue StandardError
154
+ rescue StandardError => e
155
+ Legion::Logging.debug("read_history_lines failed for #{path}: #{e.message}") if defined?(Legion::Logging)
148
156
  []
149
157
  end
150
158
  end
@@ -169,7 +177,8 @@ module Legion
169
177
  result = { name: name.empty? ? nil : name, email: email.empty? ? nil : email }
170
178
  result[:signing_key] = signing_key unless signing_key.empty?
171
179
  result
172
- rescue StandardError
180
+ rescue StandardError => e
181
+ Legion::Logging.debug("scan_gitconfig failed: #{e.message}") if defined?(Legion::Logging)
173
182
  nil
174
183
  end
175
184
 
@@ -185,7 +194,8 @@ module Legion
185
194
  servers.map do |s|
186
195
  { server_id: s[:serverId], url: s[:url], user: s[:user] }
187
196
  end
188
- rescue StandardError
197
+ rescue StandardError => e
198
+ Legion::Logging.debug("scan_jfrog failed: #{e.message}") if defined?(Legion::Logging)
189
199
  nil
190
200
  end
191
201
 
@@ -199,7 +209,8 @@ module Legion
199
209
  return nil if hosts.empty?
200
210
 
201
211
  { hosts: hosts.map(&:to_s) }
202
- rescue StandardError
212
+ rescue StandardError => e
213
+ Legion::Logging.debug("scan_terraform failed: #{e.message}") if defined?(Legion::Logging)
203
214
  nil
204
215
  end
205
216
  end
@@ -35,7 +35,8 @@ module Legion
35
35
  prompt = ::TTY::Prompt.new(output: output)
36
36
  choices = entries.map { |e| { name: "#{e[:label]} (#{e[:category]})", value: e[:label] } }
37
37
  prompt.select('Command:', choices, filter: true, per_page: 15)
38
- rescue ::TTY::Reader::InputInterrupt, Interrupt
38
+ rescue ::TTY::Reader::InputInterrupt, Interrupt => e
39
+ Legion::Logging.debug("command palette cancelled: #{e.message}") if defined?(Legion::Logging)
39
40
  nil
40
41
  end
41
42
  end
@@ -39,7 +39,8 @@ module Legion
39
39
  gems = Gem::Specification.select { |s| s.name.start_with?('lex-') }
40
40
  .map { |s| s.name.sub(/^lex-/, '') }
41
41
  gems.empty? ? FALLBACK_NAMES : gems
42
- rescue StandardError
42
+ rescue StandardError => e
43
+ Legion::Logging.debug("extension_names failed: #{e.message}") if defined?(Legion::Logging)
43
44
  FALLBACK_NAMES
44
45
  end
45
46
 
@@ -54,7 +54,8 @@ module Legion
54
54
  reader = ::TTY::Reader.new(history_cycle: true)
55
55
  register_tab_completion(reader)
56
56
  reader
57
- rescue LoadError
57
+ rescue LoadError => e
58
+ Legion::Logging.debug("tty-reader not available: #{e.message}") if defined?(Legion::Logging)
58
59
  nil
59
60
  end
60
61
 
@@ -9,6 +9,7 @@ module Legion
9
9
  def self.render(text, width: 80)
10
10
  ::TTY::Markdown.parse(text, width: width)
11
11
  rescue StandardError => e
12
+ Legion::Logging.warn("markdown render failed: #{e.message}") if defined?(Legion::Logging)
12
13
  "#{text}\n(markdown render error: #{e.message})"
13
14
  end
14
15
  end
@@ -182,7 +182,8 @@ module Legion
182
182
  def render_markdown(text, width)
183
183
  require_relative 'markdown_view'
184
184
  MarkdownView.render(text, width: width)
185
- rescue StandardError
185
+ rescue StandardError => e
186
+ Legion::Logging.warn("render_markdown failed: #{e.message}") if defined?(Legion::Logging)
186
187
  text
187
188
  end
188
189
 
@@ -206,7 +207,8 @@ module Legion
206
207
  @highlights.reduce(text) do |result, pattern|
207
208
  result.gsub(pattern) { "#{HIGHLIGHT_COLOR}#{$LAST_MATCH_INFO}#{HIGHLIGHT_RESET}" }
208
209
  end
209
- rescue StandardError
210
+ rescue StandardError => e
211
+ Legion::Logging.warn("apply_highlights failed: #{e.message}") if defined?(Legion::Logging)
210
212
  text
211
213
  end
212
214
 
@@ -37,7 +37,8 @@ module Legion
37
37
  { name: "#{m[:provider]} / #{m[:model]}#{indicator}", value: m }
38
38
  end
39
39
  prompt.select('Select model:', choices, per_page: 10)
40
- rescue ::TTY::Reader::InputInterrupt, Interrupt
40
+ rescue ::TTY::Reader::InputInterrupt, Interrupt => e
41
+ Legion::Logging.debug("model picker cancelled: #{e.message}") if defined?(Legion::Logging)
41
42
  nil
42
43
  end
43
44
  end
@@ -61,7 +61,8 @@ module Legion
61
61
  output: @output,
62
62
  width: 40
63
63
  )
64
- rescue LoadError
64
+ rescue LoadError => e
65
+ Legion::Logging.debug("tty-progressbar not available: #{e.message}") if defined?(Legion::Logging)
65
66
  nil
66
67
  end
67
68
  end
@@ -19,7 +19,8 @@ module Legion
19
19
  end
20
20
  choices << { name: '+ New session', value: :new }
21
21
  prompt.select('Select session:', choices, per_page: 10)
22
- rescue ::TTY::Reader::InputInterrupt, Interrupt
22
+ rescue ::TTY::Reader::InputInterrupt, Interrupt => e
23
+ Legion::Logging.debug("session picker cancelled: #{e.message}") if defined?(Legion::Logging)
23
24
  nil
24
25
  end
25
26
  end
@@ -9,6 +9,7 @@ module Legion
9
9
  table = ::TTY::Table.new(header: headers, rows: rows)
10
10
  table.render(:unicode, width: width, padding: [0, 1]) || ''
11
11
  rescue StandardError => e
12
+ Legion::Logging.warn("table render failed: #{e.message}") if defined?(Legion::Logging)
12
13
  "Table render error: #{e.message}"
13
14
  end
14
15
  end
@@ -96,7 +96,8 @@ module Legion
96
96
  end
97
97
 
98
98
  @on_tool_call.call(name: name, args: args)
99
- rescue StandardError
99
+ rescue StandardError => e
100
+ Legion::Logging.warn("emit_tool_call failed: #{e.message}") if defined?(Legion::Logging)
100
101
  @on_text.call("#{OPEN_TAG}#{json_str}#{CLOSE_TAG}")
101
102
  end
102
103
 
@@ -24,7 +24,8 @@ module Legion
24
24
  http.get(uri.path)
25
25
  end
26
26
  response.code.to_i == 200
27
- rescue StandardError
27
+ rescue StandardError => e
28
+ Legion::Logging.debug("daemon available? check failed: #{e.message}") if defined?(Legion::Logging)
28
29
  false
29
30
  end
30
31
 
@@ -39,7 +40,8 @@ module Legion
39
40
  @manifest = body[:data]
40
41
  write_cache(@manifest)
41
42
  @manifest
42
- rescue StandardError
43
+ rescue StandardError => e
44
+ Legion::Logging.warn("fetch_manifest failed: #{e.message}") if defined?(Legion::Logging)
43
45
  nil
44
46
  end
45
47
 
@@ -49,7 +51,8 @@ module Legion
49
51
  return nil unless @cache_file && File.exist?(@cache_file)
50
52
 
51
53
  @manifest = Legion::JSON.load(File.read(@cache_file))
52
- rescue StandardError
54
+ rescue StandardError => e
55
+ Legion::Logging.warn("cached_manifest failed: #{e.message}") if defined?(Legion::Logging)
53
56
  nil
54
57
  end
55
58
 
@@ -81,7 +84,8 @@ module Legion
81
84
  return nil unless response && SUCCESS_CODES.include?(response.code.to_i)
82
85
 
83
86
  Legion::JSON.load(response.body)
84
- rescue StandardError
87
+ rescue StandardError => e
88
+ Legion::Logging.warn("chat failed: #{e.message}") if defined?(Legion::Logging)
85
89
  nil
86
90
  end
87
91
 
@@ -110,7 +114,8 @@ module Legion
110
114
 
111
115
  FileUtils.mkdir_p(File.dirname(@cache_file))
112
116
  File.write(@cache_file, Legion::JSON.dump(data))
113
- rescue StandardError
117
+ rescue StandardError => e
118
+ Legion::Logging.warn("write_cache failed: #{e.message}") if defined?(Legion::Logging)
114
119
  nil
115
120
  end
116
121
  end
@@ -15,6 +15,7 @@ module Legion
15
15
  @message_stream.add_message(role: :system, content: "Exported to: #{path}")
16
16
  :handled
17
17
  rescue StandardError => e
18
+ Legion::Logging.warn("handle_export failed: #{e.message}") if defined?(Legion::Logging)
18
19
  @message_stream.add_message(role: :system, content: "Export failed: #{e.message}")
19
20
  :handled
20
21
  end
@@ -128,6 +129,7 @@ module Legion
128
129
  @message_stream.add_message(role: :system, content: "Bookmarks exported to: #{path}")
129
130
  :handled
130
131
  rescue StandardError => e
132
+ Legion::Logging.warn("handle_bookmark failed: #{e.message}") if defined?(Legion::Logging)
131
133
  @message_stream.add_message(role: :system, content: "Bookmark export failed: #{e.message}")
132
134
  :handled
133
135
  end
@@ -150,6 +152,7 @@ module Legion
150
152
  end
151
153
  :handled
152
154
  rescue StandardError => e
155
+ Legion::Logging.warn("handle_tee failed: #{e.message}") if defined?(Legion::Logging)
153
156
  @message_stream.add_message(role: :system, content: "Tee error: #{e.message}")
154
157
  :handled
155
158
  end
@@ -158,7 +161,8 @@ module Legion
158
161
  return unless @tee_path
159
162
 
160
163
  File.open(@tee_path, 'a') { |f| f.puts(line) }
161
- rescue StandardError
164
+ rescue StandardError => e
165
+ Legion::Logging.warn("tee_message failed: #{e.message}") if defined?(Legion::Logging)
162
166
  nil
163
167
  end
164
168
  end
@@ -98,6 +98,7 @@ module Legion
98
98
  display_grep_results(results, pattern_str)
99
99
  :handled
100
100
  rescue RegexpError => e
101
+ Legion::Logging.warn("handle_grep regex error: #{e.message}") if defined?(Legion::Logging)
101
102
  @message_stream.add_message(role: :system, content: "Invalid regex: #{e.message}")
102
103
  :handled
103
104
  end
@@ -300,10 +301,12 @@ module Legion
300
301
 
301
302
  def copy_to_clipboard(text)
302
303
  IO.popen('pbcopy', 'w') { |io| io.write(text) }
303
- rescue Errno::ENOENT
304
+ rescue Errno::ENOENT => e
305
+ Legion::Logging.debug("pbcopy not available: #{e.message}") if defined?(Legion::Logging)
304
306
  begin
305
307
  IO.popen('xclip -selection clipboard', 'w') { |io| io.write(text) }
306
- rescue Errno::ENOENT
308
+ rescue Errno::ENOENT => e
309
+ Legion::Logging.debug("xclip not available: #{e.message}") if defined?(Legion::Logging)
307
310
  nil
308
311
  end
309
312
  end
@@ -394,7 +397,8 @@ module Legion
394
397
  raw = File.read(favorites_file)
395
398
  parsed = ::JSON.parse(raw, symbolize_names: true)
396
399
  parsed.is_a?(Array) ? parsed : []
397
- rescue StandardError
400
+ rescue StandardError => e
401
+ Legion::Logging.warn("load_favorites failed: #{e.message}") if defined?(Legion::Logging)
398
402
  []
399
403
  end
400
404
 
@@ -25,6 +25,7 @@ module Legion
25
25
 
26
26
  apply_model_switch(name)
27
27
  rescue StandardError => e
28
+ Legion::Logging.warn("switch_model failed: #{e.message}") if defined?(Legion::Logging)
28
29
  @message_stream.add_message(role: :system, content: "Failed to switch model: #{e.message}")
29
30
  end
30
31
 
@@ -53,7 +54,8 @@ module Legion
53
54
  return nil unless providers.is_a?(Hash) && providers.key?(name.to_sym)
54
55
 
55
56
  Legion::LLM.chat(provider: name)
56
- rescue StandardError
57
+ rescue StandardError => e
58
+ Legion::Logging.warn("try_provider_switch failed: #{e.message}") if defined?(Legion::Logging)
57
59
  nil
58
60
  end
59
61
 
@@ -141,7 +141,8 @@ module Legion
141
141
  auto_save_session
142
142
  @last_autosave = Time.now
143
143
  @status_bar.notify(message: 'Autosaved', level: :info, ttl: 2)
144
- rescue StandardError
144
+ rescue StandardError => e
145
+ Legion::Logging.warn("check_autosave failed: #{e.message}") if defined?(Legion::Logging)
145
146
  nil
146
147
  end
147
148
 
@@ -152,7 +153,8 @@ module Legion
152
153
  @session_name = @session_store.auto_session_name(messages: @message_stream.messages)
153
154
  end
154
155
  @session_store.save(@session_name, messages: @message_stream.messages)
155
- rescue StandardError
156
+ rescue StandardError => e
157
+ Legion::Logging.warn("auto_save_session failed: #{e.message}") if defined?(Legion::Logging)
156
158
  nil
157
159
  end
158
160
 
@@ -102,7 +102,8 @@ module Legion
102
102
  screen = Screens::Extensions.new(@app, output: @output)
103
103
  @app.screen_manager.push(screen)
104
104
  :handled
105
- rescue LoadError
105
+ rescue LoadError => e
106
+ Legion::Logging.debug("extensions screen not available: #{e.message}") if defined?(Legion::Logging)
106
107
  @message_stream.add_message(role: :system, content: 'Extensions screen not available.')
107
108
  :handled
108
109
  end
@@ -112,7 +113,8 @@ module Legion
112
113
  screen = Screens::Config.new(@app, output: @output)
113
114
  @app.screen_manager.push(screen)
114
115
  :handled
115
- rescue LoadError
116
+ rescue LoadError => e
117
+ Legion::Logging.debug("config screen not available: #{e.message}") if defined?(Legion::Logging)
116
118
  @message_stream.add_message(role: :system, content: 'Config screen not available.')
117
119
  :handled
118
120
  end
@@ -479,6 +481,7 @@ module Legion
479
481
  @message_stream.add_message(role: :system, content: "= #{result}")
480
482
  :handled
481
483
  rescue SyntaxError, ZeroDivisionError, Math::DomainError => e
484
+ Legion::Logging.warn("handle_calc error: #{e.message}") if defined?(Legion::Logging)
482
485
  @message_stream.add_message(role: :system, content: "Error: #{e.message}")
483
486
  :handled
484
487
  end
@@ -641,6 +644,7 @@ module Legion
641
644
  end
642
645
  result.to_s.chomp
643
646
  rescue StandardError => e
647
+ Legion::Logging.warn("pipe_through_command failed: #{e.message}") if defined?(Legion::Logging)
644
648
  raise "command failed: #{e.message}"
645
649
  end
646
650
 
@@ -652,6 +656,7 @@ module Legion
652
656
  @message_stream.add_message(role: :system, content: "#{path}:\n#{entries.join("\n")}")
653
657
  :handled
654
658
  rescue Errno::ENOENT, Errno::EACCES => e
659
+ Legion::Logging.warn("handle_ls failed: #{e.message}") if defined?(Legion::Logging)
655
660
  @message_stream.add_message(role: :system, content: "ls: #{e.message}")
656
661
  :handled
657
662
  end
@@ -837,7 +842,8 @@ module Legion
837
842
 
838
843
  require 'json'
839
844
  ::JSON.parse(File.read(prefs_path))
840
- rescue ::JSON::ParserError
845
+ rescue ::JSON::ParserError => e
846
+ Legion::Logging.warn("load_prefs failed: #{e.message}") if defined?(Legion::Logging)
841
847
  {}
842
848
  end
843
849
 
@@ -194,6 +194,7 @@ module Legion
194
194
  send_via_direct(message)
195
195
  end
196
196
  rescue StandardError => e
197
+ Legion::Logging.error("send_to_llm failed: #{e.message}") if defined?(Legion::Logging)
197
198
  @status_bar.update(thinking: false)
198
199
  @message_stream.append_streaming("\n[Error: #{e.message}]")
199
200
  end
@@ -268,7 +269,8 @@ module Legion
268
269
  else
269
270
  send_via_direct(message)
270
271
  end
271
- rescue StandardError
272
+ rescue StandardError => e
273
+ Legion::Logging.warn("send_via_daemon failed: #{e.message}") if defined?(Legion::Logging)
272
274
  send_via_direct(message)
273
275
  end
274
276
 
@@ -301,7 +303,8 @@ module Legion
301
303
  return unless RUBY_PLATFORM =~ /darwin/
302
304
 
303
305
  ::Process.spawn('say', text[0..500], err: '/dev/null', out: '/dev/null')
304
- rescue StandardError
306
+ rescue StandardError => e
307
+ Legion::Logging.debug("speak_response failed: #{e.message}") if defined?(Legion::Logging)
305
308
  nil
306
309
  end
307
310
 
@@ -383,7 +386,8 @@ module Legion
383
386
  @output.print ::TTY::Cursor.move_to(2, start_row + i)
384
387
  @output.print line
385
388
  end
386
- rescue StandardError
389
+ rescue StandardError => e
390
+ Legion::Logging.warn("render_overlay failed: #{e.message}") if defined?(Legion::Logging)
387
391
  nil
388
392
  end
389
393
  # rubocop:enable Metrics/AbcSize
@@ -393,7 +397,8 @@ module Legion
393
397
  return read_multiline_input if @multiline_mode
394
398
 
395
399
  @input_bar.read_line
396
- rescue Interrupt
400
+ rescue Interrupt => e
401
+ Legion::Logging.debug("read_input interrupted: #{e.message}") if defined?(Legion::Logging)
397
402
  nil
398
403
  end
399
404
 
@@ -407,7 +412,8 @@ module Legion
407
412
  lines << line
408
413
  end
409
414
  lines.empty? ? nil : lines.join("\n")
410
- rescue Interrupt
415
+ rescue Interrupt => e
416
+ Legion::Logging.debug("read_multiline_input interrupted: #{e.message}") if defined?(Legion::Logging)
411
417
  nil
412
418
  end
413
419
 
@@ -644,14 +650,16 @@ module Legion
644
650
  def terminal_width
645
651
  require 'tty-screen'
646
652
  ::TTY::Screen.width
647
- rescue StandardError
653
+ rescue StandardError => e
654
+ Legion::Logging.debug("terminal_width failed: #{e.message}") if defined?(Legion::Logging)
648
655
  80
649
656
  end
650
657
 
651
658
  def terminal_height
652
659
  require 'tty-screen'
653
660
  ::TTY::Screen.height
654
- rescue StandardError
661
+ rescue StandardError => e
662
+ Legion::Logging.debug("terminal_height failed: #{e.message}") if defined?(Legion::Logging)
655
663
  24
656
664
  end
657
665
 
@@ -100,7 +100,8 @@ module Legion
100
100
  @file_data = ::JSON.parse(File.read(path))
101
101
  @viewing_file = true
102
102
  @selected_key = 0
103
- rescue ::JSON::ParserError, Errno::ENOENT
103
+ rescue ::JSON::ParserError, Errno::ENOENT => e
104
+ Legion::Logging.warn("open_file failed: #{e.message}") if defined?(Legion::Logging)
104
105
  @file_data = { 'error' => 'Failed to parse file' }
105
106
  @viewing_file = true
106
107
  end
@@ -123,7 +124,8 @@ module Legion
123
124
  return unless validate_config(@file_data)
124
125
 
125
126
  save_current_file
126
- rescue ::TTY::Reader::InputInterrupt, Interrupt
127
+ rescue ::TTY::Reader::InputInterrupt, Interrupt => e
128
+ Legion::Logging.debug("edit_selected_key cancelled: #{e.message}") if defined?(Legion::Logging)
127
129
  nil
128
130
  end
129
131
 
@@ -131,6 +133,7 @@ module Legion
131
133
  ::JSON.generate(data)
132
134
  true
133
135
  rescue StandardError => e
136
+ Legion::Logging.warn("validate_config failed: #{e.message}") if defined?(Legion::Logging)
134
137
  @messages = ["Invalid JSON: #{e.message}"]
135
138
  false
136
139
  end
@@ -215,11 +215,12 @@ module Legion
215
215
  else
216
216
  :pass
217
217
  end
218
- rescue LoadError, StandardError
218
+ rescue LoadError, StandardError => e
219
+ Legion::Logging.debug("extensions_shortcut failed: #{e.message}") if defined?(Legion::Logging)
219
220
  :pass
220
221
  end
221
222
 
222
- # rubocop:disable Metrics/AbcSize
223
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
223
224
  def llm_info
224
225
  info = { provider: 'none', model: nil, started: false, daemon: false }
225
226
  if defined?(Legion::LLM)
@@ -233,11 +234,12 @@ module Legion
233
234
  Legion::LLM::DaemonClient.available?
234
235
  end
235
236
  info
236
- rescue StandardError
237
+ rescue StandardError => e
238
+ Legion::Logging.warn("llm_info failed: #{e.message}") if defined?(Legion::Logging)
237
239
  info
238
240
  end
239
241
 
240
- # rubocop:enable Metrics/AbcSize
242
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
241
243
 
242
244
  def probe_services
243
245
  require 'socket'
@@ -252,13 +254,15 @@ module Legion
252
254
 
253
255
  def port_open?(port)
254
256
  ::Socket.tcp('127.0.0.1', port, connect_timeout: 0.5) { true }
255
- rescue StandardError
257
+ rescue StandardError => e
258
+ Legion::Logging.debug("port_open? #{port} failed: #{e.message}") if defined?(Legion::Logging)
256
259
  false
257
260
  end
258
261
 
259
262
  def discover_extensions
260
263
  Gem::Specification.select { |s| s.name.start_with?('lex-') }.map(&:name).sort
261
- rescue StandardError
264
+ rescue StandardError => e
265
+ Legion::Logging.warn("discover_extensions failed: #{e.message}") if defined?(Legion::Logging)
262
266
  []
263
267
  end
264
268
 
@@ -270,7 +274,8 @@ module Legion
270
274
  pid: ::Process.pid,
271
275
  memory: format_memory
272
276
  }
273
- rescue StandardError
277
+ rescue StandardError => e
278
+ Legion::Logging.warn("system_info failed: #{e.message}") if defined?(Legion::Logging)
274
279
  {}
275
280
  end
276
281
 
@@ -283,7 +288,8 @@ module Legion
283
288
  rss_kb = match ? match[1].to_i : 0
284
289
  "#{(rss_kb / 1024.0).round(1)} MB"
285
290
  end
286
- rescue StandardError
291
+ rescue StandardError => e
292
+ Legion::Logging.debug("format_memory failed: #{e.message}") if defined?(Legion::Logging)
287
293
  'unknown'
288
294
  end
289
295
 
@@ -292,7 +298,8 @@ module Legion
292
298
  return [] unless File.exist?(log_path)
293
299
 
294
300
  File.readlines(log_path, chomp: true).last(20)
295
- rescue StandardError
301
+ rescue StandardError => e
302
+ Legion::Logging.warn("recent_activity failed: #{e.message}") if defined?(Legion::Logging)
296
303
  []
297
304
  end
298
305
  end
@@ -171,7 +171,8 @@ module Legion
171
171
  return unless entry && entry[:homepage]
172
172
 
173
173
  system_open(entry[:homepage])
174
- rescue StandardError
174
+ rescue StandardError => e
175
+ Legion::Logging.warn("open_homepage failed: #{e.message}") if defined?(Legion::Logging)
175
176
  nil
176
177
  end
177
178
 
@@ -359,14 +359,16 @@ module Legion
359
359
 
360
360
  results = detect_result[:data] || []
361
361
  results.any? { |d| d[:name] == 'Microsoft Teams' }
362
- rescue StandardError
362
+ rescue StandardError => e
363
+ Legion::Logging.debug("teams_detected? failed: #{e.message}") if defined?(Legion::Logging)
363
364
  false
364
365
  end
365
366
 
366
367
  def teams_gem_loadable?
367
368
  Gem::Specification.find_by_name('lex-microsoft_teams')
368
369
  true
369
- rescue Gem::MissingSpecError
370
+ rescue Gem::MissingSpecError => e
371
+ Legion::Logging.debug("lex-microsoft_teams not installed: #{e.message}") if defined?(Legion::Logging)
370
372
  false
371
373
  end
372
374
 
@@ -378,7 +380,8 @@ module Legion
378
380
  require 'legion/extensions/microsoft_teams/helpers/browser_auth'
379
381
  settings = begin
380
382
  Legion::Settings.dig(:microsoft_teams, :auth) || {}
381
- rescue StandardError
383
+ rescue StandardError => e
384
+ Legion::Logging.warn("build_teams_browser_auth settings failed: #{e.message}") if defined?(Legion::Logging)
382
385
  {}
383
386
  end
384
387
  Legion::Extensions::MicrosoftTeams::Helpers::BrowserAuth.new(
@@ -392,7 +395,8 @@ module Legion
392
395
  cache = Legion::Extensions::MicrosoftTeams::Helpers::TokenCache.new
393
396
  cache.store_delegated_token(result)
394
397
  cache.save_to_vault
395
- rescue StandardError
398
+ rescue StandardError => e
399
+ Legion::Logging.warn("store_teams_token failed: #{e.message}") if defined?(Legion::Logging)
396
400
  nil
397
401
  end
398
402
 
@@ -445,13 +449,15 @@ module Legion
445
449
 
446
450
  clusters = Legion::Settings.dig(:crypt, :vault, :clusters)
447
451
  clusters.is_a?(Hash) && clusters.any?
448
- rescue StandardError
452
+ rescue StandardError => e
453
+ Legion::Logging.warn("vault_clusters_configured? failed: #{e.message}") if defined?(Legion::Logging)
449
454
  false
450
455
  end
451
456
 
452
457
  def vault_cluster_count
453
458
  Legion::Settings.dig(:crypt, :vault, :clusters)&.size || 0
454
- rescue StandardError
459
+ rescue StandardError => e
460
+ Legion::Logging.warn("vault_cluster_count failed: #{e.message}") if defined?(Legion::Logging)
455
461
  0
456
462
  end
457
463
 
@@ -848,7 +854,8 @@ module Legion
848
854
 
849
855
  sleep 0.1
850
856
  end
851
- rescue ThreadError
857
+ rescue ThreadError => e
858
+ Legion::Logging.debug("drain_with_timeout interrupted: #{e.message}") if defined?(Legion::Logging)
852
859
  nil
853
860
  end
854
861
 
@@ -870,6 +877,7 @@ module Legion
870
877
  false
871
878
  end
872
879
 
880
+ # rubocop:disable Metrics/AbcSize
873
881
  def legionio_running?
874
882
  pid_paths = [
875
883
  File.expand_path('~/.legionio/legion.pid'),
@@ -884,16 +892,20 @@ module Legion
884
892
  begin
885
893
  ::Process.kill(0, pid)
886
894
  return true
887
- rescue Errno::ESRCH
895
+ rescue Errno::ESRCH => e
896
+ Legion::Logging.debug("pid #{pid} not running: #{e.message}") if defined?(Legion::Logging)
888
897
  next
889
- rescue Errno::EPERM
898
+ rescue Errno::EPERM => e
899
+ Legion::Logging.debug("pid #{pid} exists (no permission): #{e.message}") if defined?(Legion::Logging)
890
900
  return true
891
901
  end
892
902
  end
893
903
  system('pgrep -x legionio > /dev/null 2>&1')
894
- rescue StandardError
904
+ rescue StandardError => e
905
+ Legion::Logging.warn("legionio_running? failed: #{e.message}") if defined?(Legion::Logging)
895
906
  false
896
907
  end
908
+ # rubocop:enable Metrics/AbcSize
897
909
 
898
910
  def start_legionio_daemon
899
911
  @log.log('gaia', 'attempting to start legionio daemon')
@@ -915,14 +927,16 @@ module Legion
915
927
  def terminal_width
916
928
  require 'tty-screen'
917
929
  ::TTY::Screen.width
918
- rescue StandardError
930
+ rescue StandardError => e
931
+ Legion::Logging.debug("terminal_width failed: #{e.message}") if defined?(Legion::Logging)
919
932
  80
920
933
  end
921
934
 
922
935
  def terminal_height
923
936
  require 'tty-screen'
924
937
  ::TTY::Screen.height
925
- rescue StandardError
938
+ rescue StandardError => e
939
+ Legion::Logging.debug("terminal_height failed: #{e.message}") if defined?(Legion::Logging)
926
940
  24
927
941
  end
928
942
  end
@@ -31,7 +31,8 @@ module Legion
31
31
  data = ::JSON.parse(File.read(path), symbolize_names: true)
32
32
  data[:messages] = data[:messages].map { |m| deserialize_message(m) }
33
33
  data
34
- rescue ::JSON::ParserError
34
+ rescue ::JSON::ParserError => e
35
+ Legion::Logging.warn("session load failed: #{e.message}") if defined?(Legion::Logging)
35
36
  nil
36
37
  end
37
38
 
@@ -40,7 +41,8 @@ module Legion
40
41
  name = File.basename(path, '.json')
41
42
  data = ::JSON.parse(File.read(path), symbolize_names: true)
42
43
  { name: name, saved_at: data[:saved_at], message_count: data[:messages]&.size || 0 }
43
- rescue StandardError
44
+ rescue StandardError => e
45
+ Legion::Logging.warn("session list entry failed: #{e.message}") if defined?(Legion::Logging)
44
46
  { name: name, saved_at: nil, message_count: 0 }
45
47
  end
46
48
  entries.sort_by { |s| s[:saved_at] || '' }.reverse
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module TTY
5
- VERSION = '0.4.29'
5
+ VERSION = '0.4.30'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-tty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.29
4
+ version: 0.4.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity