lex-microsoft_teams 0.6.51 → 0.6.53
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/.rubocop.yml +4 -0
- data/CHANGELOG.md +10 -1
- data/lib/legion/extensions/microsoft_teams/absorbers/channel.rb +3 -3
- data/lib/legion/extensions/microsoft_teams/absorbers/chat.rb +3 -3
- data/lib/legion/extensions/microsoft_teams/absorbers/meeting.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/actors/absorb_channel.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/actors/absorb_chat.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/actors/absorb_meeting.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/actors/api_ingest.rb +16 -6
- data/lib/legion/extensions/microsoft_teams/actors/cache_bulk_ingest.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/meeting_ingest.rb +14 -6
- data/lib/legion/extensions/microsoft_teams/actors/observed_chat_poller.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/presence_poller.rb +14 -5
- data/lib/legion/extensions/microsoft_teams/actors/profile_ingest.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/faraday/retry_after.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/client.rb +4 -4
- data/lib/legion/extensions/microsoft_teams/helpers/graph_cache.rb +3 -3
- data/lib/legion/extensions/microsoft_teams/helpers/graph_client.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/high_water_mark.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/prompt_resolver.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/session_manager.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/helpers/throttle_aware.rb +185 -0
- data/lib/legion/extensions/microsoft_teams/helpers/trace_retriever.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/local_cache/sstable_reader.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/runners/api_ingest.rb +91 -19
- data/lib/legion/extensions/microsoft_teams/runners/bot.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/runners/cache_ingest.rb +2 -2
- data/lib/legion/extensions/microsoft_teams/runners/profile_ingest.rb +89 -35
- data/lib/legion/extensions/microsoft_teams/version.rb +1 -1
- data/lib/legion/extensions/microsoft_teams.rb +3 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1c452da3646f36302d562fefd816a7b00621e95d819017c6125cc7c0fcb1ea74
|
|
4
|
+
data.tar.gz: c11fa2558cb00fa66d884360242f98a574b68d4ecda61451ba7e1a5de3b8067c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: db1531411cd4b67f36b644652e3549aae7b9f3360a987187f04a8bc39c9d436bb8dea21873f61edcbf85964b6bcf5889e68bd64bd786f1967f0426f5aede2d51
|
|
7
|
+
data.tar.gz: 6798cc2a718ac3ba43db14b3476abaeab0279d9747c90c8d47f6dfd185f86271787f48042ab22d0dcdfce48af5d7cdf505bb4bf0766601d0d2bfdd8f37bfeb7a
|
data/.rubocop.yml
CHANGED
|
@@ -16,6 +16,10 @@ Legion/Extension/EveryActorRequiresTime:
|
|
|
16
16
|
# RunnerReturnHash fires on private helper methods inside runner modules (false positives)
|
|
17
17
|
Legion/Extension/RunnerReturnHash:
|
|
18
18
|
Enabled: false
|
|
19
|
+
|
|
20
|
+
# This extension uses trace types (episodic, semantic, procedural) not LLM taxonomy types
|
|
21
|
+
Legion/Llm/TaxonomyEnum:
|
|
22
|
+
Enabled: false
|
|
19
23
|
|
|
20
24
|
Metrics/CyclomaticComplexity:
|
|
21
25
|
Max: 25
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.53] - 2026-07-15
|
|
4
|
+
### Fixed
|
|
5
|
+
- Fix throttle propagation, invalid OData filter, member index priority, stop trace spam from API fetches
|
|
6
|
+
|
|
7
|
+
## [0.6.52] - 2026-05-29
|
|
8
|
+
### Fixed
|
|
9
|
+
- **Actors now defer their next scheduled run on a Graph throttle** instead of re-firing on their fixed timer interval — resolves the 0.6.51 "Known follow-up". New `Helpers::ThrottleAware` mixin records a "suppress until" instant of `now + retry_after` when a Graph call raises `Errors::Throttled`; subsequent ticks short-circuit until that window elapses. Wired into `PresencePoller`, `MeetingIngest`, and `ApiIngest`. Falls back to a bounded 60s deferral when the server gave no usable `Retry-After`, and clamps any single deferral to 600s. Previously a poller on a 30–300s interval would walk straight back into the still-open shared circuit every interval, emitting a `[throttle_circuit] hard circuit` ERROR (and a duplicate `Errors::Throttled` WARN/ERROR) each tick while ingesting nothing.
|
|
10
|
+
- **`ProfileIngest#full_ingest` and `ApiIngest#ingest_api` now propagate `Errors::Throttled`** rather than folding it into a per-stage error hash. `full_ingest` catches it once and aborts the remaining fan-out stages — once the shared circuit is open every later stage would only raise `Throttled(attempts: 0)` instantly, so continuing produced a burst of identical errors. The actor that drives `ingest_api` uses the propagated throttle to open its deferral window. Non-throttle errors keep their existing error-result behavior.
|
|
11
|
+
|
|
3
12
|
## [0.6.51] - 2026-05-27
|
|
4
13
|
### Added
|
|
5
14
|
- `Faraday::RetryAfter` middleware honoring `Retry-After` per RFC 9110 §10.2.3 (originally RFC 7231 §7.1.3) in both delta-seconds and HTTP-date forms. Retries HTTP 429 by default; 503/504 opt-in. Bounded by `max_retries` and cumulative `max_wait`; ±jitter on advertised wait to avoid thundering-herd. Configurable via `microsoft_teams.client.retry.{max_retries,max_wait,jitter,fallback_wait,retry_statuses}`; `fetch` semantics preserve explicit falsey values.
|
|
@@ -18,7 +27,7 @@
|
|
|
18
27
|
- Actors that were accidentally re-enabled by `952607c` (rubocop removed `return false` guards) are now properly gated by `settings[:actor_name][:enabled]` — `presence_poller`, `channel_poller`, `direct_chat_poller`, and `observed_chat_poller` all default to `false`.
|
|
19
28
|
|
|
20
29
|
### Known follow-up
|
|
21
|
-
- Actors (`*_poller.rb`, `meeting_ingest`, `profile_ingest`) still catch `Errors::Throttled` via the generic `rescue StandardError` block but do not yet *defer their next scheduled run* using the carried `retry_after`. To be addressed in a follow-up issue.
|
|
30
|
+
- Actors (`*_poller.rb`, `meeting_ingest`, `profile_ingest`) still catch `Errors::Throttled` via the generic `rescue StandardError` block but do not yet *defer their next scheduled run* using the carried `retry_after`. To be addressed in a follow-up issue. *(Resolved in [Unreleased] — see `Helpers::ThrottleAware`.)*
|
|
22
31
|
|
|
23
32
|
## [0.6.50] - 2026-05-27
|
|
24
33
|
### Added
|
|
@@ -57,7 +57,7 @@ module Legion
|
|
|
57
57
|
def graph_token
|
|
58
58
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.load_token(:delegated)
|
|
59
59
|
rescue StandardError => e
|
|
60
|
-
handle_exception(e, level: :
|
|
60
|
+
handle_exception(e, level: :warn, operation: 'Channel#graph_token')
|
|
61
61
|
nil
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -85,7 +85,7 @@ module Legion
|
|
|
85
85
|
|
|
86
86
|
{ team_id: team_id, channel_id: channel_id, message_id: message_id }
|
|
87
87
|
rescue StandardError => e
|
|
88
|
-
handle_exception(e, level: :
|
|
88
|
+
handle_exception(e, level: :warn, operation: 'Channel#extract_ids', url: url)
|
|
89
89
|
nil
|
|
90
90
|
end
|
|
91
91
|
|
|
@@ -202,7 +202,7 @@ module Legion
|
|
|
202
202
|
" ↳ [#{timestamp}] #{sender}: #{text}"
|
|
203
203
|
end
|
|
204
204
|
rescue StandardError => e
|
|
205
|
-
handle_exception(e, level: :
|
|
205
|
+
handle_exception(e, level: :warn, operation: 'Channel#fetch_reply_lines',
|
|
206
206
|
team_id: team_id, channel_id: channel_id, message_id: message_id)
|
|
207
207
|
[]
|
|
208
208
|
end
|
|
@@ -46,7 +46,7 @@ module Legion
|
|
|
46
46
|
def graph_token
|
|
47
47
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.load_token(:delegated)
|
|
48
48
|
rescue StandardError => e
|
|
49
|
-
handle_exception(e, level: :
|
|
49
|
+
handle_exception(e, level: :warn, operation: 'Chat#graph_token')
|
|
50
50
|
nil
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -60,7 +60,7 @@ module Legion
|
|
|
60
60
|
|
|
61
61
|
URI.decode_uri_component(match[1])
|
|
62
62
|
rescue StandardError => e
|
|
63
|
-
handle_exception(e, level: :
|
|
63
|
+
handle_exception(e, level: :warn, operation: 'Chat#extract_chat_id', url: url)
|
|
64
64
|
nil
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -150,7 +150,7 @@ module Legion
|
|
|
150
150
|
" ↳ [#{timestamp}] #{sender}: #{text}"
|
|
151
151
|
end
|
|
152
152
|
rescue StandardError => e
|
|
153
|
-
handle_exception(e, level: :
|
|
153
|
+
handle_exception(e, level: :warn, operation: 'Chat#fetch_reply_lines',
|
|
154
154
|
chat_id: chat_id, message_id: message_id)
|
|
155
155
|
[]
|
|
156
156
|
end
|
|
@@ -51,7 +51,7 @@ module Legion
|
|
|
51
51
|
def graph_token
|
|
52
52
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.load_token(:delegated)
|
|
53
53
|
rescue StandardError => e
|
|
54
|
-
handle_exception(e, level: :
|
|
54
|
+
handle_exception(e, level: :warn, operation: 'Meeting#graph_token')
|
|
55
55
|
nil
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -75,7 +75,7 @@ module Legion
|
|
|
75
75
|
match = uri.path.match(%r{/l/chat/(19:meeting_[^/]+)})
|
|
76
76
|
match&.[](1)
|
|
77
77
|
rescue URI::InvalidURIError => e
|
|
78
|
-
handle_exception(e, level: :
|
|
78
|
+
handle_exception(e, level: :warn, operation: 'Meeting#extract_meeting_thread_id', url: url)
|
|
79
79
|
nil
|
|
80
80
|
end
|
|
81
81
|
|
|
@@ -14,7 +14,7 @@ module Legion
|
|
|
14
14
|
defined?(Legion::Extensions::Absorbers::Base) &&
|
|
15
15
|
defined?(Legion::Extensions::MicrosoftTeams::Absorbers::Channel)
|
|
16
16
|
rescue StandardError => e
|
|
17
|
-
handle_exception(e, level: :
|
|
17
|
+
handle_exception(e, level: :warn, operation: 'AbsorbChannel#enabled?')
|
|
18
18
|
false
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -53,7 +53,7 @@ module Legion
|
|
|
53
53
|
|
|
54
54
|
data.transform_keys(&:to_sym)
|
|
55
55
|
rescue StandardError => e
|
|
56
|
-
handle_exception(e, level: :
|
|
56
|
+
handle_exception(e, level: :warn, operation: 'AbsorbChannel#parse_payload')
|
|
57
57
|
{}
|
|
58
58
|
end
|
|
59
59
|
end
|
|
@@ -14,7 +14,7 @@ module Legion
|
|
|
14
14
|
defined?(Legion::Extensions::Absorbers::Base) &&
|
|
15
15
|
defined?(Legion::Extensions::MicrosoftTeams::Absorbers::Chat)
|
|
16
16
|
rescue StandardError => e
|
|
17
|
-
handle_exception(e, level: :
|
|
17
|
+
handle_exception(e, level: :warn, operation: 'AbsorbChat#enabled?')
|
|
18
18
|
false
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -53,7 +53,7 @@ module Legion
|
|
|
53
53
|
|
|
54
54
|
data.transform_keys(&:to_sym)
|
|
55
55
|
rescue StandardError => e
|
|
56
|
-
handle_exception(e, level: :
|
|
56
|
+
handle_exception(e, level: :warn, operation: 'AbsorbChat#parse_payload')
|
|
57
57
|
{}
|
|
58
58
|
end
|
|
59
59
|
end
|
|
@@ -14,7 +14,7 @@ module Legion
|
|
|
14
14
|
defined?(Legion::Extensions::Absorbers::Base) &&
|
|
15
15
|
defined?(Legion::Extensions::MicrosoftTeams::Absorbers::Meeting)
|
|
16
16
|
rescue StandardError => e
|
|
17
|
-
handle_exception(e, level: :
|
|
17
|
+
handle_exception(e, level: :warn, operation: 'AbsorbMeeting#enabled?')
|
|
18
18
|
false
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -53,7 +53,7 @@ module Legion
|
|
|
53
53
|
|
|
54
54
|
data.transform_keys(&:to_sym)
|
|
55
55
|
rescue StandardError => e
|
|
56
|
-
handle_exception(e, level: :
|
|
56
|
+
handle_exception(e, level: :warn, operation: 'AbsorbMeeting#parse_payload')
|
|
57
57
|
{}
|
|
58
58
|
end
|
|
59
59
|
end
|
|
@@ -5,6 +5,8 @@ module Legion
|
|
|
5
5
|
module MicrosoftTeams
|
|
6
6
|
module Actor
|
|
7
7
|
class ApiIngest < Legion::Extensions::Actors::Every
|
|
8
|
+
include Legion::Extensions::MicrosoftTeams::Helpers::ThrottleAware
|
|
9
|
+
|
|
8
10
|
def runner_class = Legion::Extensions::MicrosoftTeams::Runners::ApiIngest
|
|
9
11
|
|
|
10
12
|
def runner_function = 'ingest_api'
|
|
@@ -22,7 +24,7 @@ module Legion
|
|
|
22
24
|
base_delay = auth_validator.respond_to?(:delay) ? auth_validator.delay.to_f : 9.0
|
|
23
25
|
[base_delay + 5.0, 14].max
|
|
24
26
|
rescue StandardError => e
|
|
25
|
-
handle_exception(e, level: :
|
|
27
|
+
handle_exception(e, level: :warn, operation: 'ApiIngest#delay')
|
|
26
28
|
14
|
|
27
29
|
end
|
|
28
30
|
|
|
@@ -40,6 +42,18 @@ module Legion
|
|
|
40
42
|
|
|
41
43
|
def manual
|
|
42
44
|
log.debug('ApiIngest#manual starting')
|
|
45
|
+
# The runner re-raises Errors::Throttled (rather than folding it
|
|
46
|
+
# into an error result) precisely so this actor can defer its
|
|
47
|
+
# next run by the advertised retry_after instead of charging the
|
|
48
|
+
# shared Graph circuit again on the next interval.
|
|
49
|
+
with_throttle_deferral { run_ingest }
|
|
50
|
+
rescue StandardError => e
|
|
51
|
+
handle_exception(e, level: :error, operation: 'ApiIngest#manual')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def run_ingest
|
|
43
57
|
token = resolve_token
|
|
44
58
|
unless token
|
|
45
59
|
log.warn('ApiIngest: no delegated token, skipping')
|
|
@@ -57,12 +71,8 @@ module Legion
|
|
|
57
71
|
)
|
|
58
72
|
log.info("ApiIngest: #{result.inspect[0, 200]}")
|
|
59
73
|
result
|
|
60
|
-
rescue StandardError => e
|
|
61
|
-
handle_exception(e, level: :error, operation: 'ApiIngest#manual')
|
|
62
74
|
end
|
|
63
75
|
|
|
64
|
-
private
|
|
65
|
-
|
|
66
76
|
def token_available?
|
|
67
77
|
resolve_token != nil
|
|
68
78
|
end
|
|
@@ -83,7 +93,7 @@ module Legion
|
|
|
83
93
|
|
|
84
94
|
Legion::Extensions::Coldstart::Helpers::Bootstrap.new.imprint_active?
|
|
85
95
|
rescue StandardError => e
|
|
86
|
-
handle_exception(e, level: :
|
|
96
|
+
handle_exception(e, level: :warn, operation: 'ApiIngest#imprint_active?')
|
|
87
97
|
false
|
|
88
98
|
end
|
|
89
99
|
end
|
|
@@ -41,7 +41,7 @@ module Legion
|
|
|
41
41
|
|
|
42
42
|
Legion::Extensions::Coldstart::Helpers::Bootstrap.new.imprint_active?
|
|
43
43
|
rescue StandardError => e
|
|
44
|
-
handle_exception(e, level: :
|
|
44
|
+
handle_exception(e, level: :warn, operation: 'CacheBulkIngest#imprint_active?')
|
|
45
45
|
false
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -34,7 +34,7 @@ module Legion
|
|
|
34
34
|
def enabled?
|
|
35
35
|
settings.dig(:channel_poller, :enabled)
|
|
36
36
|
rescue StandardError => e
|
|
37
|
-
handle_exception(e, level: :
|
|
37
|
+
handle_exception(e, level: :warn, operation: 'ChannelPoller#enabled?')
|
|
38
38
|
false
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -29,7 +29,7 @@ module Legion
|
|
|
29
29
|
defined?(Legion::Extensions::MicrosoftTeams::Runners::Bot) &&
|
|
30
30
|
Legion.const_defined?(:Transport, false)
|
|
31
31
|
rescue StandardError => e
|
|
32
|
-
handle_exception(e, level: :
|
|
32
|
+
handle_exception(e, level: :warn, operation: 'DirectChatPoller#enabled?')
|
|
33
33
|
false
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -22,7 +22,7 @@ module Legion
|
|
|
22
22
|
defined?(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces) &&
|
|
23
23
|
token_available?
|
|
24
24
|
rescue StandardError => e
|
|
25
|
-
handle_exception(e, level: :
|
|
25
|
+
handle_exception(e, level: :warn, operation: 'IncrementalSync#enabled?')
|
|
26
26
|
false
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -6,6 +6,7 @@ module Legion
|
|
|
6
6
|
module Actor
|
|
7
7
|
class MeetingIngest < Legion::Extensions::Actors::Every
|
|
8
8
|
include Legion::Extensions::MicrosoftTeams::Helpers::Client
|
|
9
|
+
include Legion::Extensions::MicrosoftTeams::Helpers::ThrottleAware
|
|
9
10
|
|
|
10
11
|
def runner_class = self.class
|
|
11
12
|
def runner_function = 'manual'
|
|
@@ -27,7 +28,7 @@ module Legion
|
|
|
27
28
|
settings.dig(:meeting_ingest, :enabled) &&
|
|
28
29
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.respond_to?(:load_token)
|
|
29
30
|
rescue StandardError => e
|
|
30
|
-
handle_exception(e, level: :
|
|
31
|
+
handle_exception(e, level: :warn, operation: 'MeetingIngest#enabled?')
|
|
31
32
|
false
|
|
32
33
|
end
|
|
33
34
|
|
|
@@ -41,6 +42,17 @@ module Legion
|
|
|
41
42
|
|
|
42
43
|
def manual
|
|
43
44
|
log.info('MeetingIngest polling for meetings')
|
|
45
|
+
# Defer the next run when Graph throttles the meetings listing
|
|
46
|
+
# (the first, fixed call every tick makes); per-meeting throttles
|
|
47
|
+
# are handled by the inner rescue below and don't change cadence.
|
|
48
|
+
with_throttle_deferral { ingest_meetings }
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
handle_exception(e, level: :error, operation: 'MeetingIngest#manual')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def ingest_meetings
|
|
44
56
|
token = Legion::Extensions::Identity::Entra::Helpers::TokenManager.load_token(:delegated)
|
|
45
57
|
return if token.nil?
|
|
46
58
|
|
|
@@ -57,16 +69,12 @@ module Legion
|
|
|
57
69
|
process_meeting(meeting_id: meeting_id, subject: meeting['subject'], token: token)
|
|
58
70
|
@processed_meetings.add(meeting_id)
|
|
59
71
|
rescue StandardError => e
|
|
60
|
-
handle_exception(e, level: :error, operation: 'MeetingIngest#
|
|
72
|
+
handle_exception(e, level: :error, operation: 'MeetingIngest#ingest_meetings',
|
|
61
73
|
meeting_id: meeting_id)
|
|
62
74
|
end
|
|
63
75
|
end
|
|
64
|
-
rescue StandardError => e
|
|
65
|
-
handle_exception(e, level: :error, operation: 'MeetingIngest#manual')
|
|
66
76
|
end
|
|
67
77
|
|
|
68
|
-
private
|
|
69
|
-
|
|
70
78
|
def process_meeting(meeting_id:, subject:, token:)
|
|
71
79
|
log.debug("MeetingIngest#process_meeting meeting_id=#{meeting_id} subject=#{subject}")
|
|
72
80
|
conn = graph_connection(token: token)
|
|
@@ -28,7 +28,7 @@ module Legion
|
|
|
28
28
|
defined?(Legion::Extensions::MicrosoftTeams::Runners::Bot) &&
|
|
29
29
|
Legion.const_defined?(:Transport, false)
|
|
30
30
|
rescue StandardError => e
|
|
31
|
-
handle_exception(e, level: :
|
|
31
|
+
handle_exception(e, level: :warn, operation: 'ObservedChatPoller#enabled?')
|
|
32
32
|
false
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -6,6 +6,7 @@ module Legion
|
|
|
6
6
|
module Actor
|
|
7
7
|
class PresencePoller < Legion::Extensions::Actors::Every
|
|
8
8
|
include Legion::Extensions::MicrosoftTeams::Helpers::Client
|
|
9
|
+
include Legion::Extensions::MicrosoftTeams::Helpers::ThrottleAware
|
|
9
10
|
|
|
10
11
|
def runner_class = self.class
|
|
11
12
|
def runner_function = 'manual'
|
|
@@ -22,12 +23,24 @@ module Legion
|
|
|
22
23
|
settings.dig(:presence_poller, :enabled) &&
|
|
23
24
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.respond_to?(:load_token)
|
|
24
25
|
rescue StandardError => e
|
|
25
|
-
handle_exception(e, level: :
|
|
26
|
+
handle_exception(e, level: :warn, operation: 'PresencePoller#enabled?')
|
|
26
27
|
false
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def manual
|
|
30
31
|
log.debug('PresencePoller#manual starting')
|
|
32
|
+
# Honour a recent Graph throttle by deferring this run; on a
|
|
33
|
+
# 429 the block raises Errors::Throttled, which the mixin
|
|
34
|
+
# converts into a deferral window so the next tick stands down
|
|
35
|
+
# for retry_after seconds instead of re-firing on the interval.
|
|
36
|
+
with_throttle_deferral { poll_presence }
|
|
37
|
+
rescue StandardError => e
|
|
38
|
+
handle_exception(e, level: :error, operation: 'PresencePoller#manual')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def poll_presence
|
|
31
44
|
token = delegated_token
|
|
32
45
|
unless token
|
|
33
46
|
log.debug('No token available, skipping presence poll')
|
|
@@ -49,12 +62,8 @@ module Legion
|
|
|
49
62
|
log.info("Presence changed: availability=#{availability}, activity=#{activity}")
|
|
50
63
|
@last_presence = current
|
|
51
64
|
end
|
|
52
|
-
rescue StandardError => e
|
|
53
|
-
handle_exception(e, level: :error, operation: 'PresencePoller#manual')
|
|
54
65
|
end
|
|
55
66
|
|
|
56
|
-
private
|
|
57
|
-
|
|
58
67
|
def delegated_token
|
|
59
68
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.load_token(:delegated)
|
|
60
69
|
rescue StandardError => e
|
|
@@ -16,7 +16,7 @@ module Legion
|
|
|
16
16
|
base_delay = auth_validator.respond_to?(:delay) ? auth_validator.delay.to_f : 9.0
|
|
17
17
|
base_delay + 5.0
|
|
18
18
|
rescue StandardError => e
|
|
19
|
-
handle_exception(e, level: :
|
|
19
|
+
handle_exception(e, level: :warn, operation: 'ProfileIngest#delay')
|
|
20
20
|
14.0
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ module Legion
|
|
|
25
25
|
defined?(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces) &&
|
|
26
26
|
token_available?
|
|
27
27
|
rescue StandardError => e
|
|
28
|
-
handle_exception(e, level: :
|
|
28
|
+
handle_exception(e, level: :warn, operation: 'ProfileIngest#enabled?')
|
|
29
29
|
false
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -12,7 +12,7 @@ module Legion
|
|
|
12
12
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
13
13
|
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
14
14
|
|
|
15
|
-
def graph_connection(token: nil, api_url: 'https://graph.microsoft.com/v1.0', **
|
|
15
|
+
def graph_connection(token: nil, api_url: 'https://graph.microsoft.com/v1.0', **)
|
|
16
16
|
token ||= entra_delegated_token
|
|
17
17
|
::Faraday.new(url: api_url) do |conn|
|
|
18
18
|
conn.request :json
|
|
@@ -24,7 +24,7 @@ module Legion
|
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def bot_connection(token: nil, service_url: 'https://smba.trafficmanager.net/teams/', **
|
|
27
|
+
def bot_connection(token: nil, service_url: 'https://smba.trafficmanager.net/teams/', **)
|
|
28
28
|
::Faraday.new(url: service_url) do |conn|
|
|
29
29
|
conn.request :json
|
|
30
30
|
conn.use Legion::Extensions::MicrosoftTeams::Faraday::ThrottleCircuit, **throttle_circuit_options
|
|
@@ -39,7 +39,7 @@ module Legion
|
|
|
39
39
|
user_id == 'me' ? 'me' : "users/#{user_id}"
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def oauth_connection(tenant_id: 'common', **
|
|
42
|
+
def oauth_connection(tenant_id: 'common', **)
|
|
43
43
|
::Faraday.new(url: "https://login.microsoftonline.com/#{tenant_id}") do |conn|
|
|
44
44
|
conn.request :url_encoded
|
|
45
45
|
conn.response :json, content_type: /\bjson$/
|
|
@@ -51,7 +51,7 @@ module Legion
|
|
|
51
51
|
def entra_delegated_token
|
|
52
52
|
Legion::Extensions::Identity::Entra::Helpers::TokenManager.load_token(:delegated)
|
|
53
53
|
rescue StandardError => e
|
|
54
|
-
handle_exception(e, level: :
|
|
54
|
+
handle_exception(e, level: :warn, operation: 'Client#entra_delegated_token')
|
|
55
55
|
nil
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -21,7 +21,7 @@ module Legion
|
|
|
21
21
|
resp.body
|
|
22
22
|
end
|
|
23
23
|
rescue StandardError => e
|
|
24
|
-
handle_exception(e, level: :
|
|
24
|
+
handle_exception(e, level: :warn, operation: 'GraphCache#cached_graph_get', path: path)
|
|
25
25
|
conn.get(path, params).body
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -35,7 +35,7 @@ module Legion
|
|
|
35
35
|
key = graph_cache_key(path: path, params: params, shared: shared)
|
|
36
36
|
cache_delete(key)
|
|
37
37
|
rescue StandardError => e
|
|
38
|
-
handle_exception(e, level: :
|
|
38
|
+
handle_exception(e, level: :warn, operation: 'GraphCache#invalidate_graph_cache')
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
private
|
|
@@ -55,7 +55,7 @@ module Legion
|
|
|
55
55
|
|
|
56
56
|
Legion::Settings[:microsoft_teams] || {}
|
|
57
57
|
rescue StandardError => e
|
|
58
|
-
handle_exception(e, level: :
|
|
58
|
+
handle_exception(e, level: :warn, operation: 'GraphCache#teams_extension_settings')
|
|
59
59
|
{}
|
|
60
60
|
end
|
|
61
61
|
end
|
|
@@ -59,7 +59,7 @@ module Legion
|
|
|
59
59
|
|
|
60
60
|
raw.is_a?(Hash) ? raw : ::JSON.parse(raw, symbolize_names: true)
|
|
61
61
|
rescue StandardError => e
|
|
62
|
-
handle_exception(e, level: :
|
|
62
|
+
handle_exception(e, level: :warn, operation: 'HighWaterMark#get_extended_hwm',
|
|
63
63
|
chat_id: chat_id)
|
|
64
64
|
nil
|
|
65
65
|
end
|
|
@@ -55,7 +55,7 @@ module Legion
|
|
|
55
55
|
Legion::Extensions::Mesh::Helpers::PreferenceProfile.preference_instructions(profile: profile)
|
|
56
56
|
rescue StandardError => e
|
|
57
57
|
if defined?(handle_exception)
|
|
58
|
-
handle_exception(e, level: :
|
|
58
|
+
handle_exception(e, level: :warn, operation: 'PromptResolver#preference_instructions_for',
|
|
59
59
|
owner_id: owner_id)
|
|
60
60
|
end
|
|
61
61
|
nil
|
|
@@ -153,7 +153,7 @@ module Legion
|
|
|
153
153
|
profile_traces.map { |t| { type: t[:trace_type], content: t[:content_payload].to_s[0, 200] } }
|
|
154
154
|
rescue StandardError => e
|
|
155
155
|
if defined?(handle_exception)
|
|
156
|
-
handle_exception(e, level: :
|
|
156
|
+
handle_exception(e, level: :warn, operation: 'SessionManager#trace_seed_for',
|
|
157
157
|
owner_id: owner_id)
|
|
158
158
|
end
|
|
159
159
|
nil
|