lex-microsoft_teams 0.6.27 → 0.6.28

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: 43d16a02f8047eba906a48c119cc7e8e4f20bb1c57feb4fefc02fd07dd64ad1f
4
- data.tar.gz: 1022f0744bc276a6f230dbb695653c77745cb4a0312f3b1ebd844d9e82a40c50
3
+ metadata.gz: 2635c7d3e8d564623f365709464ce8b8e20bb84e535c20d6a268d2419cf816cc
4
+ data.tar.gz: e3886e4a92ab9e885d48308d2657fea15d9a853d6be25ca56a4083033a50cba6
5
5
  SHA512:
6
- metadata.gz: 8d7c53718d3754733629c1ca29d791241b4112d44da6fe4e077da45d6054fe37c3031e0da0f2dd96a485c3084ad80e9925b1cab9aacdadc4e7e1c82cc68def09
7
- data.tar.gz: eae5de2c3b7e62e43454a30cfc8cde3a5e82337d568bb1ca2949a719e4ab12f01cca6a768587505a53158d0241960e3777a938e89d7fd558614a2741a300d05a
6
+ metadata.gz: 159525c1fbf00aa64cdd5ce9b992b2210dbd1077382c8a51ba188be8670139c7b393612f10401ab88f457d24ab3b998890f9ca4c972a104873c78ce428d0d010
7
+ data.tar.gz: 6d1110df11e58b20a3f518f0df2bbd6788cc351408b247010a7039666fde2ed46754153e4ffc20381c426417b291d42381b13157589bcdaf0ea931ab3b5fd353
data/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.6.28] - 2026-03-30
6
+
7
+ ### Fixed
8
+ - `teams_auth_settings` in AuthValidator, TokenRefresher, and TokenCache now falls back to parent `[:microsoft_teams][:tenant_id]`/`[:client_id]` when not found under `[:auth]`, fixing browser auth never triggering when config uses top-level keys
9
+ - `TokenCache#teams_auth_settings` now includes ENV fallback for `AZURE_TENANT_ID`/`AZURE_CLIENT_ID` (previously missing, inconsistent with actor implementations) and parent-level `client_secret` fallback
10
+ - Silent rescue blocks in TraceRetriever (`format_single_trace`, `trace_age_label`), SubscriptionRegistry (`parse_stored`), and ProfileIngest runner (`ingest_self` presence fetch) now log errors instead of swallowing them
11
+
12
+ ### Changed
13
+ - AuthValidator actor delay increased from 2s to 90s to allow Vault, transport, cache, and delegated auth to fully initialize before validation runs
14
+ - ProfileIngest actor delay increased from 5s to 95s to fire after AuthValidator completes (Once actor — no retry if token missing)
15
+ - ApiIngest actor delay increased from 10s to 95s to fire after AuthValidator completes delegated auth
16
+ - CLAUDE.md updated: added 5 undocumented actors (AbsorbMeeting, ApiIngest, ChannelPoller, MeetingIngest, PresencePoller), 3 runners (AiInsights, ApiIngest, Ownership), 1 helper (GraphClient), corrected spec counts
17
+
5
18
  ## [0.6.27] - 2026-03-29
6
19
 
7
20
  ### Changed
data/CLAUDE.md CHANGED
@@ -10,7 +10,7 @@ Legion Extension that connects LegionIO to Microsoft Teams via Graph API and Bot
10
10
 
11
11
  **GitHub**: https://github.com/LegionIO/lex-microsoft_teams
12
12
  **License**: MIT
13
- **Version**: 0.6.27
13
+ **Version**: 0.6.28
14
14
 
15
15
  ## Architecture
16
16
 
@@ -32,16 +32,24 @@ Legion::Extensions::MicrosoftTeams
32
32
  │ ├── LocalCache # Offline message extraction from local LevelDB cache
33
33
  │ ├── CacheIngest # Ingest cached messages into lex-memory as episodic traces
34
34
  │ ├── People # Graph API /me and /me/people (profile + relevant contacts)
35
- └── ProfileIngest # Four-phase cognitive pipeline (self, people, conversations, teams/meetings)
35
+ ├── ProfileIngest # Four-phase cognitive pipeline (self, people, conversations, teams/meetings)
36
+ │ ├── ApiIngest # Graph API ingest (top contacts, 1:1 chat messages, HWM dedup)
37
+ │ ├── AiInsights # Graph API meeting AI insights, recordings, call records
38
+ │ └── Ownership # Graph API ownership sync
36
39
  ├── Actors/
