@openclaw/msteams 2026.3.13 → 2026.5.1-beta.1

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 (175) hide show
  1. package/api.ts +3 -0
  2. package/channel-config-api.ts +1 -0
  3. package/channel-plugin-api.ts +2 -0
  4. package/config-api.ts +4 -0
  5. package/contract-api.ts +4 -0
  6. package/index.ts +15 -12
  7. package/openclaw.plugin.json +553 -1
  8. package/package.json +46 -12
  9. package/runtime-api.ts +73 -0
  10. package/secret-contract-api.ts +5 -0
  11. package/setup-entry.ts +13 -0
  12. package/setup-plugin-api.ts +3 -0
  13. package/src/ai-entity.ts +7 -0
  14. package/src/approval-auth.ts +44 -0
  15. package/src/attachments/bot-framework.test.ts +461 -0
  16. package/src/attachments/bot-framework.ts +362 -0
  17. package/src/attachments/download.ts +63 -19
  18. package/src/attachments/graph.test.ts +416 -0
  19. package/src/attachments/graph.ts +163 -72
  20. package/src/attachments/html.ts +33 -1
  21. package/src/attachments/payload.ts +1 -1
  22. package/src/attachments/remote-media.test.ts +137 -0
  23. package/src/attachments/remote-media.ts +75 -8
  24. package/src/attachments/shared.test.ts +138 -1
  25. package/src/attachments/shared.ts +193 -26
  26. package/src/attachments/types.ts +10 -0
  27. package/src/attachments.graph.test.ts +342 -0
  28. package/src/attachments.helpers.test.ts +246 -0
  29. package/src/attachments.test-helpers.ts +17 -0
  30. package/src/attachments.test.ts +163 -418
  31. package/src/attachments.ts +5 -5
  32. package/src/block-streaming-config.test.ts +61 -0
  33. package/src/channel-api.ts +1 -0
  34. package/src/channel.actions.test.ts +742 -0
  35. package/src/channel.directory.test.ts +145 -4
  36. package/src/channel.runtime.ts +56 -0
  37. package/src/channel.setup.ts +77 -0
  38. package/src/channel.test.ts +128 -0
  39. package/src/channel.ts +1077 -395
  40. package/src/config-schema.ts +6 -0
  41. package/src/config-ui-hints.ts +12 -0
  42. package/src/conversation-store-fs.test.ts +4 -5
  43. package/src/conversation-store-fs.ts +35 -51
  44. package/src/conversation-store-helpers.test.ts +202 -0
  45. package/src/conversation-store-helpers.ts +105 -0
  46. package/src/conversation-store-memory.ts +27 -23
  47. package/src/conversation-store.shared.test.ts +225 -0
  48. package/src/conversation-store.ts +30 -0
  49. package/src/directory-live.test.ts +156 -0
  50. package/src/directory-live.ts +7 -4
  51. package/src/doctor.ts +27 -0
  52. package/src/errors.test.ts +64 -1
  53. package/src/errors.ts +50 -9
  54. package/src/feedback-reflection-prompt.ts +117 -0
  55. package/src/feedback-reflection-store.ts +114 -0
  56. package/src/feedback-reflection.test.ts +237 -0
  57. package/src/feedback-reflection.ts +283 -0
  58. package/src/file-consent-helpers.test.ts +83 -0
  59. package/src/file-consent-helpers.ts +64 -11
  60. package/src/file-consent-invoke.ts +150 -0
  61. package/src/file-consent.test.ts +363 -0
  62. package/src/file-consent.ts +165 -4
  63. package/src/graph-chat.ts +5 -3
  64. package/src/graph-group-management.test.ts +318 -0
  65. package/src/graph-group-management.ts +168 -0
  66. package/src/graph-members.test.ts +89 -0
  67. package/src/graph-members.ts +48 -0
  68. package/src/graph-messages.actions.test.ts +243 -0
  69. package/src/graph-messages.read.test.ts +391 -0
  70. package/src/graph-messages.search.test.ts +213 -0
  71. package/src/graph-messages.test-helpers.ts +50 -0
  72. package/src/graph-messages.ts +534 -0
  73. package/src/graph-teams.test.ts +215 -0
  74. package/src/graph-teams.ts +114 -0
  75. package/src/graph-thread.test.ts +246 -0
  76. package/src/graph-thread.ts +146 -0
  77. package/src/graph-upload.test.ts +161 -4
  78. package/src/graph-upload.ts +147 -56
  79. package/src/graph.test.ts +516 -0
  80. package/src/graph.ts +233 -21
  81. package/src/inbound.test.ts +156 -1
  82. package/src/inbound.ts +101 -1
  83. package/src/media-helpers.ts +1 -1
  84. package/src/mentions.test.ts +27 -18
  85. package/src/mentions.ts +2 -2
  86. package/src/messenger.test.ts +504 -23
  87. package/src/messenger.ts +133 -52
  88. package/src/monitor-handler/access.ts +125 -0
  89. package/src/monitor-handler/inbound-media.test.ts +289 -0
  90. package/src/monitor-handler/inbound-media.ts +57 -5
  91. package/src/monitor-handler/message-handler-mock-support.test-support.ts +28 -0
  92. package/src/monitor-handler/message-handler.authz.test.ts +588 -74
  93. package/src/monitor-handler/message-handler.dm-media.test.ts +54 -0
  94. package/src/monitor-handler/message-handler.test-support.ts +100 -0
  95. package/src/monitor-handler/message-handler.thread-parent.test.ts +223 -0
  96. package/src/monitor-handler/message-handler.thread-session.test.ts +77 -0
  97. package/src/monitor-handler/message-handler.ts +470 -164
  98. package/src/monitor-handler/reaction-handler.test.ts +267 -0
  99. package/src/monitor-handler/reaction-handler.ts +210 -0
  100. package/src/monitor-handler/thread-session.ts +17 -0
  101. package/src/monitor-handler.adaptive-card.test.ts +162 -0
  102. package/src/monitor-handler.feedback-authz.test.ts +314 -0
  103. package/src/monitor-handler.file-consent.test.ts +281 -79
  104. package/src/monitor-handler.sso.test.ts +563 -0
  105. package/src/monitor-handler.test-helpers.ts +180 -0
  106. package/src/monitor-handler.ts +459 -115
  107. package/src/monitor-handler.types.ts +27 -0
  108. package/src/monitor-types.ts +1 -0
  109. package/src/monitor.lifecycle.test.ts +74 -10
  110. package/src/monitor.test.ts +35 -1
  111. package/src/monitor.ts +143 -46
  112. package/src/oauth.flow.ts +77 -0
  113. package/src/oauth.shared.ts +37 -0
  114. package/src/oauth.test.ts +305 -0
  115. package/src/oauth.token.ts +158 -0
  116. package/src/oauth.ts +130 -0
  117. package/src/outbound.test.ts +10 -11
  118. package/src/outbound.ts +62 -44
  119. package/src/pending-uploads-fs.test.ts +246 -0
  120. package/src/pending-uploads-fs.ts +235 -0
  121. package/src/pending-uploads.test.ts +173 -0
  122. package/src/pending-uploads.ts +34 -2
  123. package/src/policy.test.ts +11 -5
  124. package/src/policy.ts +5 -5
  125. package/src/polls.test.ts +106 -5
  126. package/src/polls.ts +15 -7
  127. package/src/presentation.ts +68 -0
  128. package/src/probe.test.ts +27 -8
  129. package/src/probe.ts +43 -9
  130. package/src/reply-dispatcher.test.ts +437 -0
  131. package/src/reply-dispatcher.ts +259 -73
  132. package/src/reply-stream-controller.test.ts +235 -0
  133. package/src/reply-stream-controller.ts +147 -0
  134. package/src/resolve-allowlist.test.ts +105 -1
  135. package/src/resolve-allowlist.ts +112 -7
  136. package/src/runtime.ts +6 -3
  137. package/src/sdk-types.ts +43 -3
  138. package/src/sdk.test.ts +666 -0
  139. package/src/sdk.ts +867 -16
  140. package/src/secret-contract.ts +49 -0
  141. package/src/secret-input.ts +1 -1
  142. package/src/send-context.ts +76 -9
  143. package/src/send.test.ts +389 -5
  144. package/src/send.ts +140 -32
  145. package/src/sent-message-cache.ts +30 -18
  146. package/src/session-route.ts +40 -0
  147. package/src/setup-core.ts +160 -0
  148. package/src/setup-surface.test.ts +202 -0
  149. package/src/setup-surface.ts +320 -0
  150. package/src/sso-token-store.test.ts +72 -0
  151. package/src/sso-token-store.ts +166 -0
  152. package/src/sso.ts +300 -0
  153. package/src/storage.ts +1 -1
  154. package/src/store-fs.ts +2 -2
  155. package/src/streaming-message.test.ts +262 -0
  156. package/src/streaming-message.ts +297 -0
  157. package/src/test-runtime.ts +1 -1
  158. package/src/thread-parent-context.test.ts +224 -0
  159. package/src/thread-parent-context.ts +159 -0
  160. package/src/token.test.ts +237 -50
  161. package/src/token.ts +162 -7
  162. package/src/user-agent.test.ts +86 -0
  163. package/src/user-agent.ts +53 -0
  164. package/src/webhook-timeouts.ts +27 -0
  165. package/src/welcome-card.test.ts +81 -0
  166. package/src/welcome-card.ts +57 -0
  167. package/test-api.ts +1 -0
  168. package/tsconfig.json +16 -0
  169. package/CHANGELOG.md +0 -107
  170. package/src/file-lock.ts +0 -1
  171. package/src/graph-users.test.ts +0 -66
  172. package/src/onboarding.ts +0 -381
  173. package/src/polls-store.test.ts +0 -38
  174. package/src/revoked-context.test.ts +0 -39
  175. package/src/token-response.test.ts +0 -23
