lex-microsoft_teams 0.6.5 → 0.6.7
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/CHANGELOG.md +16 -0
- data/lib/legion/extensions/microsoft_teams/actors/channel_poller.rb +27 -1
- data/lib/legion/extensions/microsoft_teams/actors/meeting_ingest.rb +36 -0
- data/lib/legion/extensions/microsoft_teams/actors/message_processor.rb +1 -1
- data/lib/legion/extensions/microsoft_teams/actors/profile_ingest.rb +1 -2
- data/lib/legion/extensions/microsoft_teams/runners/bot.rb +9 -0
- data/lib/legion/extensions/microsoft_teams/version.rb +1 -1
- 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: f2b4cefc6a1bd6c568b74afb644092dbff531b11e2eb40fd5ad62835caccba13
|
|
4
|
+
data.tar.gz: 6077b95ded27b3160e4d31d3bd003ca6b4fa17c35e0defdd91e5fb66d72245f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0cf55cc7c012c40fc2299e2697384efea18f2e9d220f7dfcc97470eae276ebe76524251e79d57681edf408aa660c38ae00880dc45861be0cbdc8303c7147910e
|
|
7
|
+
data.tar.gz: 7891774a5a9a02d9ac2c71d0f55d44ff9be5e11949b7a36f8b6bcdbe9d94bd7f5503f984afa7e42ddac77132fa155af35c57b35e7c8b070de3d333356183327a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.7] - 2026-03-22
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- ProfileIngest actor uses `TokenCache.instance` singleton instead of `TokenCache.new` (empty cache returned nil token, preventing boot-time profile ingest)
|
|
7
|
+
|
|
8
|
+
## [0.6.6] - 2026-03-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `Bot.dispatch_message` routes AMQP messages by mode (direct -> handle_message, observe -> observe_message)
|
|
12
|
+
- MeetingIngest stores transcripts as episodic traces and AI insights as semantic traces in lex-agentic-memory
|
|
13
|
+
- ChannelPoller stores new channel messages as episodic traces in lex-agentic-memory
|
|
14
|
+
- INFO-level poll logging in MeetingIngest and ChannelPoller for visibility
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- MessageProcessor actor now calls `dispatch_message` instead of `handle_message` directly
|
|
18
|
+
|
|
3
19
|
## [0.6.5] - 2026-03-22
|
|
4
20
|
|
|
5
21
|
### Added
|
|
@@ -26,6 +26,14 @@ module Legion
|
|
|
26
26
|
def check_subtask? = false
|
|
27
27
|
def generate_task? = false
|
|
28
28
|
|
|
29
|
+
def memory_available?
|
|
30
|
+
defined?(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def memory_runner
|
|
34
|
+
@memory_runner ||= Object.new.extend(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces)
|
|
35
|
+
end
|
|
36
|
+
|
|
29
37
|
def enabled?
|
|
30
38
|
return false unless defined?(Legion::Extensions::MicrosoftTeams::Helpers::TokenCache)
|
|
31
39
|
|
|
@@ -39,6 +47,7 @@ module Legion
|
|
|
39
47
|
end
|
|
40
48
|
|
|
41
49
|
def manual
|
|
50
|
+
log_info('ChannelPoller polling team channels')
|
|
42
51
|
token = token_cache.cached_graph_token
|
|
43
52
|
unless token
|
|
44
53
|
log_debug('No token available, skipping poll')
|
|
@@ -113,7 +122,10 @@ module Legion
|
|
|
113
122
|
return if new_msgs.empty?
|
|
114
123
|
|
|
115
124
|
log_info("#{team_name} / #{channel_name}: #{new_msgs.length} new message(s)")
|
|
116
|
-
new_msgs.each
|
|
125
|
+
new_msgs.each do |msg|
|
|
126
|
+
log_message(team_name: team_name, channel_name: channel_name, msg: msg)
|
|
127
|
+
store_channel_message_trace(team_name: team_name, channel_name: channel_name, msg: msg) if memory_available?
|
|
128
|
+
end
|
|
117
129
|
|
|
118
130
|
latest = new_msgs.map { |m| m['createdDateTime'] }.compact.max
|
|
119
131
|
@channel_hwm[channel_id] = latest if latest
|
|
@@ -149,6 +161,20 @@ module Legion
|
|
|
149
161
|
default
|
|
150
162
|
end
|
|
151
163
|
|
|
164
|
+
def store_channel_message_trace(team_name:, channel_name:, msg:)
|
|
165
|
+
sender = msg.dig('from', 'user', 'displayName') || 'Unknown'
|
|
166
|
+
content = (msg.dig('body', 'content') || '').gsub(/<[^>]+>/, '').strip
|
|
167
|
+
memory_runner.store_trace(
|
|
168
|
+
type: :episodic,
|
|
169
|
+
content_payload: "#{sender} in #{team_name}/##{channel_name}: #{content}"[0, 5000],
|
|
170
|
+
domain_tags: ['teams', 'channel', "team:#{team_name}", "channel:#{channel_name}", "sender:#{sender}"],
|
|
171
|
+
origin: :direct_experience,
|
|
172
|
+
confidence: 0.7
|
|
173
|
+
)
|
|
174
|
+
rescue StandardError => e
|
|
175
|
+
log_error("Failed to store channel message trace: #{e.message}")
|
|
176
|
+
end
|
|
177
|
+
|
|
152
178
|
def log_debug(msg)
|
|
153
179
|
Legion::Logging.debug("[Teams::ChannelPoller] #{msg}") if defined?(Legion::Logging)
|
|
154
180
|
end
|
|
@@ -36,11 +36,20 @@ module Legion
|
|
|
36
36
|
false
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
def memory_available?
|
|
40
|
+
defined?(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def memory_runner
|
|
44
|
+
@memory_runner ||= Object.new.extend(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces)
|
|
45
|
+
end
|
|
46
|
+
|
|
39
47
|
def token_cache
|
|
40
48
|
Legion::Extensions::MicrosoftTeams::Helpers::TokenCache.instance
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
def manual
|
|
52
|
+
log_info('MeetingIngest polling for meetings')
|
|
44
53
|
token = token_cache.cached_graph_token
|
|
45
54
|
return if token.nil?
|
|
46
55
|
|
|
@@ -104,6 +113,7 @@ module Legion
|
|
|
104
113
|
content = content_response.body.to_s
|
|
105
114
|
preview = content[0, 200]
|
|
106
115
|
log_debug("Meeting '#{subject}' transcript #{tid}: #{preview}")
|
|
116
|
+
store_transcript_trace(meeting_id: meeting_id, subject: subject, transcript_id: tid, content: content) if memory_available?
|
|
107
117
|
rescue StandardError => e
|
|
108
118
|
log_warn("Could not fetch transcript content #{tid} for meeting #{meeting_id}: #{e.message}")
|
|
109
119
|
end
|
|
@@ -121,11 +131,37 @@ module Legion
|
|
|
121
131
|
action_items.each do |item|
|
|
122
132
|
log_info(" - #{item['text'] || item.inspect}")
|
|
123
133
|
end
|
|
134
|
+
|
|
135
|
+
store_insight_trace(meeting_id: meeting_id, subject: subject, insight: insight) if memory_available?
|
|
124
136
|
end
|
|
125
137
|
rescue StandardError => e
|
|
126
138
|
log_warn("Could not fetch AI insights for meeting #{meeting_id}: #{e.message}")
|
|
127
139
|
end
|
|
128
140
|
|
|
141
|
+
def store_transcript_trace(meeting_id:, subject:, transcript_id:, content:) # rubocop:disable Lint/UnusedMethodArgument
|
|
142
|
+
memory_runner.store_trace(
|
|
143
|
+
type: :episodic,
|
|
144
|
+
content_payload: content[0, 10_000],
|
|
145
|
+
domain_tags: ['teams', 'transcript', "meeting:#{meeting_id}", "transcript:#{transcript_id}"],
|
|
146
|
+
origin: :direct_experience,
|
|
147
|
+
confidence: 0.9
|
|
148
|
+
)
|
|
149
|
+
rescue StandardError => e
|
|
150
|
+
log_warn("Could not store transcript trace for meeting #{meeting_id}: #{e.message}")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def store_insight_trace(meeting_id:, subject:, insight:) # rubocop:disable Lint/UnusedMethodArgument
|
|
154
|
+
memory_runner.store_trace(
|
|
155
|
+
type: :semantic,
|
|
156
|
+
content_payload: insight.to_s,
|
|
157
|
+
domain_tags: ['teams', 'ai-insight', "meeting:#{meeting_id}"],
|
|
158
|
+
origin: :inferred,
|
|
159
|
+
confidence: 0.8
|
|
160
|
+
)
|
|
161
|
+
rescue StandardError => e
|
|
162
|
+
log_warn("Could not store insight trace for meeting #{meeting_id}: #{e.message}")
|
|
163
|
+
end
|
|
164
|
+
|
|
129
165
|
def log_debug(msg)
|
|
130
166
|
Legion::Logging.debug("[Teams::MeetingIngest] #{msg}") if defined?(Legion::Logging)
|
|
131
167
|
end
|
|
@@ -6,7 +6,7 @@ module Legion
|
|
|
6
6
|
module Actor
|
|
7
7
|
class MessageProcessor < Legion::Extensions::Actors::Subscription
|
|
8
8
|
def runner_class = 'Legion::Extensions::MicrosoftTeams::Runners::Bot'
|
|
9
|
-
def runner_function = '
|
|
9
|
+
def runner_function = 'dispatch_message'
|
|
10
10
|
def check_subtask? = false
|
|
11
11
|
def generate_task? = false
|
|
12
12
|
|
|
@@ -49,8 +49,7 @@ module Legion
|
|
|
49
49
|
|
|
50
50
|
def resolve_token
|
|
51
51
|
if defined?(Legion::Extensions::MicrosoftTeams::Helpers::TokenCache)
|
|
52
|
-
|
|
53
|
-
cache.cached_delegated_token
|
|
52
|
+
Legion::Extensions::MicrosoftTeams::Helpers::TokenCache.instance.cached_delegated_token
|
|
54
53
|
end
|
|
55
54
|
rescue StandardError
|
|
56
55
|
nil
|
|
@@ -71,6 +71,15 @@ module Legion
|
|
|
71
71
|
{ result: response.body }
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def dispatch_message(mode: :direct, **payload)
|
|
75
|
+
case mode.to_s
|
|
76
|
+
when 'observe'
|
|
77
|
+
observe_message(**payload)
|
|
78
|
+
else
|
|
79
|
+
handle_message(**payload)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
74
83
|
def handle_message(chat_id:, conversation_id:, text:, owner_id:, mode: :direct, **opts)
|
|
75
84
|
command_result = handle_command(text: text, owner_id: owner_id, chat_id: chat_id, **opts)
|
|
76
85
|
if command_result
|