Skip to content

Commit 82c775b

Browse files
Alive-Fishgithub-actions[bot]
authored andcommitted
sync: update knowledge from upstream sources
1 parent e3e42b6 commit 82c775b

33 files changed

Lines changed: 1441 additions & 173 deletions

.github/sync-state.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
"version": 1,
33
"sources": {
44
"slack-plus-teams-experts": {
5-
"lastSyncedCommit": "9ee143ba47bc28dd1eccf19cdbafffeddd51b4ab",
6-
"lastSyncedAt": "2026-04-21T02:21:41Z"
5+
"lastSyncedCommit": "88276fb07f8f38c4ad76c95381093e37086b2d19",
6+
"lastSyncedAt": "2026-07-30T10:12:05Z"
77
},
88
"slack-plus-teams-docs": {
9-
"lastSyncedCommit": "9ee143ba47bc28dd1eccf19cdbafffeddd51b4ab",
10-
"lastSyncedAt": "2026-04-21T02:21:44Z"
9+
"lastSyncedCommit": "88276fb07f8f38c4ad76c95381093e37086b2d19",
10+
"lastSyncedAt": "2026-07-30T10:12:08Z"
1111
}
1212
}
1313
}

skills/microsoft-365-agents-toolkit/docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ A practical guide for developers adding cross-platform support to an existing bo
66