@@ -0,0 +1,180 @@
1
+ import { vi } from "vitest";
2
+ import type { OpenClawConfig, PluginRuntime, RuntimeEnv } from "../runtime-api.js";
3
+ import type { MSTeamsConversationStore } from "./conversation-store.js";
4
+ import type { MSTeamsAdapter } from "./messenger.js";
5
+ import type { MSTeamsActivityHandler, MSTeamsMessageHandlerDeps } from "./monitor-handler.js";
6
+ import type { MSTeamsPollStore } from "./polls.js";
7
+ import { setMSTeamsRuntime } from "./runtime.js";
8
+
9
+ type RuntimeRoutePeer = { peer: { kind: string; id: string } };
10
+
11
+ type MSTeamsTestRuntimeOptions = {
12
+ enqueueSystemEvent?: ReturnType<typeof vi.fn>;
13
+ readAllowFromStore?: ReturnType<typeof vi.fn>;
14
+ upsertPairingRequest?: ReturnType<typeof vi.fn>;
15
+ recordInboundSession?: ReturnType<typeof vi.fn>;
16
+ resolveAgentRoute?: (params: RuntimeRoutePeer) => unknown;
17
+ resolveTextChunkLimit?: () => number;
18
+ resolveStorePath?: () => string;
19
+ };
20
+
21
+ export function installMSTeamsTestRuntime(options: MSTeamsTestRuntimeOptions = {}): void {
22
+ const runPrepared = vi.fn(
23
+ async (turn: Parameters<PluginRuntime["channel"]["turn"]["runPrepared"]>[0]) => {
24
+ await turn.recordInboundSession({
25
+ storePath: turn.storePath,
26
+ sessionKey: turn.ctxPayload.SessionKey ?? turn.routeSessionKey,
27
+ ctx: turn.ctxPayload,
28
+ groupResolution: turn.record?.groupResolution,
29
+ createIfMissing: turn.record?.createIfMissing,
30
+ updateLastRoute: turn.record?.updateLastRoute,
31
+ onRecordError: turn.record?.onRecordError ?? (() => undefined),
32
+ });
33
+ const dispatchResult = await turn.runDispatch();
34
+ return {
35
+ admission: { kind: "dispatch" as const },
36
+ dispatched: true,
37
+ ctxPayload: turn.ctxPayload,
38
+ routeSessionKey: turn.routeSessionKey,
39
+ dispatchResult,
40
+ };
41
+ },
42
+ );
43
+ const run = vi.fn(async (params: Parameters<PluginRuntime["channel"]["turn"]["run"]>[0]) => {
44
+ const input = await params.adapter.ingest(params.raw);
45
+ if (!input) {
46
+ return { admission: { kind: "drop" as const, reason: "ingest-null" }, dispatched: false };
47
+ }
48
+ const eventClass = (await params.adapter.classify?.(input)) ?? {
49
+ kind: "message" as const,
50
+ canStartAgentTurn: true,
51
+ };
52
+ const preflightResult = await params.adapter.preflight?.(input, eventClass);
53
+ const preflight =
54
+ preflightResult && "kind" in preflightResult
55
+ ? { admission: preflightResult }
56
+ : (preflightResult ?? {});
57
+ const turn = await params.adapter.resolveTurn(input, eventClass, preflight);
58
+ if ("runDispatch" in turn) {
59
+ return await runPrepared(turn);
60
+ }
61
+ throw new Error("msteams test runtime only supports prepared turn dispatch");
62
+ });
63
+ setMSTeamsRuntime({
64
+ logging: { shouldLogVerbose: () => false },
65
+ system: { enqueueSystemEvent: options.enqueueSystemEvent ?? vi.fn() },
66
+ channel: {
67
+ debounce: {
68
+ resolveInboundDebounceMs: () => 0,
69
+ createInboundDebouncer: <T>(params: {
70
+ onFlush: (entries: T[]) => Promise<void>;
71
+ }): { enqueue: (entry: T) => Promise<void> } => ({
72
+ enqueue: async (entry: T) => {
73
+ await params.onFlush([entry]);
74
+ },
75
+ }),
76
+ },
77
+ pairing: {
78
+ readAllowFromStore: options.readAllowFromStore ?? vi.fn(async () => []),
79
+ upsertPairingRequest: options.upsertPairingRequest ?? vi.fn(async () => null),
80
+ },
81
+ text: {
82
+ hasControlCommand: () => false,
83
+ resolveChunkMode: () => "length",
84
+ resolveMarkdownTableMode: () => "code",
85
+ ...(options.resolveTextChunkLimit
86
+ ? { resolveTextChunkLimit: options.resolveTextChunkLimit }
87
+ : {}),
88
+ },
89
+ routing: {
90
+ resolveAgentRoute:
91
+ options.resolveAgentRoute ??
92
+ (({ peer }: RuntimeRoutePeer) => ({
93
+ sessionKey: `msteams:${peer.kind}:${peer.id}`,
94
+ agentId: "default",
95
+ accountId: "default",
96
+ })),
97
+ },
98
+ reply: {
99
+ createReplyDispatcherWithTyping: () => ({
100
+ dispatcher: {},
101
+ replyOptions: {},
102
+ markDispatchIdle: vi.fn(),
103
+ }),
104
+ formatAgentEnvelope: ({ body }: { body: string }) => body,
105
+ finalizeInboundContext: <T extends Record<string, unknown>>(ctx: T) => ctx,
106
+ resolveHumanDelayConfig: () => undefined,
107
+ },
108
+ session: {
109
+ recordInboundSession: options.recordInboundSession ?? vi.fn(async () => undefined),
110
+ ...(options.resolveStorePath ? { resolveStorePath: options.resolveStorePath } : {}),
111
+ },
112
+ turn: {
113
+ run: run as unknown as PluginRuntime["channel"]["turn"]["run"],
114
+ runPrepared: runPrepared as unknown as PluginRuntime["channel"]["turn"]["runPrepared"],
115
+ },
116
+ },
117
+ } as unknown as PluginRuntime);
118
+ }
119
+
120
+ export function createActivityHandler(
121
+ run = vi.fn(async () => undefined),
122
+ ): MSTeamsActivityHandler & {
123
+ run: NonNullable<MSTeamsActivityHandler["run"]>;
124
+ } {
125
+ let handler: MSTeamsActivityHandler & {
126
+ run: NonNullable<MSTeamsActivityHandler["run"]>;
127
+ };
128
+ handler = {
129
+ onMessage: () => handler,
130
+ onMembersAdded: () => handler,
131
+ onReactionsAdded: () => handler,
132
+ onReactionsRemoved: () => handler,
133
+ run,
134
+ };
135
+ return handler;
136
+ }
137
+
138
+ export function createMSTeamsMessageHandlerDeps(params?: {
139
+ cfg?: OpenClawConfig;
140
+ runtime?: RuntimeEnv;
141
+ }): MSTeamsMessageHandlerDeps {
142
+ const adapter: MSTeamsAdapter = {
143
+ continueConversation: async () => {},
144
+ process: async () => {},
145
+ updateActivity: async () => {},
146
+ deleteActivity: async () => {},
147
+ };
148
+ const conversationStore: MSTeamsConversationStore = {
149
+ upsert: async () => {},
150
+ get: async () => null,
151
+ list: async () => [],
152
+ remove: async () => false,
153
+ findPreferredDmByUserId: async () => null,
154
+ findByUserId: async () => null,
155
+ };
156
+ const pollStore: MSTeamsPollStore = {
157
+ createPoll: async () => {},
158
+ getPoll: async () => null,
159
+ recordVote: async () => null,
160
+ };
161
+
162
+ return {
163
+ cfg: params?.cfg ?? {},
164
+ runtime: (params?.runtime ?? { error: vi.fn() }) as RuntimeEnv,
165
+ appId: "test-app-id",
166
+ adapter,
167
+ tokenProvider: {
168
+ getAccessToken: async () => "token",
169
+ },
170
+ textLimit: 4000,
171
+ mediaMaxBytes: 8 * 1024 * 1024,
172
+ conversationStore,
173
+ pollStore,
174
+ log: {
175
+ info: vi.fn(),
176
+ error: vi.fn(),
177
+ debug: vi.fn(),
178
+ },
179
+ };
180
+ }