37
40
  │ ├── CacheBulkIngest # Once: full cache ingest at startup (imprint window support)
38
41
  │ ├── CacheSync # Every 5min: incremental ingest of new messages
39
42
  │ ├── DirectChatPoller # Every 5s: polls bot DM chats via Graph API
40
43
  │ ├── ObservedChatPoller # Every 30s: polls subscribed human conversations (compliance-gated)
41
44
  │ ├── MessageProcessor # Subscription: consumes AMQP queue, routes by mode
42
- │ ├── AuthValidator # Once: validates/restores delegated tokens on boot (2s delay)
45
+ │ ├── AuthValidator # Once (90s delay): validates/restores delegated tokens on boot
43
46
  │ ├── TokenRefresher # Every 15min (configurable): keeps delegated tokens fresh
44
- │ ├── ProfileIngest # Once (5s delay): four-phase data pipeline after auth
47
+ │ ├── ProfileIngest # Once (95s delay): four-phase data pipeline after auth
48
+ │ ├── ApiIngest # Every 30min (95s delay): Graph API ingest with HWM dedup
49
+ │ ├── ChannelPoller # Every 60s: polls joined team channels for new messages
50
+ │ ├── MeetingIngest # Every 5min: polls online meetings, fetches transcripts and AI insights
51
+ │ ├── PresencePoller # Every 60s: polls Graph API presence, logs changes
52
+ │ ├── AbsorbMeeting # Subscription: absorbs Teams meeting data via absorber framework
45
53
  │ └── IncrementalSync # Every 15min: periodic re-sync with HWM dedup
46
54
  ├── Transport/
47
55
  │ ├── Exchanges/Messages # teams.messages topic exchange
@@ -62,7 +70,8 @@ Legion::Extensions::MicrosoftTeams
62
70
  │ ├── CallbackServer # Ephemeral TCP server for OAuth redirect callback
63
71
  │ ├── PermissionGuard # Circuit breaker for 403 errors with exponential backoff
64
72
  │ ├── TraceRetriever # Retrieves memory traces from the shared store for bot context (2000-token budget, strength-ranked dedup)
65
- └── TransformDefinitions # lex-transformer definitions for conversation extraction and person summary
73
+ ├── TransformDefinitions # lex-transformer definitions for conversation extraction and person summary
74
+ │ └── GraphClient # Graph API wrapper mixin (graph_get, graph_post, graph_paginate, GraphError)
66
75
  ├── Hooks/
67
76
  │ └── Auth # OAuth callback hook (mount '/callback') → /api/extensions/microsoft_teams/hooks/auth/handle
68
77
  ├── CLI/
@@ -255,7 +264,7 @@ Optional framework dependencies (guarded with `defined?`, not in gemspec):
255
264
 
256
265
  ```bash
257
266
  bundle install
258
- bundle exec rspec # ~305 specs across 40 spec files (as of v0.6.18)
267
+ bundle exec rspec # ~342 specs across 43 spec files (as of v0.6.28)
259
268
  bundle exec rubocop # Clean
260
269
  ```
261
270
 
@@ -18,7 +18,13 @@ module Legion
18
18
  def run_now? = true
19
19
 
20
20
  def delay
21
- 10.0 # let memory + cache ingest initialize first
21
+ if defined?(Legion::Extensions::MicrosoftTeams::Actor::AuthValidator)
22
+ auth_validator = Legion::Extensions::MicrosoftTeams::Actor::AuthValidator.allocate
23
+ base_delay = auth_validator.respond_to?(:delay) ? auth_validator.delay.to_f : 90.0
24
+ base_delay + 5.0 # must fire shortly after AuthValidator completes delegated auth
25
+ else
26
+ 95.0 # conservative boot-ordering fallback if AuthValidator is unavailable
27
+ end
22
28
  end
23
29
 
24
30
  def time
@@ -10,7 +10,7 @@ module Legion
10
10
  def generate_task? = false
11
11
 
12
12
  def delay
13
- 2.0
13
+ 90.0
14
14
  end
15
15
 
16
16
  def enabled?
@@ -105,7 +105,10 @@ module Legion
105
105
  def teams_auth_settings
