lex-microsoft_teams 0.6.34 → 0.6.35

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: a09012375cc07436aafb2c4267acd8ac9a7660d5a79055d2992ca85b079e616c
4
- data.tar.gz: 25e1012b639bcf091422cf0b40e762245c07753e080e4fb190d75be7eeff2f71
3
+ metadata.gz: a180c2f6406a210f6d7f76959fd16a2030e0c43d3269901228f7a6464425d456
4
+ data.tar.gz: 7ea5b4c6a093f23875cc841b18e490c5812654a2bda3faf73a36453345ff4d0f
5
5
  SHA512:
6
- metadata.gz: f0cf0c2cc962656680b8200dfefd405b681bcd016820eb4114d4c4ef9d5e85845778418983639e5a7ce3d96e62a8b175c6f2a475c04f486378341698cb23936e
7
- data.tar.gz: 10b2122a0681ab769270ddc19f67deb6e1701beef934e4e07af970d1675f11e7750ead02ca98111c42a08a6f0f2f472698cbb342d27526fad8852681b5958e15
6
+ metadata.gz: 4d7cbc835079bdeed837263bfbb98269ed0685223a18c002c2b11e726c85c9f2d141b97a1cb58b1270322ef63766ec5d1ee5de415e84a272bf86e48c5347bd04
7
+ data.tar.gz: 9e30a76561740ce85410bbf278958a2f7bff53a3dfc9476d10db329b0ee174e0baffeac9bdaec01c0c04784f2922287756c50876555984c02d1f1bf0f25cda52
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.6.35] - 2026-04-09
6
+
7
+ ### Changed
8
+ - Split `cached_graph_token` into separate `cached_delegated_token` and `cached_app_token` helpers in `TokenCache` — delegated token used for user-context calls, app token for application-credential (client_credentials) calls
9
+ - Added `Broker` soft consumer actor to cache app tokens via client_credentials flow without blocking extension boot
10
+ - Updated all actors (ChannelPoller, DirectChatPoller, MeetingIngest, ObservedChatPoller, PresencePoller) to route token selection based on call context: delegated token for user-scoped Graph API paths, app token for app-scoped paths
11
+
5
12
  ## [0.6.34] - 2026-04-03
6
13
 
7
14
  ### Fixed
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.28
13
+ **Version**: 0.6.34
14
14
 
15
15
  ## Architecture
16
16
 
@@ -264,7 +264,7 @@ Optional framework dependencies (guarded with `defined?`, not in gemspec):
264
264
 
265
265
  ```bash
266
266
  bundle install
267
- bundle exec rspec # ~342 specs across 43 spec files (as of v0.6.28)
267
+ bundle exec rspec # 352 specs across 44 spec files
268
268
  bundle exec rubocop # Clean
269
269
  ```
270
270
 
data/README.md CHANGED
@@ -88,6 +88,23 @@ gem install lex-microsoft_teams
88
88
  ### Cache Ingest
89
89
  - `ingest_cache` — Ingest messages from the local Teams cache into lex-memory as episodic traces; returns `{ stored:, skipped:, latest_time: }`
90
90
 
91
+ ### People
92
+ - `get_profile` — Get Graph API profile for a user (default: `/me`)
93
+ - `list_people` — List relevant people for a user via `/me/people`
94
+
95
+ ### AI Insights
96
+ - `list_meeting_ai_insights` — List AI-generated insights for an online meeting
97
+ - `get_meeting_ai_insight` — Get a specific AI insight
98
+ - `list_meeting_recordings` — List recordings for an online meeting
99
+ - `get_meeting_recording` — Get a specific meeting recording
100
+ - `list_call_records` — List call records from Graph API
101
+ - `get_call_record` — Get a specific call record
102
+
103
+ ### Ownership
104
+ - `sync_owners` — Sync team ownership data from Graph API (single team or all teams)
105
+ - `detect_orphans` — Detect teams with no current owners
106
+ - `get_team_owners` — Get owners for a specific team
107
+
91
108
  ### Adaptive Cards
92
109
  - `build_card` — Build an Adaptive Card payload
93
110
  - `text_block` — Create a TextBlock element
@@ -109,9 +126,20 @@ gem install lex-microsoft_teams
109
126
  - `observe_message` — Conversation observer that extracts tasks, context, and relationship data from subscribed human chats (disabled by default, compliance-gated)
110
127
 
111
128
  **Actors:**
112
- - `DirectChatPoller` — Polls bot DM chats every 5s, publishes to AMQP
113
- - `ObservedChatPoller` — Polls subscribed conversations every 30s (disabled by default)
114
- - `MessageProcessor` — AMQP subscription actor, routes messages by mode to `handle_message` or `observe_message`
129
+ - `CacheBulkIngest` — Once at startup: full local LevelDB cache ingest
130
+ - `CacheSync` — Every 5min: incremental new-message ingest from local cache
131
+ - `DirectChatPoller` — Every 5s: polls bot DM chats via Graph API, publishes to AMQP
132
+ - `ObservedChatPoller` — Every 30s: polls subscribed conversations (compliance-gated, disabled by default)
133
+ - `MessageProcessor` — AMQP subscription actor, routes messages by mode
134
+ - `AuthValidator` — Once at boot: validates and restores delegated tokens
135
+ - `TokenRefresher` — Every 15min: keeps delegated tokens fresh
136
+ - `ProfileIngest` — Once (5s delay): four-phase cognitive data pipeline after auth
137
+ - `ApiIngest` — Every 30min: Graph API ingest with HWM dedup
138
+ - `ChannelPoller` — Every 60s: polls joined team channels for new messages
139
+ - `MeetingIngest` — Every 5min: polls online meetings, fetches transcripts and AI insights
140
+ - `PresencePoller` — Every 60s: polls Graph API presence, logs changes
141
+ - `AbsorbMeeting` — Subscription: absorbs Teams meeting data via absorber framework
142
+ - `IncrementalSync` — Every 15min: periodic re-sync with HWM dedup
115
143
 