77
| Document | What It Covers |
88
|---|---|
9+
| [**Migration Guide**](migration-guide.md) | **Step-by-step guide for migrating Line of Business apps from Slack to Teams** |
910
| [**Feature Gaps**](feature-gaps.md) | **Complete inventory of every RED and YELLOW gap with mitigations in both directions** |
1011
| [**Workflows**](workflows.md) | **Message-native workflow scenarios: standup, PTO, equipment, account health, break management, incidents** |
1112
| [Messaging & Commands](messaging-and-commands.md) | Messages, slash commands, events, threading, @mentions |
22 KB
Loading
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
from pptx import Presentation
2+
from pptx.util import Pt, Emu
3+
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
4+
from pptx.dml.color import RGBColor
5+
from pptx.enum.shapes import MSO_SHAPE
6+
from pptx.oxml.ns import qn
7+
8+
prs = Presentation('C:/source/slack-plus-teams/docs/slack-plus-teams-architecture.pptx')
9+
10+
# Theme colors from slides 1 and 2 — no platform-specific colors
11+
INDIGO = RGBColor(0x4B, 0x4A, 0x78)
12+
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
13+
GRAY_TEXT = RGBColor(0x6D, 0x6D, 0x6D)
14+
LIGHT_GRAY = RGBColor(0x7A, 0x7A, 0x7A)
15+
GREEN = RGBColor(0x2E, 0x7D, 0x32)
16+
LIGHT_INDIGO_BG = RGBColor(0xE8, 0xE8, 0xF0) # light indigo for adapter bg
17+
LIGHT_GREEN_BG = RGBColor(0xE8, 0xF5, 0xE9) # light green for shared layer bg
18+
ARROW_COLOR = INDIGO
19+
20+
slide_layout = prs.slide_layouts[0]
21+
slide = prs.slides.add_slide(slide_layout)
22+
23+
24+
def add_rect(left, top, width, height, fill_color=None):
25+
shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
26+
shape.line.fill.background()
27+
if fill_color:
28+
shape.fill.solid()
29+
shape.fill.fore_color.rgb = fill_color
30+
else:
31+
shape.fill.background()
32+
tf = shape.text_frame
33+
tf.word_wrap = True
34+
tf.auto_size = None
35+
tf.margin_left = Emu(91440)
36+
tf.margin_right = Emu(91440)
37+
tf.margin_top = Emu(45720)
38+
tf.margin_bottom = Emu(45720)
39+
return shape, tf
40+
41+
42+
def add_rounded(left, top, width, height, fill_color=None, radius=5000,
43+
border_color=None, border_width=None):
44+
shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height)
45+
if border_color:
46+
shape.line.color.rgb = border_color
47+
shape.line.width = border_width or Pt(1.5)
48+
else:
49+
shape.line.fill.background()
50+
spPr = shape._element.spPr
51+
prstGeom = spPr.find(qn('a:prstGeom'))
52+
if prstGeom is not None:
53+
avLst = prstGeom.find(qn('a:avLst'))
54+
if avLst is None:
55+
from lxml import etree
56+
avLst = etree.SubElement(prstGeom, qn('a:avLst'))
57+
else:
58+
for child in list(avLst):
59+
avLst.remove(child)
60+
from lxml import etree
61+
gd = etree.SubElement(avLst, qn('a:gd'))
62+
gd.set('name', 'adj')
63+
gd.set('fmla', f'val {radius}')
64+
if fill_color:
65+
shape.fill.solid()
66+
shape.fill.fore_color.rgb = fill_color
67+
else:
68+
shape.fill.background()
69+
tf = shape.text_frame
70+
tf.word_wrap = True
71+
tf.auto_size = None
72+
tf.margin_left = Emu(91440)
73+
tf.margin_right = Emu(91440)
74+
tf.margin_top = Emu(45720)
75+
tf.margin_bottom = Emu(45720)
76+
return shape, tf
77+
78+
79+
def set_text(tf, text, size, color, bold=False, align=PP_ALIGN.LEFT):
80+
p = tf.paragraphs[0]
81+
p.text = text
82+
p.alignment = align
83+
p.runs[0].font.size = size
84+
p.runs[0].font.color.rgb = color
85+
p.runs[0].font.bold = bold
86+
87+
88+
def add_box(left, top, width, height, title, subtitle_lines,
89+
fill_color, text_color, border_color=None):
90+
"""Add a labeled box with title and subtitle lines."""
91+
shape, tf = add_rounded(left, top, width, height, fill_color=fill_color,
92+
radius=4000, border_color=border_color,
93+
border_width=Pt(1.5))
94+
tf.margin_top = Emu(36000)
95+
tf.margin_bottom = Emu(36000)
96+
p = tf.paragraphs[0]
97+
p.alignment = PP_ALIGN.CENTER
98+
run = p.add_run()
99+
run.text = title
100+
run.font.size = Pt(13)
101+
run.font.bold = True
102+
run.font.color.rgb = text_color
103+
for line in subtitle_lines:
104+
p2 = tf.add_paragraph()
105+
p2.alignment = PP_ALIGN.CENTER
106+
r2 = p2.add_run()
107+
r2.text = line
108+
r2.font.size = Pt(9.5)
109+
r2.font.color.rgb = text_color
110+
r2.font.bold = False
111+
return shape
112+
113+
114+
def add_arrow(x1, y1, x2, y2, color=ARROW_COLOR, width=Pt(2), head=True, tail=False):
115+
"""Add an arrow. head=arrowhead at end, tail=arrowhead at start."""
116+
connector = slide.shapes.add_connector(
117+
1, Emu(x1), Emu(y1), Emu(x2), Emu(y2)
118+
)
119+
connector.line.color.rgb = color
120+
connector.line.width = width
121+
connector.line.fill.solid()
122+
connector.line.color.rgb = color
123+
ln = connector._element.find(qn('a:ln'))
124+
if ln is None:
125+
spPr = connector._element.spPr
126+
ln = spPr.find(qn('a:ln'))
127+
if ln is not None:
128+
from lxml import etree
129+
if head:
130+
t = etree.SubElement(ln, qn('a:tailEnd'))
131+
t.set('type', 'triangle')
132+
t.set('w', 'med')
133+
t.set('len', 'med')
134+
if tail:
135+
h = etree.SubElement(ln, qn('a:headEnd'))
136+
h.set('type', 'triangle')
137+
h.set('w', 'med')
138+
h.set('len', 'med')
139+
return connector
140+
141+
142+
# --- Title banner (squared corners, matching slide 2) ---
143+
shape, tf = add_rect(Emu(109728), Emu(411480), Emu(4500000), Emu(713232), fill_color=INDIGO)
144+
p = tf.paragraphs[0]
145+
run = p.add_run()
146+
run.text = "Adapter Pattern Architecture"
147+
run.font.size = Pt(22)
148+
run.font.bold = True
149+
run.font.color.rgb = WHITE
150+
151+
# Subtitle
152+
shape, tf = add_rect(Emu(4800000), Emu(493776), Emu(7200000), Emu(219456))
153+
set_text(tf, "Inbound calls from each platform converge on a shared service layer",
154+
Pt(13.5), GRAY_TEXT)
155+
156+
157+
# === Layout ===
158+
#
159+
# [Slack] --> [Slack Adapter] --> [ Shared Service ] <-- [Teams Adapter] <-- [Teams]
160+
# [ Layer ]
161+
#
162+
# Both platforms send calls INWARD to the central shared layer.
163+
# The shared layer is the hub; adapters translate platform-specific protocols.
164+
165+
slide_w = 12192000
166+
center_x = slide_w // 2
167+
center_y = 3700000 # slightly below center to account for title
168+
169+
# Shared Service Layer — center, prominent
170+
shared_w = 2600000
171+
shared_h = 2000000
172+
shared_left = center_x - shared_w // 2
173+
shared_top = center_y - shared_h // 2
174+
175+
# Adapter boxes
176+
adapter_w = 1800000
177+
adapter_h = 1400000
178+
adapter_gap = 400000 # gap between adapter and shared layer
179+
180+
slack_adapter_left = shared_left - adapter_gap - adapter_w
181+
slack_adapter_top = center_y - adapter_h // 2
182+
183+
teams_adapter_left = shared_left + shared_w + adapter_gap
184+
teams_adapter_top = center_y - adapter_h // 2
185+
186+
# Platform boxes (outer)
187+
platform_w = 1500000
188+
platform_h = 1000000
189+
platform_gap = 350000
190+
191+
slack_left = slack_adapter_left - platform_gap - platform_w
192+
slack_top = center_y - platform_h // 2
193+
194+
teams_left = teams_adapter_left + adapter_w + platform_gap
195+
teams_top = center_y - platform_h // 2
196+
197+
198+
# --- Draw boxes ---
199+
200+
# Shared Service Layer (center, green theme)
201+
add_box(shared_left, shared_top, shared_w, shared_h,
202+
"Shared Service Layer",
203+
["Business logic", "AI / LLM calls", "Data access", "Common types"],
204+
fill_color=LIGHT_GREEN_BG, text_color=GREEN,
205+
border_color=GREEN)
206+
207+
# Slack Adapter (left of center)
208+
add_box(slack_adapter_left, slack_adapter_top, adapter_w, adapter_h,
209+
"Slack Adapter",
210+
["@slack/bolt", "Event handlers", "Block Kit"],
211+
fill_color=LIGHT_INDIGO_BG, text_color=INDIGO,
212+
border_color=INDIGO)
213+
214+
# Teams Adapter (right of center)
215+
add_box(teams_adapter_left, teams_adapter_top, adapter_w, adapter_h,
216+
"Teams Adapter",
217+
["Agents SDK", "Activity handlers", "Adaptive Cards"],
218+
fill_color=LIGHT_INDIGO_BG, text_color=INDIGO,
219+
border_color=INDIGO)
220+
221+
# Slack Platform (far left)
222+
add_box(slack_left, slack_top, platform_w, platform_h,
223+
"Slack",
224+
["WebSocket", "Socket Mode"],
225+
fill_color=INDIGO, text_color=WHITE)
226+
227+
# Teams Platform (far right)
228+
add_box(teams_left, teams_top, platform_w, platform_h,
229+
"Microsoft Teams",
230+
["HTTPS", "Bot Framework"],
231+
fill_color=INDIGO, text_color=WHITE)
232+
233+
234+
# --- Arrows: both sides point INWARD to the shared layer ---
235+
arrow_y_top = center_y - 150000 # upper arrow (inbound)
236+
arrow_y_bot = center_y + 150000 # lower arrow (outbound/response)
237+
238+
# LEFT SIDE: Slack → Slack Adapter → Shared Layer
239+
240+
# Slack → Slack Adapter (inbound)
241+
add_arrow(slack_left + platform_w, arrow_y_top,
242+
slack_adapter_left, arrow_y_top)
243+
244+
# Slack Adapter → Shared Layer (inbound)
245+
add_arrow(slack_adapter_left + adapter_w, arrow_y_top,
246+
shared_left, arrow_y_top)
247+
248+
# Shared Layer → Slack Adapter (response)
249+
add_arrow(shared_left, arrow_y_bot,
250+
slack_adapter_left + adapter_w, arrow_y_bot)
251+
252+
# Slack Adapter → Slack (response)
253+
add_arrow(slack_adapter_left, arrow_y_bot,
254+
slack_left + platform_w, arrow_y_bot)
255+
256+
257+
# RIGHT SIDE: Teams → Teams Adapter → Shared Layer
258+
259+
# Teams → Teams Adapter (inbound)
260+
add_arrow(teams_left, arrow_y_top,
261+
teams_adapter_left + adapter_w, arrow_y_top)
262+
263+
# Teams Adapter → Shared Layer (inbound)
264+
add_arrow(teams_adapter_left, arrow_y_top,
265+
shared_left + shared_w, arrow_y_top)
266+
267+
# Shared Layer → Teams Adapter (response)
268+
add_arrow(shared_left + shared_w, arrow_y_bot,
269+
teams_adapter_left, arrow_y_bot)
270+
271+
# Teams Adapter → Teams (response)
272+
add_arrow(teams_adapter_left + adapter_w, arrow_y_bot,
273+
teams_left, arrow_y_bot)
274+
275+
276+
# --- Arrow labels ---
277+
def add_label(cx, cy, text):
278+
w = 1400000
279+
h = 220000
280+
shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE,
281+
Emu(cx - w // 2), Emu(cy),
282+
Emu(w), Emu(h))
283+
shape.fill.background()
284+
shape.line.fill.background()
285+
tf = shape.text_frame
286+
tf.word_wrap = True
287+
p = tf.paragraphs[0]
288+
p.alignment = PP_ALIGN.CENTER
289+
p.text = text
290+
p.runs[0].font.size = Pt(8.5)
291+
p.runs[0].font.color.rgb = LIGHT_GRAY
292+
p.runs[0].font.italic = True
293+
294+
295+
# Labels above the inbound arrows
296+
label_y = center_y - shared_h // 2 - 280000
297+
298+
# Left side labels
299+
slack_mid = (slack_left + platform_w + slack_adapter_left) // 2
300+
add_label(slack_mid, label_y, "Events / Messages")
301+
302+
slack_adapter_mid = (slack_adapter_left + adapter_w + shared_left) // 2
303+
add_label(slack_adapter_mid, label_y, "Normalized Calls")
304+
305+
# Right side labels
306+
teams_mid = (teams_left + teams_adapter_left + adapter_w) // 2
307+
add_label(teams_mid, label_y, "Activities / Messages")
308+
309+
teams_adapter_mid = (teams_adapter_left + shared_left + shared_w) // 2
310+
add_label(teams_adapter_mid, label_y, "Normalized Calls")
311+
312+
313+
# --- Footer ---
314+
shape, tf = add_rect(Emu(219456), Emu(6455664), Emu(6035040), Emu(128016))
315+
set_text(tf, "Slack to Teams migration guide \u2022 architecture diagram 4 of 7",
316+
Pt(9.5), LIGHT_GRAY)
317+
318+
prs.save('C:/source/slack-plus-teams/docs/slack-plus-teams-architecture-v3.pptx')
319+
print("Slide 4 (Adapter Pattern Architecture) added successfully!")

0 commit comments

Comments
 (0)