106
106
  settings = if defined?(Legion::Settings)
107
107
  ms = Legion::Settings[:microsoft_teams]
108
- (ms && ms[:auth]) || {}
108
+ auth = ms && ms[:auth].is_a?(Hash) ? ms[:auth].dup : {}
109
+ auth[:tenant_id] ||= ms[:tenant_id] if ms
110
+ auth[:client_id] ||= ms[:client_id] if ms
111
+ auth
109
112
  else
110
113
  {}
111
114
  end
@@ -12,7 +12,13 @@ module Legion
12
12
  def generate_task? = false
13
13
 
14
14
  def delay
15
- 5.0
15
+ if defined?(Legion::Extensions::MicrosoftTeams::Actor::AuthValidator)
16
+ auth_validator = Legion::Extensions::MicrosoftTeams::Actor::AuthValidator.allocate
17
+ base_delay = auth_validator.respond_to?(:delay) ? auth_validator.delay.to_f : 90.0
18
+ base_delay + 5.0
19
+ else
20
+ 95.0
21
+ end
16
22
  end
17
23
 
18
24
  def enabled?
@@ -100,7 +100,14 @@ module Legion
100
100
  def teams_auth_settings
101
101
  settings = if defined?(Legion::Settings)
102
102
  ms = Legion::Settings[:microsoft_teams]
103
- (ms && ms[:auth]) || {}
103
+ auth = if ms && ms[:auth].is_a?(Hash)
104
+ ms[:auth].dup
105
+ else
106
+ {}
107
+ end
108
+ auth[:tenant_id] ||= ms[:tenant_id] if ms
109
+ auth[:client_id] ||= ms[:client_id] if ms
110
+ auth
104
111
  else
105
112
  {}
106
113
  end
@@ -123,7 +123,8 @@ module Legion
123
123
  v[:created_at] = Time.parse(v[:created_at]) if v[:created_at].is_a?(String)
124
124
  v
125
125
  end
126
- rescue ::JSON::ParserError => _e
126
+ rescue ::JSON::ParserError => e
127
+ log.warn("SubscriptionRegistry: corrupted subscription data, resetting: #{e.message}")
127
128
  {}
128
129
  end
129
130
 
@@ -386,7 +386,14 @@ module Legion
386
386
  return {} unless defined?(Legion::Settings)
387
387
 
388
388
  ms = Legion::Settings[:microsoft_teams]
389
- (ms && ms[:auth]) || {}
389
+ auth = ms && ms[:auth].is_a?(Hash) ? ms[:auth].dup : {}
390
+ auth[:tenant_id] ||= ms[:tenant_id] if ms
391
+ auth[:client_id] ||= ms[:client_id] if ms
392
+ auth[:client_secret] ||= ms[:client_secret] if ms
393
+ auth[:tenant_id] ||= ENV.fetch('AZURE_TENANT_ID', nil)
394
+ auth[:client_id] ||= ENV.fetch('AZURE_CLIENT_ID', nil)
395
+ auth[:client_secret] ||= ENV.fetch('AZURE_CLIENT_SECRET', nil)
396
+ auth
390
397
  end
391
398
  end
392
399
  end
@@ -95,7 +95,8 @@ 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 => _e
98
+ rescue StandardError => e
99
+ log_trace_error('format_single_trace', e)
99
100
  nil
100
101
  end
101
102
 
@@ -109,7 +110,8 @@ module Legion
109
110
  when 86_400..604_800 then "#{(seconds / 86_400).to_i}d ago"
110
111
  else "#{(seconds / 604_800).to_i}w ago"
111
112
  end
112
- rescue StandardError => _e
113
+ rescue StandardError => e
114
+ log_trace_error('trace_age_label', e)
113
115
  'unknown age'
114
116
  end
115
117
 
@@ -41,7 +41,8 @@ module Legion
41
41
 
42
42
  presence = begin
43
43
  conn.get('me/presence').body
44
- rescue StandardError => _e
44
+ rescue StandardError => e
45
+ log.debug("ProfileIngest: presence fetch failed: #{e.message}") if defined?(log)
45
46
  {}
46
47
  end
47
48
  unless presence.empty?
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module MicrosoftTeams
6
- VERSION = '0.6.27'
6
+ VERSION = '0.6.28'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-microsoft_teams
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.27
4
+ version: 0.6.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity