lex-microsoft_teams 0.6.26 → 0.6.27
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 +4 -4
- data/.github/workflows/ci.yml +3 -3
- data/.rubocop.yml +11 -49
- data/CHANGELOG.md +11 -0
- data/CLAUDE.md +1 -1
- data/Gemfile +2 -1
- data/lib/legion/extensions/microsoft_teams/absorbers/meeting.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/auth_validator.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/channel_poller.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/direct_chat_poller.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/incremental_sync.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/message_processor.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/observed_chat_poller.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/browser_auth.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/helpers/callback_server.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/helpers/high_water_mark.rb +6 -6
- data/lib/legion/extensions/microsoft_teams/helpers/subscription_registry.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/token_cache.rb +4 -5
- data/lib/legion/extensions/microsoft_teams/helpers/trace_retriever.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/hooks/auth.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/local_cache/sstable_reader.rb +3 -3
- data/lib/legion/extensions/microsoft_teams/runners/api_ingest.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/runners/bot.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/runners/profile_ingest.rb +2 -3
- data/lib/legion/extensions/microsoft_teams/version.rb +1 -1
- data/lib/legion/extensions/microsoft_teams.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 43d16a02f8047eba906a48c119cc7e8e4f20bb1c57feb4fefc02fd07dd64ad1f
|
|
4
|
+
data.tar.gz: 1022f0744bc276a6f230dbb695653c77745cb4a0312f3b1ebd844d9e82a40c50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8d7c53718d3754733629c1ca29d791241b4112d44da6fe4e077da45d6054fe37c3031e0da0f2dd96a485c3084ad80e9925b1cab9aacdadc4e7e1c82cc68def09
|
|
7
|
+
data.tar.gz: eae5de2c3b7e62e43454a30cfc8cde3a5e82337d568bb1ca2949a719e4ab12f01cca6a768587505a53158d0241960e3777a938e89d7fd558614a2741a300d05a
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -10,8 +10,8 @@ jobs:
|
|
|
10
10
|
ci:
|
|
11
11
|
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
uses: LegionIO/.github/.github/workflows/
|
|
13
|
+
excluded-files:
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/excluded-files.yml@main
|
|
15
15
|
|
|
16
16
|
security:
|
|
17
17
|
uses: LegionIO/.github/.github/workflows/security-scan.yml@main
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
uses: LegionIO/.github/.github/workflows/stale.yml@main
|
|
28
28
|
|
|
29
29
|
release:
|
|
30
|
-
needs: [ci,
|
|
30
|
+
needs: [ci, excluded-files]
|
|
31
31
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
32
32
|
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
33
33
|
secrets:
|
data/.rubocop.yml
CHANGED
|
@@ -1,56 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
NewCops: enable
|
|
4
|
-
SuggestExtensions: false
|
|
1
|
+
inherit_gem:
|
|
2
|
+
rubocop-legion: config/lex.yml
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
-
EnforcedStyle: space
|
|
11
|
-
|
|
12
|
-
Layout/HashAlignment:
|
|
13
|
-
EnforcedHashRocketStyle: table
|
|
14
|
-
EnforcedColonStyle: table
|
|
15
|
-
|
|
16
|
-
Metrics/MethodLength:
|
|
17
|
-
Max: 50
|
|
18
|
-
|
|
19
|
-
Metrics/ClassLength:
|
|
20
|
-
Max: 1500
|
|
21
|
-
|
|
22
|
-
Metrics/ModuleLength:
|
|
23
|
-
Max: 1500
|
|
24
|
-
|
|
25
|
-
Metrics/BlockLength:
|
|
26
|
-
Max: 40
|
|
27
|
-
Exclude:
|
|
28
|
-
- 'spec/**/*'
|
|
29
|
-
|
|
30
|
-
Metrics/ParameterLists:
|
|
31
|
-
Max: 8
|
|
32
|
-
|
|
33
|
-
Metrics/AbcSize:
|
|
34
|
-
Max: 60
|
|
35
|
-
|
|
36
|
-
Metrics/CyclomaticComplexity:
|
|
37
|
-
Max: 15
|
|
38
|
-
|
|
39
|
-
Metrics/PerceivedComplexity:
|
|
40
|
-
Max: 17
|
|
41
|
-
|
|
42
|
-
Style/Documentation:
|
|
4
|
+
# This repo uses Faraday JSON middleware (string keys), not Legion::JSON.load (symbol keys)
|
|
5
|
+
Legion/Framework/ApiStringKeys:
|
|
43
6
|
Enabled: false
|
|
44
7
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Style/FrozenStringLiteralComment:
|
|
49
|
-
Enabled: true
|
|
50
|
-
EnforcedStyle: always
|
|
8
|
+
# All actors in this extension define `enabled?` with cheap settings/defined? checks only
|
|
9
|
+
Legion/Extension/ActorEnabledSideEffects:
|
|
10
|
+
Enabled: false
|
|
51
11
|
|
|
52
|
-
|
|
12
|
+
# Every actors define `def time` as an instance method override, not via class-level DSL call
|
|
13
|
+
Legion/Extension/EveryActorRequiresTime:
|
|
53
14
|
Enabled: false
|
|
54
15
|
|
|
55
|
-
|
|
16
|
+
# RunnerReturnHash fires on private helper methods inside runner modules (false positives)
|
|
17
|
+
Legion/Extension/RunnerReturnHash:
|
|
56
18
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.6.27] - 2026-03-29
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- Update to rubocop-legion 0.1.7 — resolve all 63 offenses
|
|
9
|
+
- Replace `defined?(Legion::Transport)` with `Legion.const_defined?(:Transport, false)` across 4 files
|
|
10
|
+
- Fix `llm_ask` call in `ProfileIngest` to use `message:` keyword (was `prompt:` + `caller:`)
|
|
11
|
+
- Add rescue variable captures (`=> _e`) for 5 rescue-logging offenses
|
|
12
|
+
- Add inline rubocop disables for 4 structural false positives
|
|
13
|
+
- Disable 3 cops in `.rubocop.yml` that produce systematic false positives
|
|
14
|
+
- Auto-correct Layout/ArgumentAlignment and Performance cops via rubocop -A
|
|
15
|
+
|
|
5
16
|
## [0.6.26] - 2026-03-29
|
|
6
17
|
|
|
7
18
|
### Fixed
|
data/CLAUDE.md
CHANGED
data/Gemfile
CHANGED
|
@@ -4,7 +4,7 @@ module Legion
|
|
|
4
4
|
module Extensions
|
|
5
5
|
module MicrosoftTeams
|
|
6
6
|
module Absorbers
|
|
7
|
-
class Meeting < Legion::Extensions::Absorbers::Base
|
|
7
|
+
class Meeting < Legion::Extensions::Absorbers::Base # rubocop:disable Legion/Extension/AbsorberMissingAbsorbMethod
|
|
8
8
|
pattern :url, 'teams.microsoft.com/l/meetup-join/*'
|
|
9
9
|
pattern :url, '*.teams.microsoft.com/meet/*'
|
|
10
10
|
description 'Absorbs Teams meeting transcripts, AI insights, and participants into Apollo'
|
|
@@ -4,7 +4,7 @@ module Legion
|
|
|
4
4
|
module Extensions
|
|
5
5
|
module MicrosoftTeams
|
|
6
6
|
module Actor
|
|
7
|
-
class AuthValidator < Legion::Extensions::Actors::Once
|
|
7
|
+
class AuthValidator < Legion::Extensions::Actors::Once # rubocop:disable Legion/Extension/SelfContainedActorRunnerClass
|
|
8
8
|
def use_runner? = false
|
|
9
9
|
def check_subtask? = false
|
|
10
10
|
def generate_task? = false
|
|
@@ -128,7 +128,7 @@ module Legion
|
|
|
128
128
|
store_channel_message_trace(team_name: team_name, channel_name: channel_name, msg: msg) if memory_available?
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
-
latest = new_msgs.
|
|
131
|
+
latest = new_msgs.filter_map { |m| m['createdDateTime'] }.max
|
|
132
132
|
@channel_hwm[channel_id] = latest if latest
|
|
133
133
|
end
|
|
134
134
|
|
|
@@ -27,7 +27,7 @@ module Legion
|
|
|
27
27
|
|
|
28
28
|
def enabled?
|
|
29
29
|
defined?(Legion::Extensions::MicrosoftTeams::Runners::Bot) &&
|
|
30
|
-
|
|
30
|
+
Legion.const_defined?(:Transport, false)
|
|
31
31
|
rescue StandardError => e
|
|
32
32
|
log.debug("DirectChatPoller#enabled?: #{e.message}")
|
|
33
33
|
false
|
|
@@ -12,7 +12,7 @@ module Legion
|
|
|
12
12
|
|
|
13
13
|
def enabled?
|
|
14
14
|
defined?(Legion::Extensions::MicrosoftTeams::Runners::Bot) &&
|
|
15
|
-
|
|
15
|
+
Legion.const_defined?(:Transport, false)
|
|
16
16
|
rescue StandardError => e
|
|
17
17
|
log.debug("MessageProcessor#enabled?: #{e.message}")
|
|
18
18
|
false
|
|
@@ -26,7 +26,7 @@ module Legion
|
|
|
26
26
|
|
|
27
27
|
def enabled?
|
|
28
28
|
return false unless defined?(Legion::Extensions::MicrosoftTeams::Runners::Bot)
|
|
29
|
-
return false unless
|
|
29
|
+
return false unless Legion.const_defined?(:Transport, false)
|
|
30
30
|
return false unless defined?(Legion::Settings)
|
|
31
31
|
|
|
32
32
|
Legion::Settings.dig(:microsoft_teams, :bot, :observe, :enabled) == true
|
|
@@ -84,7 +84,7 @@ module Legion
|
|
|
84
84
|
|
|
85
85
|
def gui_available?
|
|
86
86
|
os = host_os
|
|
87
|
-
return true if
|
|
87
|
+
return true if /darwin|mswin|mingw/.match?(os)
|
|
88
88
|
|
|
89
89
|
!ENV['DISPLAY'].nil? || !ENV['WAYLAND_DISPLAY'].nil?
|
|
90
90
|
end
|
|
@@ -107,7 +107,7 @@ module Legion
|
|
|
107
107
|
private
|
|
108
108
|
|
|
109
109
|
def log
|
|
110
|
-
return Legion::Logging if defined?(Legion::Logging)
|
|
110
|
+
return Legion::Logging if defined?(Legion::Logging) # rubocop:disable Legion/HelperMigration/LoggingGuard
|
|
111
111
|
|
|
112
112
|
@log ||= Object.new.tap do |nl|
|
|
113
113
|
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
@@ -26,7 +26,7 @@ module Legion
|
|
|
26
26
|
def start
|
|
27
27
|
@server = TCPServer.new('127.0.0.1', 0)
|
|
28
28
|
@port = @server.addr[1]
|
|
29
|
-
@thread = Thread.new { listen }
|
|
29
|
+
@thread = Thread.new { listen } # rubocop:disable ThreadSafety/NewThread
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def wait_for_callback(timeout: 120)
|
|
@@ -75,7 +75,7 @@ module Legion
|
|
|
75
75
|
client.close
|
|
76
76
|
break if @result
|
|
77
77
|
end
|
|
78
|
-
rescue IOError
|
|
78
|
+
rescue IOError # rubocop:disable Legion/RescueLogging/NoCapture
|
|
79
79
|
nil # server closed during shutdown
|
|
80
80
|
rescue StandardError => e
|
|
81
81
|
@mutex.synchronize do
|
|
@@ -16,7 +16,7 @@ module Legion
|
|
|
16
16
|
def get_hwm(chat_id:)
|
|
17
17
|
key = hwm_key(chat_id: chat_id)
|
|
18
18
|
if cache_available?
|
|
19
|
-
|
|
19
|
+
cache_get(key)
|
|
20
20
|
else
|
|
21
21
|
@hwm_fallback ||= {}
|
|
22
22
|
@hwm_fallback[key]
|
|
@@ -26,7 +26,7 @@ module Legion
|
|
|
26
26
|
def set_hwm(chat_id:, timestamp:)
|
|
27
27
|
key = hwm_key(chat_id: chat_id)
|
|
28
28
|
if cache_available?
|
|
29
|
-
|
|
29
|
+
cache_set(key, timestamp, HWM_TTL)
|
|
30
30
|
else
|
|
31
31
|
@hwm_fallback ||= {}
|
|
32
32
|
@hwm_fallback[key] = timestamp
|
|
@@ -50,7 +50,7 @@ module Legion
|
|
|
50
50
|
def get_extended_hwm(chat_id:)
|
|
51
51
|
key = "teams:ehwm:#{chat_id}"
|
|
52
52
|
raw = if cache_available?
|
|
53
|
-
|
|
53
|
+
cache_get(key)
|
|
54
54
|
else
|
|
55
55
|
@ehwm_fallback ||= {}
|
|
56
56
|
@ehwm_fallback[key]
|
|
@@ -68,7 +68,7 @@ module Legion
|
|
|
68
68
|
value = { last_message_at: last_message_at, last_ingested_at: last_ingested_at,
|
|
69
69
|
message_count: message_count }
|
|
70
70
|
if cache_available?
|
|
71
|
-
|
|
71
|
+
cache_set(key, ::JSON.dump(value), HWM_TTL)
|
|
72
72
|
else
|
|
73
73
|
@ehwm_fallback ||= {}
|
|
74
74
|
@ehwm_fallback[key] = value
|
|
@@ -108,7 +108,7 @@ module Legion
|
|
|
108
108
|
last_ingested_at: data[:last_ingested_at], message_count: data[:message_count] || 0)
|
|
109
109
|
end
|
|
110
110
|
rescue StandardError => e
|
|
111
|
-
|
|
111
|
+
log.warn("Failed to restore HWM from traces: #{e.message}")
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
def memory_runner
|
|
@@ -124,7 +124,7 @@ module Legion
|
|
|
124
124
|
def cache_available?
|
|
125
125
|
defined?(Legion::Cache) &&
|
|
126
126
|
Legion::Cache.respond_to?(:connected?) &&
|
|
127
|
-
|
|
127
|
+
cache_connected?
|
|
128
128
|
end
|
|
129
129
|
end
|
|
130
130
|
end
|
|
@@ -174,11 +174,10 @@ module Legion
|
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
log.info("Saving delegated token to Vault (#{vault_path})")
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
scopes: data[:scopes])
|
|
177
|
+
vault_write(vault_path, access_token: data[:token],
|
|
178
|
+
refresh_token: data[:refresh_token],
|
|
179
|
+
expires_at: data[:expires_at].utc.iso8601,
|
|
180
|
+
scopes: data[:scopes])
|
|
182
181
|
log.info('Delegated token saved to Vault')
|
|
183
182
|
true
|
|
184
183
|
rescue StandardError => e
|
|
@@ -95,7 +95,7 @@ module Legion
|
|
|
95
95
|
age = trace_age_label(trace[:created_at] || trace[:last_reinforced])
|
|
96
96
|
|
|
97
97
|
"- [#{type}] #{content} (#{age}, tags: #{tags})"
|
|
98
|
-
rescue StandardError
|
|
98
|
+
rescue StandardError => _e
|
|
99
99
|
nil
|
|
100
100
|
end
|
|
101
101
|
|
|
@@ -109,7 +109,7 @@ module Legion
|
|
|
109
109
|
when 86_400..604_800 then "#{(seconds / 86_400).to_i}d ago"
|
|
110
110
|
else "#{(seconds / 604_800).to_i}w ago"
|
|
111
111
|
end
|
|
112
|
-
rescue StandardError
|
|
112
|
+
rescue StandardError => _e
|
|
113
113
|
'unknown age'
|
|
114
114
|
end
|
|
115
115
|
|
|
@@ -4,7 +4,7 @@ module Legion
|
|
|
4
4
|
module Extensions
|
|
5
5
|
module MicrosoftTeams
|
|
6
6
|
module Hooks
|
|
7
|
-
class Auth < Legion::Extensions::Hooks::Base
|
|
7
|
+
class Auth < Legion::Extensions::Hooks::Base # rubocop:disable Legion/Extension/HookMissingRunnerClass
|
|
8
8
|
mount '/callback'
|
|
9
9
|
|
|
10
10
|
def self.runner_class
|
|
@@ -58,11 +58,11 @@ module Legion
|
|
|
58
58
|
when 0x00 then block
|
|
59
59
|
when 0x01 then Snappy.inflate(block)
|
|
60
60
|
end
|
|
61
|
-
rescue Snappy::Error
|
|
61
|
+
rescue Snappy::Error => _e
|
|
62
62
|
nil
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
def parse_block_entries(block
|
|
65
|
+
def parse_block_entries(block)
|
|
66
66
|
return unless block && block.bytesize > 4
|
|
67
67
|
|
|
68
68
|
num_restarts = block.byteslice(-4, 4).unpack1('V')
|
|
@@ -88,7 +88,7 @@ module Legion
|
|
|
88
88
|
pos += value_len
|
|
89
89
|
|
|
90
90
|
prev_key = key
|
|
91
|
-
|
|
91
|
+
yield(key, value)
|
|
92
92
|
end
|
|
93
93
|
end
|
|
94
94
|
|
|
@@ -84,7 +84,7 @@ module Legion
|
|
|
84
84
|
|
|
85
85
|
people_ingested += 1
|
|
86
86
|
update_extended_hwm(chat_id: chat['id'],
|
|
87
|
-
last_message_at: messages.
|
|
87
|
+
last_message_at: messages.filter_map { |m| m['createdDateTime'] }.max,
|
|
88
88
|
new_message_count: msg_stored, ingested: true)
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -41,7 +41,7 @@ module Legion
|
|
|
41
41
|
|
|
42
42
|
presence = begin
|
|
43
43
|
conn.get('me/presence').body
|
|
44
|
-
rescue StandardError
|
|
44
|
+
rescue StandardError => _e
|
|
45
45
|
{}
|
|
46
46
|
end
|
|
47
47
|
unless presence.empty?
|
|
@@ -229,8 +229,7 @@ module Legion
|
|
|
229
229
|
result = client.transform(text: text, **definition)
|
|
230
230
|
result[:result] || result[:error] ? nil : result
|
|
231
231
|
elsif defined?(Legion::LLM)
|
|
232
|
-
|
|
233
|
-
caller: { extension: 'lex-microsoft_teams', runner: 'profile_ingest' })
|
|
232
|
+
llm_ask(message: "#{definition[:prompt]}\n\nConversation with #{peer_name}:\n#{text}")
|
|
234
233
|
end
|
|
235
234
|
rescue StandardError => e
|
|
236
235
|
log.debug("ProfileIngest: extract_conversation failed: #{e.message}")
|
|
@@ -36,7 +36,7 @@ require 'legion/extensions/microsoft_teams/helpers/transform_definitions'
|
|
|
36
36
|
require 'legion/extensions/microsoft_teams/helpers/graph_client'
|
|
37
37
|
|
|
38
38
|
# Transport
|
|
39
|
-
if
|
|
39
|
+
if Legion.const_defined?(:Transport, false)
|
|
40
40
|
require 'legion/extensions/microsoft_teams/transport/exchanges/messages'
|
|
41
41
|
require 'legion/extensions/microsoft_teams/transport/queues/messages_process'
|
|
42
42
|
require 'legion/extensions/microsoft_teams/transport/messages/teams_message'
|
|
@@ -53,7 +53,7 @@ end
|
|
|
53
53
|
module Legion
|
|
54
54
|
module Extensions
|
|
55
55
|
module MicrosoftTeams
|
|
56
|
-
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
56
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core, false
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
end
|