116
144
  **Helpers:**
117
145
  - `SessionManager` — Multi-turn LLM session lifecycle with lex-memory persistence
@@ -143,11 +171,11 @@ auth = Legion::Extensions::MicrosoftTeams::Helpers::BrowserAuth.new(
143
171
  result = auth.authenticate # returns token hash with access_token, refresh_token, expires_in
144
172
  ```
145
173
 
146
- Tokens are stored in Vault (`legionio/microsoft_teams/delegated_token`) and silently refreshed before expiry.
174
+ Tokens are stored in Vault at a per-user path (`{USER}/microsoft_teams/delegated_token`) and silently refreshed before expiry.
147
175
 
148
176
  ## Standalone Client
149
177
 
150
- The `Client` class includes all runner modules (Auth, Teams, Chats, Messages, Channels, ChannelMessages, Subscriptions, AdaptiveCards, Bot, Presence, Meetings, Transcripts, LocalCache, CacheIngest).
178
+ The `Client` class includes all runner modules (Auth, Teams, Chats, Messages, Channels, ChannelMessages, Subscriptions, AdaptiveCards, Bot, Presence, Meetings, Transcripts, LocalCache, CacheIngest, People, ProfileIngest, ApiIngest, AiInsights, Ownership).
151
179
 
152
180
  ```ruby
153
181
  client = Legion::Extensions::MicrosoftTeams::Client.new(
@@ -50,7 +50,7 @@ module Legion
50
50
 
51
51
  def manual
52
52
  log.info('ChannelPoller polling team channels')
53
- token = token_cache.cached_graph_token
53
+ token = token_cache.cached_delegated_token
54
54
  unless token
55
55
  log.debug('No token available, skipping poll')
56
56
  return
@@ -39,7 +39,7 @@ module Legion
39
39
  end
40
40
 
41
41
  def manual
42
- token = token_cache.cached_graph_token
42
+ token = token_cache.cached_delegated_token
43
43
  unless token
44
44
  log.debug('No token available, skipping poll')
45
45
  return
@@ -10,7 +10,7 @@ module Legion
10
10
  DEFAULT_INGEST_INTERVAL = 300
11
11
 
12
12
  def runner_class = Legion::Extensions::MicrosoftTeams::Helpers::TokenCache
13
- def runner_function = 'cached_graph_token'
13
+ def runner_function = 'cached_delegated_token'
14
14
  def run_now? = false
15
15
  def use_runner? = false
16
16
  def check_subtask? = false
@@ -52,7 +52,7 @@ module Legion
52
52
 
53
53
  def manual
54
54
  log.info('MeetingIngest polling for meetings')
55
- token = token_cache.cached_graph_token
55
+ token = token_cache.cached_delegated_token
56
56
  return if token.nil?
57
57
 
58
58
  conn = graph_connection(token: token)
@@ -45,7 +45,7 @@ module Legion
45
45
  end
46
46
 
47
47
  def manual
48
- token = token_cache.cached_graph_token
48
+ token = token_cache.cached_app_token
49
49
  return unless token
50
50
 
51
51
  subscriptions = subscription_registry.active_subscriptions
@@ -34,7 +34,7 @@ module Legion
34
34
  end
35
35
 
36
36
  def manual
37
- token = token_cache.cached_graph_token
37
+ token = token_cache.cached_delegated_token
38
38
  unless token
39
39
  log.debug('No token available, skipping presence poll')
40
40
  return
@@ -45,8 +45,15 @@ module Legion
45
45
 
46
46
  # --- Application token (client_credentials) ---
47
47
 
48
- def cached_graph_token
48
+ def cached_app_token
49
49
  @mutex.synchronize do
50
+ # Phase 8: Broker-managed Entra app token (short-circuits cache path)
51
+ if defined?(Legion::Identity::Broker)
52
+ token = Legion::Identity::Broker.token_for(:entra)
53
+ return token if token
54
+ end
55
+
56
+ # Legacy: self-managed client_credentials + cache
50
57
  if @token_cache && !token_expired?(@token_cache)
51
58
  log.debug('Using cached app token')
52
59
  return @token_cache[:token]
@@ -55,19 +62,16 @@ module Legion
55
62
  result = refresh_app_token
56
63
  return result if result
57
64
 
58
- if @delegated_cache && !token_expired?(@delegated_cache)
59
- log.debug('No app token available, using delegated token')
60
- return @delegated_cache[:token]
61
- end
62
-
63
65
  unless @app_token_warned
64
- log.warn('No app or delegated token available for Graph API calls')
66
+ log.warn('No app token available for Graph API calls')
65
67
  @app_token_warned = true
66
68
  end
67
69
  nil
68
70
  end
69
71
  end
70
72
 
73
+ alias cached_graph_token cached_app_token
74
+
71
75
  def clear_token_cache!
72
76
  @mutex.synchronize do
73
77
  @token_cache = nil
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module MicrosoftTeams
6
- VERSION = '0.6.34'
6
+ VERSION = '0.6.35'
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.34
4
+ version: 0.6.35
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity