@open-everywhere/provider-teams 0.0.0-stage → 0.1.0

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.
Files changed (146) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +46 -2
  4. package/agent/channels/teams-bot-name.ts +162 -0
  5. package/agent/channels/teams-catch-up.ts +244 -0
  6. package/agent/channels/teams-connector.ts +183 -0
  7. package/agent/channels/teams-conversation-ref.ts +398 -0
  8. package/agent/channels/teams-directory.ts +193 -0
  9. package/agent/channels/teams-engagement.ts +391 -0
  10. package/agent/channels/teams-fire-eligibility.ts +152 -0
  11. package/agent/channels/teams-front.ts +1404 -0
  12. package/agent/channels/teams-graph-boundary.ts +178 -0
  13. package/agent/channels/teams-graph-team-id.ts +106 -0
  14. package/agent/channels/teams-id-restore.ts +131 -0
  15. package/agent/channels/teams-identity.ts +395 -0
  16. package/agent/channels/teams-input-response.ts +129 -0
  17. package/agent/channels/teams-message-ops.ts +79 -0
  18. package/agent/channels/teams-origin-codec.ts +104 -0
  19. package/agent/channels/teams-post-arm.ts +323 -0
  20. package/agent/channels/teams-reaction-feedback.ts +127 -0
  21. package/agent/channels/teams-read.ts +510 -0
  22. package/agent/channels/teams-roster.ts +136 -0
  23. package/agent/channels/teams-stop.ts +319 -0
  24. package/agent/channels/teams-supervisor.ts +638 -0
  25. package/agent/channels/teams.ts +270 -0
  26. package/agent/contributions.ts +31 -0
  27. package/agent/docs-generated.ts +15 -0
  28. package/agent/ops.ts +129 -0
  29. package/agent/provider-events.ts +69 -0
  30. package/agent/register.ts +219 -0
  31. package/agent/surface-parity.ts +112 -0
  32. package/dist/agent/channels/teams-bot-name.d.ts +36 -0
  33. package/dist/agent/channels/teams-bot-name.d.ts.map +1 -0
  34. package/dist/agent/channels/teams-bot-name.js +141 -0
  35. package/dist/agent/channels/teams-bot-name.js.map +1 -0
  36. package/dist/agent/channels/teams-catch-up.d.ts +53 -0
  37. package/dist/agent/channels/teams-catch-up.d.ts.map +1 -0
  38. package/dist/agent/channels/teams-catch-up.js +221 -0
  39. package/dist/agent/channels/teams-catch-up.js.map +1 -0
  40. package/dist/agent/channels/teams-connector.d.ts +57 -0
  41. package/dist/agent/channels/teams-connector.d.ts.map +1 -0
  42. package/dist/agent/channels/teams-connector.js +132 -0
  43. package/dist/agent/channels/teams-connector.js.map +1 -0
  44. package/dist/agent/channels/teams-conversation-ref.d.ts +123 -0
  45. package/dist/agent/channels/teams-conversation-ref.d.ts.map +1 -0
  46. package/dist/agent/channels/teams-conversation-ref.js +368 -0
  47. package/dist/agent/channels/teams-conversation-ref.js.map +1 -0
  48. package/dist/agent/channels/teams-directory.d.ts +11 -0
  49. package/dist/agent/channels/teams-directory.d.ts.map +1 -0
  50. package/dist/agent/channels/teams-directory.js +179 -0
  51. package/dist/agent/channels/teams-directory.js.map +1 -0
  52. package/dist/agent/channels/teams-engagement.d.ts +174 -0
  53. package/dist/agent/channels/teams-engagement.d.ts.map +1 -0
  54. package/dist/agent/channels/teams-engagement.js +336 -0
  55. package/dist/agent/channels/teams-engagement.js.map +1 -0
  56. package/dist/agent/channels/teams-fire-eligibility.d.ts +26 -0
  57. package/dist/agent/channels/teams-fire-eligibility.d.ts.map +1 -0
  58. package/dist/agent/channels/teams-fire-eligibility.js +126 -0
  59. package/dist/agent/channels/teams-fire-eligibility.js.map +1 -0
  60. package/dist/agent/channels/teams-front.d.ts +249 -0
  61. package/dist/agent/channels/teams-front.d.ts.map +1 -0
  62. package/dist/agent/channels/teams-front.js +1143 -0
  63. package/dist/agent/channels/teams-front.js.map +1 -0
  64. package/dist/agent/channels/teams-graph-boundary.d.ts +45 -0
  65. package/dist/agent/channels/teams-graph-boundary.d.ts.map +1 -0
  66. package/dist/agent/channels/teams-graph-boundary.js +168 -0
  67. package/dist/agent/channels/teams-graph-boundary.js.map +1 -0
  68. package/dist/agent/channels/teams-graph-team-id.d.ts +30 -0
  69. package/dist/agent/channels/teams-graph-team-id.d.ts.map +1 -0
  70. package/dist/agent/channels/teams-graph-team-id.js +89 -0
  71. package/dist/agent/channels/teams-graph-team-id.js.map +1 -0
  72. package/dist/agent/channels/teams-id-restore.d.ts +34 -0
  73. package/dist/agent/channels/teams-id-restore.d.ts.map +1 -0
  74. package/dist/agent/channels/teams-id-restore.js +123 -0
  75. package/dist/agent/channels/teams-id-restore.js.map +1 -0
  76. package/dist/agent/channels/teams-identity.d.ts +148 -0
  77. package/dist/agent/channels/teams-identity.d.ts.map +1 -0
  78. package/dist/agent/channels/teams-identity.js +336 -0
  79. package/dist/agent/channels/teams-identity.js.map +1 -0
  80. package/dist/agent/channels/teams-input-response.d.ts +23 -0
  81. package/dist/agent/channels/teams-input-response.d.ts.map +1 -0
  82. package/dist/agent/channels/teams-input-response.js +102 -0
  83. package/dist/agent/channels/teams-input-response.js.map +1 -0
  84. package/dist/agent/channels/teams-message-ops.d.ts +3 -0
  85. package/dist/agent/channels/teams-message-ops.d.ts.map +1 -0
  86. package/dist/agent/channels/teams-message-ops.js +72 -0
  87. package/dist/agent/channels/teams-message-ops.js.map +1 -0
  88. package/dist/agent/channels/teams-origin-codec.d.ts +16 -0
  89. package/dist/agent/channels/teams-origin-codec.d.ts.map +1 -0
  90. package/dist/agent/channels/teams-origin-codec.js +99 -0
  91. package/dist/agent/channels/teams-origin-codec.js.map +1 -0
  92. package/dist/agent/channels/teams-post-arm.d.ts +37 -0
  93. package/dist/agent/channels/teams-post-arm.d.ts.map +1 -0
  94. package/dist/agent/channels/teams-post-arm.js +280 -0
  95. package/dist/agent/channels/teams-post-arm.js.map +1 -0
  96. package/dist/agent/channels/teams-reaction-feedback.d.ts +22 -0
  97. package/dist/agent/channels/teams-reaction-feedback.d.ts.map +1 -0
  98. package/dist/agent/channels/teams-reaction-feedback.js +108 -0
  99. package/dist/agent/channels/teams-reaction-feedback.js.map +1 -0
  100. package/dist/agent/channels/teams-read.d.ts +127 -0
  101. package/dist/agent/channels/teams-read.d.ts.map +1 -0
  102. package/dist/agent/channels/teams-read.js +424 -0
  103. package/dist/agent/channels/teams-read.js.map +1 -0
  104. package/dist/agent/channels/teams-roster.d.ts +54 -0
  105. package/dist/agent/channels/teams-roster.d.ts.map +1 -0
  106. package/dist/agent/channels/teams-roster.js +121 -0
  107. package/dist/agent/channels/teams-roster.js.map +1 -0
  108. package/dist/agent/channels/teams-stop.d.ts +74 -0
  109. package/dist/agent/channels/teams-stop.d.ts.map +1 -0
  110. package/dist/agent/channels/teams-stop.js +252 -0
  111. package/dist/agent/channels/teams-stop.js.map +1 -0
  112. package/dist/agent/channels/teams-supervisor.d.ts +351 -0
  113. package/dist/agent/channels/teams-supervisor.d.ts.map +1 -0
  114. package/dist/agent/channels/teams-supervisor.js +366 -0
  115. package/dist/agent/channels/teams-supervisor.js.map +1 -0
  116. package/dist/agent/channels/teams.d.ts +5 -0
  117. package/dist/agent/channels/teams.d.ts.map +1 -0
  118. package/dist/agent/channels/teams.js +246 -0
  119. package/dist/agent/channels/teams.js.map +1 -0
  120. package/dist/agent/contributions.d.ts +12 -0
  121. package/dist/agent/contributions.d.ts.map +1 -0
  122. package/dist/agent/contributions.js +31 -0
  123. package/dist/agent/contributions.js.map +1 -0
  124. package/dist/agent/docs-generated.d.ts +3 -0
  125. package/dist/agent/docs-generated.d.ts.map +1 -0
  126. package/dist/agent/docs-generated.js +13 -0
  127. package/dist/agent/docs-generated.js.map +1 -0
  128. package/dist/agent/ops.d.ts +14 -0
  129. package/dist/agent/ops.d.ts.map +1 -0
  130. package/dist/agent/ops.js +122 -0
  131. package/dist/agent/ops.js.map +1 -0
  132. package/dist/agent/provider-events.d.ts +3 -0
  133. package/dist/agent/provider-events.d.ts.map +1 -0
  134. package/dist/agent/provider-events.js +67 -0
  135. package/dist/agent/provider-events.js.map +1 -0
  136. package/dist/agent/register.d.ts +16 -0
  137. package/dist/agent/register.d.ts.map +1 -0
  138. package/dist/agent/register.js +198 -0
  139. package/dist/agent/register.js.map +1 -0
  140. package/dist/agent/surface-parity.d.ts +3 -0
  141. package/dist/agent/surface-parity.d.ts.map +1 -0
  142. package/dist/agent/surface-parity.js +106 -0
  143. package/dist/agent/surface-parity.js.map +1 -0
  144. package/package.json +183 -4
  145. package/tsconfig.build.json +22 -0
  146. package/tsconfig.json +15 -0
@@ -0,0 +1,3 @@
1
+ import type { ProviderEventDeclaration } from "@open-everywhere/core/agent/adapter-api.js";
2
+ export declare const TEAMS_PROVIDER_EVENTS: ProviderEventDeclaration;
3
+ //# sourceMappingURL=provider-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-events.d.ts","sourceRoot":"","sources":["../../agent/provider-events.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,qBAAqB,EAAE,wBA+CnC,CAAC"}
@@ -0,0 +1,67 @@
1
+ // TEAMS's event inventory (OPE-1612). See the core module's header
2
+ // (packages/core/agent/routines/provider-events.ts) for what the three routing states mean.
3
+ //
4
+ // 🔴 TEAMS REGISTERS NO EVENT NORMALIZER, so every row is `routing: "none"` and the declaration
5
+ // names no `source`.
6
+ //
7
+ // TEAMS HAS NO "EVENT NAME", AND THE ROWS SAY SO RATHER THAN INVENTING ONE. Microsoft Graph
8
+ // subscribes to a RESOURCE PATH, and one subscription declares which changes it wants through a
9
+ // separate `changeType` (`created`, `updated`, `deleted`). There is no `workflow_run`-shaped string
10
+ // to quote, so each row's `event` is the resource path verbatim and its note carries the change
11
+ // types that path accepts. Spelling a composite like `chatMessage.created` would be a name the
12
+ // vendor does not use, which is the invention this seam exists to forbid.
13
+ //
14
+ // TWO THINGS WOULD HAVE TO BE DECIDED BEFORE ANY OF THIS ROUTES, and neither is a normalizer.
15
+ // Graph proves a delivery with a validation token rather than a body signature, so the "declared
16
+ // door with a declared verifier" rule needs an answer for that shape. And a resource-data
17
+ // notification arrives ENCRYPTED under a certificate the deployment holds, so the payload a
18
+ // normalizer would read does not exist until something decrypts it.
19
+ export const TEAMS_PROVIDER_EVENTS = {
20
+ // `source` is ABSENT, not empty — the bundle registers no normalizer, so there is no key to name.
21
+ doc: "https://learn.microsoft.com/en-us/graph/teams-changenotifications-chatmessage",
22
+ events: [
23
+ {
24
+ event: "/teams/{team-id}/channels/{channel-id}/messages",
25
+ routing: "none",
26
+ match: [],
27
+ scope: [],
28
+ note: "messages and replies in ONE channel; changeType `created,updated`. The narrowest Teams subscription there is, and the one a per-channel routine would want",
29
+ },
30
+ {
31
+ event: "/chats/{chat-id}/messages",
32
+ routing: "none",
33
+ match: [],
34
+ scope: [],
35
+ note: "messages in ONE chat; changeType `created,updated`",
36
+ },
37
+ {
38
+ event: "/teams/getAllMessages",
39
+ routing: "none",
40
+ match: [],
41
+ scope: [],
42
+ note: "every channel message in the TENANT; changeType `created,updated`. Tenant-wide, so it needs the `ChannelMessage.Read.All` application permission",
43
+ },
44
+ {
45
+ event: "/chats/getAllMessages",
46
+ routing: "none",
47
+ match: [],
48
+ scope: [],
49
+ note: "every chat message in the TENANT; changeType `created,updated,deleted`. Needs `Chat.Read.All`",
50
+ },
51
+ {
52
+ event: "/users/{user-id}/chats/getAllMessages",
53
+ routing: "none",
54
+ match: [],
55
+ scope: [],
56
+ note: "every chat message one user takes part in; changeType `created,updated,deleted`",
57
+ },
58
+ {
59
+ event: "/appCatalogs/teamsApps/{teams-app-id}/installedToChats/getAllMessages",
60
+ routing: "none",
61
+ match: [],
62
+ scope: [],
63
+ note: "every chat message where a named Teams app is installed; changeType `created,updated`. The narrowest tenant-wide shape — it follows the app rather than the tenant",
64
+ },
65
+ ],
66
+ };
67
+ //# sourceMappingURL=provider-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-events.js","sourceRoot":"","sources":["../../agent/provider-events.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,4FAA4F;AAC5F,EAAE;AACF,gGAAgG;AAChG,qBAAqB;AACrB,EAAE;AACF,4FAA4F;AAC5F,gGAAgG;AAChG,oGAAoG;AACpG,gGAAgG;AAChG,+FAA+F;AAC/F,0EAA0E;AAC1E,EAAE;AACF,8FAA8F;AAC9F,iGAAiG;AACjG,0FAA0F;AAC1F,4FAA4F;AAC5F,oEAAoE;AAIpE,MAAM,CAAC,MAAM,qBAAqB,GAA6B;IAC7D,kGAAkG;IAClG,GAAG,EAAE,+EAA+E;IACpF,MAAM,EAAE;QACN;YACE,KAAK,EAAE,iDAAiD;YACxD,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,4JAA4J;SACnK;QACD;YACE,KAAK,EAAE,2BAA2B;YAClC,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,oDAAoD;SAC3D;QACD;YACE,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,kJAAkJ;SACzJ;QACD;YACE,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,+FAA+F;SACtG;QACD;YACE,KAAK,EAAE,uCAAuC;YAC9C,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,iFAAiF;SACxF;QACD;YACE,KAAK,EAAE,uEAAuE;YAC9E,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,oKAAoK;SAC3K;KACF;CACF,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type DispatchTarget, type Routine } from "@open-everywhere/core/agent/adapter-api.js";
2
+ /**
3
+ * Resolve a Teams routine to its proactive-fire DispatchTarget — MOVED VERBATIM out of core's
4
+ * schedules/dispatch.ts (OPE-114 stage 4). Proactive messaging on Teams REQUIRES a Bot Framework
5
+ * conversation reference (serviceUrl + conversation id) captured on a prior INBOUND turn — you
6
+ * cannot cold-send to a Teams user/channel the bot has never heard from. bindTeams captures exactly
7
+ * that off every inbound activity, and create_routine stores it on the routine, so by construction
8
+ * every Teams routine created in-thread carries its reference. A routine WITHOUT one (both fields
9
+ * are required by eve's teamsChannel().receive, which throws otherwise) fails closed to dry-run
10
+ * (null) here.
11
+ */
12
+ export declare function resolveTeamsTarget(r: Routine): DispatchTarget | null;
13
+ /** Perform ALL of the teams bundle's registrations. Idempotent (each register call replaces);
14
+ * cheap and side-effect-free beyond the registry writes. */
15
+ export declare function registerTeamsProvider(): void;
16
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"AA0CA,OAAO,EAeL,KAAK,cAAc,EACnB,KAAK,OAAO,EAGb,MAAM,4CAA4C,CAAC;AAwBpD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAwDpE;AAED;6DAC6D;AAC7D,wBAAgB,qBAAqB,IAAI,IAAI,CA+D5C"}
@@ -0,0 +1,198 @@
1
+ // registerTeamsProvider — the ONE boot entry of @open-everywhere/provider-teams. The app's
2
+ // adapter-wiring module (agent/lib/register-adapters.ts) imports this STATICALLY and calls it once
3
+ // at boot; every seam the teams bundle implements registers here and nowhere else. Static imports
4
+ // only: eve bundles the agent definition and its whole import graph into one rolldown chunk — a
5
+ // literal dynamic import() code-splits and trips eve's "expected one authored module" invariant.
6
+ //
7
+ // What teams registers (and what it deliberately does NOT):
8
+ // • identity mapper — bindTeams (chat-surface plane; channels/teams-identity.ts)
9
+ // • capability manifest — midTurnPost via the host-side Connector write seam
10
+ // (channels/teams-connector.ts, OPE-1237); no reaction primitive
11
+ // • post arm — teamsPostArm (mid-turn reply + unified reply + redrive helpers + the
12
+ // 1:1 DM delivery arm, OPE-887)
13
+ // • wake-origin codec — the stored-data teams arm (channels/teams-origin-codec.ts, which also
14
+ // owns the Bot-Connector serviceUrl allowlist isTrustedTeamsServiceUrl)
15
+ // • read adapter — teamsReadAdapter (Microsoft Graph channel/thread history reads)
16
+ // • routine dispatch — resolveTeamsTarget (proactive routine fires need the captured Bot
17
+ // Framework conversation reference + the teams channel object, both of
18
+ // which now live in this bundle, so its resolver moved here too)
19
+ // • teams BRIDGE — the bundle→core seam for the routine fire-eligibility leg's Graph
20
+ // checks (OPE-522, mirroring the slack provider's own bridge):
21
+ // accountEnabled + channel-membership, keyed on the creator's Azure AD
22
+ // object id (channels/teams-fire-eligibility.ts, core channels/
23
+ // teams-bridge.ts)
24
+ // • bot display name — a HANDLE line on a Teams-pinned session, not identity since OPE-610,
25
+ // read from the app's OWN service principal via Graph (OPE-587;
26
+ // channels/teams-bot-name.ts, core identity/bot-display-name.ts)
27
+ // • account directory — the Bot Connector roster of the teams this deployment has seen, for
28
+ // the identity-linking directory transport (OPE-887;
29
+ // channels/teams-directory.ts). NOT Microsoft Graph — Graph has no `29:`
30
+ // id and a link keys on one; the header of that file carries the whole
31
+ // argument
32
+ // • surface message ops — teamsMessageOps: postText/editMessage (OPE-899), the transport behind
33
+ // the stop acknowledgement and the approval decision notice. Resolves
34
+ // its own serviceUrl from the `conversation`-grain address store
35
+ // (channels/teams-conversation-ref.ts), since the registry's callers
36
+ // hand it only a bare conversation id.
37
+ // • reaction surface — INBOUND ONLY (OPE-1502). Teams delivers `messageReaction` activities
38
+ // and refuses an application identity the outbound WRITE, so the
39
+ // feedback ingest is wired (channels/teams-reaction-feedback.ts) while
40
+ // the capability manifest still reads `reactions: false`
41
+ // • NO attachment resolver — the Teams surface carries no attachment plane today
42
+ import { registerIdentityMapper, registerCapabilityManifest, registerSurfaceParity, registerProviderEvents, registerReactionSurface, registerPostArm, registerWakeOriginCodec, registerReadAdapter, registerSeatCatchUp, registerRoutineDispatch, registerTeamsBridge, registerBotDisplayName, registerAccountDirectory, registerSurfaceMessageOps, registerProviderDocs, } from "@open-everywhere/core/agent/adapter-api.js";
43
+ import { PROVIDER_DOCS } from "./docs-generated.js";
44
+ import { TEAMS_SURFACE_PARITY } from "./surface-parity.js";
45
+ import { TEAMS_PROVIDER_EVENTS } from "./provider-events.js";
46
+ import { registerTeamsOps } from "./ops.js";
47
+ import { teamsMessageOps } from "./channels/teams-message-ops.js";
48
+ import teamsChannel from "./channels/teams.js";
49
+ import { bindTeams, teamsMode } from "./channels/teams-identity.js";
50
+ import { teamsPostArm } from "./channels/teams-post-arm.js";
51
+ import { teamsWakeOriginCodec } from "./channels/teams-origin-codec.js";
52
+ import { teamsReadAdapter } from "./channels/teams-read.js";
53
+ import { teamsSeatCatchUpFetch, TEAMS_TIMESTAMP_PRECISION_MS } from "./channels/teams-catch-up.js";
54
+ import { liveTeamsRoomMembership, liveTeamsAccountActive } from "./channels/teams-fire-eligibility.js";
55
+ import { teamsBotDisplayName } from "./channels/teams-bot-name.js";
56
+ import { fetchTeamsDirectory } from "./channels/teams-directory.js";
57
+ /** One stored-target field as a non-empty string, or undefined (never a coerced non-string — the
58
+ * store row is data, validated on the way out, not trusted). Local copy of the core dispatcher's
59
+ * private helper (a two-line structural read; not a barrel port). */
60
+ function storedString(t, key) {
61
+ const v = t?.[key];
62
+ return typeof v === "string" && v.length > 0 ? v : undefined;
63
+ }
64
+ /**
65
+ * Resolve a Teams routine to its proactive-fire DispatchTarget — MOVED VERBATIM out of core's
66
+ * schedules/dispatch.ts (OPE-114 stage 4). Proactive messaging on Teams REQUIRES a Bot Framework
67
+ * conversation reference (serviceUrl + conversation id) captured on a prior INBOUND turn — you
68
+ * cannot cold-send to a Teams user/channel the bot has never heard from. bindTeams captures exactly
69
+ * that off every inbound activity, and create_routine stores it on the routine, so by construction
70
+ * every Teams routine created in-thread carries its reference. A routine WITHOUT one (both fields
71
+ * are required by eve's teamsChannel().receive, which throws otherwise) fails closed to dry-run
72
+ * (null) here.
73
+ */
74
+ export function resolveTeamsTarget(r) {
75
+ const serviceUrl = storedString(r.target, "serviceUrl");
76
+ const conversationId = storedString(r.target, "conversationId");
77
+ if (!serviceUrl || !conversationId)
78
+ return null;
79
+ const conversationType = storedString(r.target, "conversationType");
80
+ const channelId = storedString(r.target, "channelId");
81
+ const teamId = storedString(r.target, "teamId");
82
+ // The creator's Azure AD object id (OPE-522) — stamped by bindTeams onto the routine's STORED
83
+ // target at creation time (channels/teams-identity.ts). Read back here into ATTRIBUTES, never
84
+ // into the fresh `target` below: `target` is what actually rides into the Bot Connector send
85
+ // (routine-dispatch.ts's DispatchTarget doc — "stored-target extras... feed attributes instead,
86
+ // never the adapter call"), and this value has no business in a Connector payload. The
87
+ // dispatcher's fire-eligibility leg reads it off `attributes.aad_object_id`.
88
+ const aadObjectId = storedString(r.target, "aadObjectId");
89
+ // tenant: the stored raw fact, else the surfaceKey's workspace segment (a tenant GUID is seg()-safe,
90
+ // so it round-trips verbatim — unlike the conversation id, whose ":"/"@" get sanitized in the key
91
+ // and MUST come from the stored target).
92
+ const tenantId = storedString(r.target, "tenantId") ?? r.surfaceKey.split("/")[1] ?? "";
93
+ // teamsMode is the one tested scope→mode place (personal→dm, groupChat→mpim); an absent stored
94
+ // scope resolves to "channel" (capped — the conservative arm).
95
+ const mode = teamsMode(conversationType);
96
+ // OPE-486 — the fire's WAKE ORIGIN, parity with resolveSlackTarget (routine-dispatch.ts). Absent
97
+ // before this fix, so a Teams fire could never divert into the unified window (fire-window.ts's
98
+ // planFireWindow fails closed on a missing origin). serviceUrl/conversationId are already
99
+ // non-empty-checked above (isTrustedTeamsServiceUrl re-validates serviceUrl in the codec's
100
+ // validate arm); no replyToActivityId — a proactive fire has no reply chain to anchor to, matching
101
+ // teams-front.ts's own ambient-origin mint (`{ platform: "teams", serviceUrl, conversationId }`).
102
+ const origin = { platform: "teams", serviceUrl, conversationId, ...(tenantId ? { tenantId } : {}) };
103
+ return {
104
+ channel: teamsChannel,
105
+ // Full TeamsReceiveTarget: conversationType lets eve anchor non-personal threads correctly;
106
+ // tenant/team/channel ids ride into the Connector's channelData.
107
+ target: {
108
+ serviceUrl,
109
+ conversationId,
110
+ ...(conversationType ? { conversationType } : {}),
111
+ ...(channelId ? { channelId } : {}),
112
+ ...(teamId ? { teamId } : {}),
113
+ ...(tenantId ? { tenantId } : {}),
114
+ },
115
+ mode,
116
+ // The facts bindTeams reads (workspace = tenant, surface = conversation). NO membership_type is
117
+ // stamped — it was never re-verified at fire time, so teamsTrust yields no verdict and bindFrom
118
+ // fails the fire closed to `external` (shared memory / domain skills stay off), matching what an
119
+ // inbound Teams activity without membershipType gets.
120
+ attributes: {
121
+ conversation_id: conversationId,
122
+ service_url: serviceUrl,
123
+ ...(tenantId ? { tenant_id: tenantId } : {}),
124
+ ...(channelId ? { channel_id: channelId } : {}),
125
+ ...(teamId ? { team_id: teamId } : {}),
126
+ ...(conversationType ? { scope: conversationType } : {}),
127
+ ...(aadObjectId ? { aad_object_id: aadObjectId } : {}),
128
+ },
129
+ origin,
130
+ };
131
+ }
132
+ /** Perform ALL of the teams bundle's registrations. Idempotent (each register call replaces);
133
+ * cheap and side-effect-free beyond the registry writes. */
134
+ export function registerTeamsProvider() {
135
+ registerIdentityMapper("teams", bindTeams);
136
+ // Bot-Connector proactive post wired via the host-side Connector write seam (channels/
137
+ // teams-connector.ts, OPE-1237 — the post arm sends a message activity into the captured
138
+ // conversation reference). No integration reaction primitive.
139
+ // closingProseDropped (OPE-2006): the Teams completion handler DROPS a turn's closing text and
140
+ // audits it. `reply` is the only route out.
141
+ registerCapabilityManifest("teams", { midTurnPost: true, reactions: false, closingProseDropped: true });
142
+ // The OPE-1499 parity ledger: every capability the chat-surface contract names, answered
143
+ // `supported` or `{ unsupported: "<reason>" }`. Gates nothing at runtime — `lint:surface-parity`
144
+ // reds on an unanswered row, and the contract's §7.1/§7.1.1/§7.2 tables are generated from it.
145
+ registerSurfaceParity("teams", TEAMS_SURFACE_PARITY);
146
+ // The OPE-1612 event inventory: every vendor event that could wake a routine, and how far the
147
+ // normalizer plane carries each one. Gates nothing at runtime — `lint:provider-events` reds a
148
+ // bundle that declares none or that promises a match key the normalizer does not declare, and
149
+ // the manual's inventory table is generated from it.
150
+ registerProviderEvents("teams", TEAMS_PROVIDER_EVENTS);
151
+ registerPostArm(teamsPostArm);
152
+ registerWakeOriginCodec("teams", teamsWakeOriginCodec);
153
+ // Teams channel/thread history reads ride Microsoft Graph (Bot Framework has no history API).
154
+ registerReadAdapter(teamsReadAdapter);
155
+ // THE SEAT CATCH-UP FETCH (OPE-1726): the channel (or reply chain) history since the seat's
156
+ // last wake, over Microsoft Graph — the same transport `read_channel` uses, and NOT the Bot
157
+ // Connector the wake arrives on. Core's shared path applies the bounds, the policy and the cap.
158
+ // The surface DECLARES the unit its own message stamps carry, and core widens both catch-up
159
+ // bounds by it (OPE-1847). A wrong or missing unit bounds the seat out of its own window.
160
+ registerSeatCatchUp("teams", teamsSeatCatchUpFetch, { timestampPrecisionMs: TEAMS_TIMESTAMP_PRECISION_MS });
161
+ // Proactive routine fires on the teams surface (needs the captured Bot Framework reference).
162
+ registerRoutineDispatch("teams", { resolveTarget: resolveTeamsTarget });
163
+ // The bundle→core bridge for the routine fire-eligibility leg's Graph checks (OPE-522) — core's
164
+ // routines/fire-eligibility.ts consumes these through channels/teams-bridge.ts, never Graph
165
+ // directly, mirroring the slack provider's own registerSlackBridge call.
166
+ registerTeamsBridge({ roomMembership: liveTeamsRoomMembership, accountActive: liveTeamsAccountActive });
167
+ // The bot's own display name (OPE-587) — core's per-surface registry arm, rendered as a HANDLE
168
+ // line, not identity, since OPE-610 settled the naming model. Reads the app's OWN service
169
+ // principal through the same Graph token the read adapter mints; needs no extra Azure consent
170
+ // (the app's implicit self-read, measured live). See channels/teams-bot-name.ts.
171
+ registerBotDisplayName("teams", teamsBotDisplayName);
172
+ // THE TEAMS ACCOUNT DIRECTORY (OPE-887) — the lookup the reverse-initiated link uses to NAME the
173
+ // other account instead of posting a bearer code where a room can read it. It walks the Bot
174
+ // Connector roster of the teams this deployment has captured a conversation reference for, so the
175
+ // ids it returns are the `29:` ids a Teams link actually keys on. The other half of the transport
176
+ // is the post arm's `deliverDirectMessage` — core requires BOTH before it offers the transport,
177
+ // and both rest on the same captured reference (channels/teams-conversation-ref.ts).
178
+ registerAccountDirectory("teams", (query) => fetchTeamsDirectory(query));
179
+ // THE STOP ACKNOWLEDGEMENT'S TRANSPORT (OPE-899) — postText/editMessage, so turn-anchor.ts's
180
+ // postSurfaceText resolves a real send instead of undefined on a Teams turn. No postFiles (no
181
+ // attachment plane) and no setReaction (no reaction primitive beyond the `angry` stop trigger).
182
+ registerSurfaceMessageOps(teamsMessageOps);
183
+ // REACTION-FEEDBACK INGEST (OPE-1502) — INBOUND only, and that is not a contradiction with the
184
+ // `reactions: false` manifest above. Teams refuses an application identity the outbound WRITE
185
+ // (§7.3's probe), while it delivers `messageReaction` activities inbound freely. The arm that
186
+ // records them is channels/teams-reaction-feedback.ts, reached from the stop arm's fan-out.
187
+ registerReactionSurface("teams");
188
+ // Shipped-manual plane (OPE-138): this bundle's own setup runbook (docs/deploy/surfaces/teams.md,
189
+ // compiled into ./docs-generated.ts because docs/ is not on disk at runtime). De-select the bundle
190
+ // and the module leaves the import graph; registerProviderDocs re-checks the selection gate anyway.
191
+ registerProviderDocs("teams", PROVIDER_DOCS);
192
+ // Ops plane (OPE-428): the live preflight probe that reports which Microsoft boundary governs
193
+ // channel reads. Split into ./ops.js so the STANDALONE ops MCP entry (repo-root
194
+ // scripts/ops-mcp.ts, which serves preflight with no agent boot) registers it without pulling
195
+ // the whole channel graph — the same split slack uses.
196
+ registerTeamsOps();
197
+ }
198
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SurfaceParityDeclaration } from "@open-everywhere/core/agent/adapter-api.js";
2
+ export declare const TEAMS_SURFACE_PARITY: SurfaceParityDeclaration;
3
+ //# sourceMappingURL=surface-parity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-parity.d.ts","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,oBAAoB,EAAE,wBAqGlC,CAAC"}
@@ -0,0 +1,106 @@
1
+ // TEAMS' surface-parity declaration (OPE-1499). See the core module's header
2
+ // (packages/core/agent/identity/surface-parity.ts) for what the three cell shapes mean.
3
+ //
4
+ // Some of the gaps below are PERMANENT vendor limits and some are NOT BUILT YET. The distinction is
5
+ // the whole point of writing a reason down: `react` and the ✋ glyph are things Microsoft does not
6
+ // let an application identity do, so no ticket will ever close them. Reaction-feedback ingest was
7
+ // the other kind — unwritten OE work — and OPE-1502 closed it, which is what the row now says.
8
+ export const TEAMS_SURFACE_PARITY = {
9
+ // --- registration seams (§7.1) ---------------------------------------------------------------
10
+ "identity-mapper": "supported",
11
+ "capability-manifest": "supported",
12
+ "post-arm": "supported",
13
+ "wake-origin-codec": "supported",
14
+ "unified-action-plane": {
15
+ unsupported: "the arm posts a plain message activity, and a button here needs an Adaptive Card PLUS an invoke route to receive the tap. `teams-front.ts` forwards every `invoke` to the native channel, whose HITL route resolves a tap against the TEAMS channel's own session — a unified seat's parked request lives on another session entirely, so an OE-minted card would render a button that settles nothing. Prose, which stands on its own, until that route exists",
16
+ },
17
+ "origin-placement-carry": {
18
+ unsupported: "the placement is INSIDE the conversation identity: `threadRef` keys on `replyToActivityId`, the very activity a reply hangs under, so two origins that pass the conversation test already agree on placement and there is no gap to carry",
19
+ },
20
+ "read-adapter": "supported",
21
+ // INBOUND reaction ingest is wired (OPE-1502); the OUTBOUND write below is not, and the two are
22
+ // independent. The note is the honest half: Microsoft delivers `messageReaction` only for messages
23
+ // the agent itself sent, and delivers no author for the reacted message — so the "is this the
24
+ // agent's own reply" test on this surface is that vendor fence plus a present `replyToId`, not the
25
+ // author comparison Slack, Discord and Linear make.
26
+ "reaction-feedback-ingest": { supported: "the vendor fence is the guarantee — Teams delivers the event only for the agent's own messages, and carries no author to compare" },
27
+ "ancillary-ops": "supported",
28
+ // WIRED, AND TENANT-CONDITIONAL — the qualified form, because a bare ✅ over-claimed it against
29
+ // the support matrix's own 🔧 row (OPE-1527). The seam is built and armed on every channel and
30
+ // group chat; whether a PLAIN follow-up ever reaches it is the tenant's RSC consent, which no API
31
+ // can probe (channels/teams-engagement.ts). Without the grant only @mention activities arrive, so
32
+ // the seam wakes nothing and the surface answers once per mention exactly as before.
33
+ "ambient-engagement-seam": {
34
+ supported: "the seam is wired; plain follow-ups reach it only where the tenant consented to `ChannelMessage.Read.Group` / `ChatMessage.Read.Chat`, which no API can probe",
35
+ },
36
+ // The single-window divert writes `plan.window.addressing ?? "channel-watch"` (teams-front.ts), so
37
+ // an engaged follow-up and unowned room chatter leave the same row. No journey reds on it today —
38
+ // `J-ENGAGED-teams` does not gate a dispatch addressing — so the gap is declared here rather than
39
+ // carried as a silent one.
40
+ "engaged-row-promotion": {
41
+ unsupported: "not built yet — the single-window divert writes the plan's own `addressing`, which calls an engaged follow-up and room chatter alike",
42
+ },
43
+ // The reply chain IS the thread on Teams, so the router reads `replyToActivityId` the way it
44
+ // reads Slack's `threadTs`. A plain conversation send starts its own chain and stays top-level.
45
+ // The personal/group-chat DM leg keeps the raw divert — it mints no reply-chain origin.
46
+ "owned-thread-ingress": { supported: "the channel leg only — a reply chain is the thread; the DM leg mints no `replyToActivityId`, so it can own none" },
47
+ // --- wake legs and conversation shapes -------------------------------------------------------
48
+ "addressed-leg": "supported",
49
+ // Not the engagement seam: the wake is the single-window front's Leg A, a different mechanism.
50
+ // The registry does suppress it, though — the front drops a stood-down conversation above both
51
+ // legs, for a conversation an @mention enrolled (§7.6).
52
+ "ambient-leg": { supported: "the single-window front's Leg A, not the §2.5 engagement registry" },
53
+ // 🔴 OVER GRAPH, NOT THE BOT CONNECTOR. The transport a Teams activity arrives on carries no
54
+ // history API — which is why `teams-supervisor.ts` once said this surface could not catch up at all
55
+ // — but `teams-catch-up.ts` reads `/teams/{team}/channels/{channel}/messages`, the same Graph call
56
+ // `read_channel` uses. A personal or group chat carries no team id, so it takes no catch-up.
57
+ "seat-catch-up": { supported: "over Microsoft Graph (channel activities only — a personal/group chat carries no team id)" },
58
+ // The slot is EMPTY on this surface: `teams-front.ts` builds no `contextLines`, so there is no pour
59
+ // to police. The seat's room context here is the catch-up read above and the carried tail, both of
60
+ // which already pass the domain's policy in core.
61
+ "seat-context-admission": { unsupported: "the hydration fills no context-line slot — the seat's room context is the catch-up read, which core already admits" },
62
+ // The same missing invoke route the component-plane row above names: a card needs an Adaptive Card
63
+ // PLUS a tap that resolves against the UNIFIED seat's parked request, and `teams-front.ts` forwards
64
+ // every `invoke` to the native channel's own session, so nothing here can card in place. See the
65
+ // roster row for what that costs and where it does NOT cost anything.
66
+ "approval-card": { unsupported: "no invoke route resolves a tap against a unified seat's parked request. A governed act that takes the venue walk is redirected to a card-capable room in the SAME domain, or refused when the domain holds none. The paths OUTSIDE that walk do not: the spend checkpoint (spend/checkpoint.ts `requireSessionContinuation`) fails OPEN here and records the crossing in an audit row instead" },
67
+ // THE TRACE ARRIVES EVEN THOUGH THE BUTTON CANNOT (OPE-1854). A judge-lifted act posts its
68
+ // notice here as a plain message activity through the shared road (`postJudgeLiftNotice`), on this
69
+ // surface's own `SurfaceMessageOps` transport. It carries the overrule as an INSTRUCTION in
70
+ // words, with the action id a reviewer finds the act by, because no tap can land here.
71
+ // 🔴 BARE, NOT `{ supported: "…" }`. A noted cell is exempt from the overclaim arm, and the
72
+ // arm is the point: drop this bundle's text transport and the notice silently stops arriving.
73
+ "judge-lift-notice": "supported",
74
+ "name-drop-mention": { unsupported: "not built yet — Leg A wakes on an @mention or room chatter, never on a name-drop match" },
75
+ // 🔴 THE ACTIVITY TYPE IS THE FILTER. Teams sends an edit as a `messageUpdate` activity, and the
76
+ // inbound parser admits `message`, `invoke` and `conversationUpdate` only, so the edit resolves to
77
+ // null before `teams-front.ts` sees it. `teams-front.ts` forwards every non-`message` activity to
78
+ // the native channel for the same reason — there is nothing on this surface to gate.
79
+ "message-edit-wake": { unsupported: "an edit arrives as a `messageUpdate` activity, and the inbound parser admits `message`, `invoke` and `conversationUpdate` only" },
80
+ // The `;messageid=` reply chain (§4.6.1).
81
+ threads: "supported",
82
+ rooms: "supported",
83
+ dm: "supported",
84
+ mpim: "supported",
85
+ // --- core verbs (§7.2) -----------------------------------------------------------------------
86
+ reply: "supported",
87
+ edit_reply: "supported",
88
+ // PERMANENT. Microsoft Graph carries an outbound reaction route, but it refuses the
89
+ // application-only context OE runs in — there is no primitive an app identity can drive (§7.3).
90
+ react: { unsupported: "vendor limit — Graph's outbound reaction route refuses an application-only identity" },
91
+ no_reply: "supported",
92
+ read_channel: "supported",
93
+ read_thread: "supported",
94
+ search: { unsupported: "no work-search adapter — Teams is a chat surface, not a work corpus (§4.7)" },
95
+ post_message: "supported",
96
+ dm_person: "supported",
97
+ set_dm_delivery: "supported",
98
+ // Teams' six fixed reaction values carry no raised hand, so the stop trigger is `angry` — the one
99
+ // of the six people already use to mean "this is wrong" (§4.8).
100
+ stop: { supported: "the `angry` reaction — Teams' six fixed values carry no ✋" },
101
+ ack_stop_glyph: { unsupported: "vendor limit — Teams' fixed six-value reaction vocabulary has no raised hand" },
102
+ ack_cancel_note: "supported",
103
+ stand_down: { supported: "marks the conversation row; refuses on a 1:1 and when no row exists" },
104
+ post_file: { unsupported: "not built yet — no Teams attachment transport is wired (§7.3)" },
105
+ };
106
+ //# sourceMappingURL=surface-parity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-parity.js","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"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"}