@mastra/teams 0.0.0 → 0.1.0-alpha.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.
@@ -0,0 +1,428 @@
1
+ import { ChannelAdapterConfig, ChannelConfig, ChannelConnectResult, ChannelHandlers, ChannelInstallationInfo, ChannelPlatformInfo, ChannelProvider, StreamingConfig, WaitUntilFn } from "@mastra/core/channels";
2
+ import { ChannelsStorage } from "@mastra/core/storage";
3
+ import { TeamsAdapter, TeamsAdapter as TeamsAdapter$1, TeamsAdapterConfig, createTeamsAdapter } from "@chat-adapter/teams";
4
+ import { Mastra } from "@mastra/core/mastra";
5
+ import { ApiRoute } from "@mastra/core/server";
6
+ //#region src/types.d.ts
7
+ /** Microsoft Graph origin used for Entra application provisioning. */
8
+ declare const GRAPH_API_BASE_URL = "https://graph.microsoft.com";
9
+ /** Teams Developer Portal origin used for Bot Framework registrations. */
10
+ declare const DEV_PORTAL_BASE_URL = "https://dev.teams.microsoft.com";
11
+ /** Microsoft login origin used to validate bot credentials (client-credentials mint). */
12
+ declare const LOGIN_BASE_URL = "https://login.microsoftonline.com";
13
+ /**
14
+ * OAuth scope for Microsoft Graph control-plane calls (create Entra apps,
15
+ * mint client secrets). Passed to the delegated {@link TeamsTokenResolver}.
16
+ */
17
+ declare const TEAMS_GRAPH_SCOPE = "https://graph.microsoft.com/.default";
18
+ /**
19
+ * OAuth scope for the Teams Developer Portal API (bot registrations).
20
+ * Tokens for this audience are distinct from Graph tokens — a single access
21
+ * token cannot serve both APIs. Passed to the delegated
22
+ * {@link TeamsTokenResolver}.
23
+ */
24
+ declare const TEAMS_DEV_PORTAL_SCOPE = "https://dev.teams.microsoft.com/AppDefinitions.ReadWrite";
25
+ /**
26
+ * Teams Developer Portal page where minted bot registrations are managed and
27
+ * packaged into a Teams app for distribution.
28
+ */
29
+ declare const DEV_PORTAL_BOTS_URL = "https://dev.teams.microsoft.com/bots";
30
+ /**
31
+ * Resolve an access token for a Microsoft OAuth scope on demand.
32
+ *
33
+ * Teams provisioning spans two token audiences — Microsoft Graph
34
+ * ({@link TEAMS_GRAPH_SCOPE}) for Entra application management and the Teams
35
+ * Developer Portal ({@link TEAMS_DEV_PORTAL_SCOPE}) for bot registrations — so
36
+ * unlike the Slack/Telegram resolvers this one is scope-aware: the provider
37
+ * passes the scope it needs and the resolver returns a token minted for that
38
+ * audience.
39
+ */
40
+ type TeamsTokenResolver = (scope: string | string[], tenantId?: string) => Promise<string>;
41
+ /**
42
+ * Self-managed credentials: bring your own Azure Bot registration. The
43
+ * Microsoft App ID / password are supplied directly (provider defaults and/or
44
+ * per-`connect()`) and persisted in the install store. Mutually exclusive with
45
+ * {@link TeamsDelegatedCredentialsConfig}.
46
+ */
47
+ interface TeamsSelfManagedCredentialsConfig {
48
+ /** Microsoft App (client) ID of an existing bot registration. */
49
+ appId?: string;
50
+ /** Client secret for {@link appId}. */
51
+ appPassword?: string;
52
+ tokenResolver?: never;
53
+ }
54
+ /**
55
+ * Delegated credentials: an external credential manager (e.g. the Mastra
56
+ * platform) owns a *manager* credential that can provision bots. The provider
57
+ * calls the resolver with the scope it needs ({@link TEAMS_GRAPH_SCOPE} or
58
+ * {@link TEAMS_DEV_PORTAL_SCOPE}) during `connect()`/`disconnect()` to mint
59
+ * per-agent Entra applications and Developer Portal bot registrations.
60
+ *
61
+ * The manager credential is used only at provisioning time. Each provisioned
62
+ * bot gets its own client secret, stored (encrypted) in the install store, and
63
+ * the runtime authenticates with Bot Framework using that per-agent secret —
64
+ * no manager-credential round-trip on the message path.
65
+ *
66
+ * Mutually exclusive with direct `appId`/`appPassword` credentials.
67
+ */
68
+ interface TeamsDelegatedCredentialsConfig {
69
+ /** Resolve a manager access token for the given Microsoft OAuth scope. */
70
+ tokenResolver: TeamsTokenResolver;
71
+ appId?: never;
72
+ appPassword?: never;
73
+ }
74
+ /**
75
+ * How the provider obtains bot credentials: either directly
76
+ * (`appId`/`appPassword`, self-managed) or by provisioning per-agent bots via
77
+ * a scope-aware `tokenResolver` (delegated) — never both.
78
+ */
79
+ type TeamsCredentialsConfig = TeamsSelfManagedCredentialsConfig | TeamsDelegatedCredentialsConfig;
80
+ /**
81
+ * Configuration for {@link TeamsProvider}.
82
+ */
83
+ interface TeamsProviderConfigBase {
84
+ /**
85
+ * Public HTTPS base URL used as the bot messaging endpoint
86
+ * (`{baseUrl}/teams/events/{webhookId}`). May be omitted and auto-detected
87
+ * from the Mastra server config.
88
+ */
89
+ baseUrl?: string;
90
+ /**
91
+ * Persistence for bot installations. Defaults to Mastra's channels storage
92
+ * when available, falling back to an in-memory store (dev/test only).
93
+ */
94
+ storage?: ChannelsStorage;
95
+ /**
96
+ * Passphrase for encrypting the per-bot client secret at rest (AES-256-GCM).
97
+ * Defaults to the `MASTRA_ENCRYPTION_KEY` env var.
98
+ */
99
+ encryptionKey?: string;
100
+ /** Entra tenant ID for single-tenant bots. */
101
+ appTenantId?: string;
102
+ /**
103
+ * Bot application audience. Provisioned (delegated) bots default to
104
+ * `MultiTenant`.
105
+ * @default 'MultiTenant'
106
+ */
107
+ appType?: 'MultiTenant' | 'SingleTenant';
108
+ /** Override the Bot Framework service URL (e.g. sovereign clouds). Forwarded to the adapter. */
109
+ apiUrl?: string;
110
+ /** Override Microsoft Graph origin (tests / sovereign clouds). @default 'https://graph.microsoft.com' */
111
+ graphBaseUrl?: string;
112
+ /** Override the Teams Developer Portal origin (tests). @default 'https://dev.teams.microsoft.com' */
113
+ devPortalBaseUrl?: string;
114
+ /** Override the Microsoft login origin used for credential validation (tests). @default 'https://login.microsoftonline.com' */
115
+ loginBaseUrl?: string;
116
+ /** Icon URL recorded on provisioned bot registrations. */
117
+ botIconUrl?: string;
118
+ /**
119
+ * Keep the serverless invocation alive while the agent stream runs after the
120
+ * webhook returns 200. See `ChannelConfig.waitUntil`.
121
+ */
122
+ waitUntil?: WaitUntilFn;
123
+ /**
124
+ * Stream agent text to Teams as it generates (native Teams streaming in DMs,
125
+ * post-and-edit elsewhere — handled by the adapter).
126
+ * @default true
127
+ */
128
+ streaming?: StreamingConfig;
129
+ /**
130
+ * Keep a typing indicator alive during generation.
131
+ * @default true
132
+ */
133
+ typingStatus?: boolean;
134
+ /** Override built-in event handlers. Forwarded to `AgentChannels`. */
135
+ handlers?: ChannelHandlers;
136
+ /** Which media types to send inline to the model. See `ChannelConfig.inlineMedia`. */
137
+ inlineMedia?: ChannelConfig['inlineMedia'];
138
+ /** Promote URLs in message text to file parts. See `ChannelConfig.inlineLinks`. */
139
+ inlineLinks?: ChannelConfig['inlineLinks'];
140
+ /** State adapter for deduplication, locking, and subscriptions. See `ChannelConfig.state`. */
141
+ state?: ChannelConfig['state'];
142
+ /** Fetch recent thread messages when the agent joins mid-conversation. See `ChannelConfig.threadContext`. */
143
+ threadContext?: ChannelConfig['threadContext'];
144
+ /** Additional options passed directly to the Chat SDK. See `ChannelConfig.chatOptions`. */
145
+ chatOptions?: ChannelConfig['chatOptions'];
146
+ /** Resolve the memory `resourceId` before a channel thread is created. See `ChannelConfig.resolveResourceId`. */
147
+ resolveResourceId?: ChannelConfig['resolveResourceId'];
148
+ /** Resolve `waitUntil` from the request's Hono `Context`. See `ChannelConfig.resolveWaitUntil`. */
149
+ resolveWaitUntil?: ChannelConfig['resolveWaitUntil'];
150
+ /** CORS configuration for the generated Teams webhook route. */
151
+ cors?: ChannelAdapterConfig['cors'];
152
+ /** Override how errors are rendered in Teams messages. See `ChannelAdapterConfig.formatError`. */
153
+ formatError?: ChannelAdapterConfig['formatError'];
154
+ /** How tool calls are rendered in the reply. See `ChannelAdapterConfig.toolDisplay`. */
155
+ toolDisplay?: ChannelAdapterConfig['toolDisplay'];
156
+ /** Whether to expose channel reaction tools to the agent. See `ChannelConfig.tools`. */
157
+ tools?: ChannelConfig['tools'];
158
+ /** Logger forwarded to the underlying `TeamsAdapter`. */
159
+ logger?: TeamsAdapterConfig['logger'];
160
+ /** Called after an agent successfully connects and the installation is persisted. */
161
+ onInstall?: (installation: TeamsInstallation) => void | Promise<void>;
162
+ }
163
+ /** See {@link TeamsProviderConfigBase} and {@link TeamsCredentialsConfig}. */
164
+ type TeamsProviderConfig = TeamsProviderConfigBase & TeamsCredentialsConfig;
165
+ /** Options accepted by {@link TeamsProvider.connect}. */
166
+ interface TeamsConnectOptions {
167
+ /** Display name for the bot. Defaults to the agent id. */
168
+ name?: string;
169
+ /**
170
+ * Microsoft App (client) ID of an existing bot registration (self-managed
171
+ * mode). Falls back to the provider-level `appId`. Rejected in delegated
172
+ * mode, where bots are provisioned per agent.
173
+ */
174
+ appId?: string;
175
+ /** Client secret for {@link appId} (self-managed mode). Falls back to the provider-level `appPassword`. */
176
+ appPassword?: string;
177
+ /** Entra tenant ID for single-tenant bots. Falls back to the provider-level `appTenantId`. */
178
+ appTenantId?: string;
179
+ }
180
+ /**
181
+ * A Teams bot bound to a single agent (one bot = one agent).
182
+ * Persisted through {@link TeamsInstallStore}.
183
+ */
184
+ interface TeamsInstallation {
185
+ /** Stable installation id. */
186
+ id: string;
187
+ /** The agent this bot is bound to. */
188
+ agentId: string;
189
+ /**
190
+ * Opaque id embedded in the messaging endpoint path
191
+ * (`/teams/events/:webhookId`). Inbound requests are authenticated by
192
+ * Microsoft's JWT signature (verified by the adapter), not by this id.
193
+ */
194
+ webhookId: string;
195
+ /** Whether the bot is provisioned/validated and routable. */
196
+ status: 'active' | 'pending';
197
+ /** Microsoft App (client) ID of the bot. */
198
+ appId?: string;
199
+ /**
200
+ * Entra application **object id** — only set for bots this provider
201
+ * provisioned (delegated mode); used to delete the application on
202
+ * disconnect.
203
+ */
204
+ entraObjectId?: string;
205
+ /** Client secret the bot authenticates to Bot Framework with (encrypted at rest). */
206
+ appPassword?: string;
207
+ /** Entra tenant ID for single-tenant bots. */
208
+ appTenantId?: string;
209
+ /** Bot application audience. */
210
+ appType?: 'MultiTenant' | 'SingleTenant';
211
+ /** Display name of the bot. */
212
+ botName?: string;
213
+ /** The messaging endpoint registered for the bot. */
214
+ messagingEndpoint?: string;
215
+ /** When the installation was created. */
216
+ installedAt: Date;
217
+ }
218
+ //#endregion
219
+ //#region src/teams-provider.d.ts
220
+ /**
221
+ * Resolve the per-adapter streaming/typing config the provider applies to the
222
+ * Teams entry in `AgentChannels.adapters` — both default on.
223
+ */
224
+ declare function resolveTeamsAdapterConfig(config: Pick<TeamsProviderConfig, 'streaming' | 'typingStatus'>): {
225
+ streaming: StreamingConfig;
226
+ typingStatus: boolean;
227
+ };
228
+ /**
229
+ * Microsoft Teams channel provider for Mastra — a {@link ChannelProvider} over
230
+ * `@chat-adapter/teams`. The adapter handles the Bot Framework transport
231
+ * (activity parse, JWT webhook verification, send/stream, typing, adaptive
232
+ * cards); this provider adds the install/lifecycle layer.
233
+ *
234
+ * Credential modes (mutually exclusive, enforced at the type level):
235
+ *
236
+ * - **Self-managed** — bring your own Azure Bot registration: pass
237
+ * `appId`/`appPassword` (provider-level or per-`connect()`). Point the bot's
238
+ * messaging endpoint at `{baseUrl}/teams/events/{webhookId}`.
239
+ * - **Delegated** — pass a scope-aware `tokenResolver` for a *manager*
240
+ * credential; `connect(agentId)` then provisions a bot per agent: an Entra
241
+ * application (Microsoft Graph), a fresh client secret, and a Teams
242
+ * Developer Portal bot registration pointing at this server. The per-agent
243
+ * secret is stored (encrypted) and used by the runtime — the manager
244
+ * credential is never needed on the message path.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * const teams = new TeamsProvider({ baseUrl: 'https://my-app.example.com', tokenResolver });
249
+ * const mastra = new Mastra({ agents: { myAgent }, channels: { teams } });
250
+ * await teams.connect('my-agent'); // → { type: 'deep_link', url: 'https://dev.teams.microsoft.com/bots' }
251
+ * ```
252
+ */
253
+ declare class TeamsProvider implements ChannelProvider {
254
+ #private;
255
+ readonly id = "teams";
256
+ constructor(config?: TeamsProviderConfig);
257
+ /**
258
+ * Called by Mastra when this channel is registered.
259
+ * @internal
260
+ */
261
+ __attach(mastra: Mastra): void;
262
+ /**
263
+ * Per-bot messaging endpoint. A single POST route keyed by an opaque
264
+ * `webhookId`; inbound requests are authenticated by Microsoft's JWT
265
+ * signature (verified by the adapter against the bot's `appId`), not by the
266
+ * path. Auto-initializes on first hit (mirrors `@mastra/slack`).
267
+ */
268
+ getRoutes(): ApiRoute[];
269
+ /** Discovery metadata for the editor UI. */
270
+ getInfo(): ChannelPlatformInfo;
271
+ /**
272
+ * Restore installations from storage: rebuild an adapter per active bot and
273
+ * inject `AgentChannels` so the agent can receive events immediately.
274
+ * Idempotent. Does not re-register messaging endpoints (they persist in the
275
+ * bot registration across restarts); reconnect an agent if its `baseUrl` changed.
276
+ */
277
+ initialize(): Promise<void>;
278
+ /**
279
+ * Update runtime provider settings. Pass `appId`/`appPassword` to change the
280
+ * default bot credentials new {@link connect} calls fall back to; pass
281
+ * `baseUrl`/`apiUrl` to point the provider/adapter at a different host.
282
+ * `null` clears the default credentials only — per-bot installs are managed
283
+ * via {@link connect}/{@link disconnect}.
284
+ */
285
+ configure(credentials: {
286
+ appId?: string;
287
+ appPassword?: string;
288
+ appTenantId?: string;
289
+ baseUrl?: string;
290
+ apiUrl?: string;
291
+ } | null): Promise<void>;
292
+ /**
293
+ * Connect an agent to Microsoft Teams.
294
+ *
295
+ * - **Delegated** (`tokenResolver`): provisions a per-agent bot — Entra
296
+ * application + client secret via Microsoft Graph, then a Teams Developer
297
+ * Portal bot registration whose messaging endpoint points at this server —
298
+ * and returns `{ type: 'deep_link' }` to the Developer Portal where the
299
+ * bot is packaged into a Teams app for install.
300
+ * - **Self-managed** with `appId`/`appPassword` (per-call or provider
301
+ * default): validates the credentials via a Bot Framework token mint,
302
+ * persists the installation, and returns `{ type: 'immediate' }`. Point
303
+ * the bot registration's messaging endpoint at the installation's
304
+ * `messagingEndpoint`.
305
+ * - Self-managed without credentials: persists a pending installation and
306
+ * returns `{ type: 'deep_link' }` pointing at the Teams Developer Portal.
307
+ */
308
+ connect(agentId: string, options?: TeamsConnectOptions): Promise<ChannelConnectResult>;
309
+ /**
310
+ * Disconnect an agent from Microsoft Teams. For bots this provider
311
+ * provisioned (delegated mode), the Developer Portal registration and the
312
+ * Entra application are deleted best-effort — a control-plane failure never
313
+ * blocks removal of the local installation.
314
+ */
315
+ disconnect(agentId: string): Promise<void>;
316
+ /** List installations (public info only — no secrets). */
317
+ listInstallations(): Promise<ChannelInstallationInfo[]>;
318
+ /**
319
+ * Get the full installation for an agent (includes the client secret).
320
+ * Returns `null` if the agent has no Teams installation. Mirrors
321
+ * `SlackProvider.getInstallation`.
322
+ */
323
+ getInstallation(agentId: string): Promise<TeamsInstallation | null>;
324
+ /** Whether at least one bot is actively registered. */
325
+ isConfigured(): boolean;
326
+ /**
327
+ * Get the live `TeamsAdapter` for an installation id, if one is active.
328
+ * Used for message formatting/posting. Mirrors `SlackProvider.getAdapter`.
329
+ */
330
+ getAdapter(installationId: string): TeamsAdapter$1 | undefined;
331
+ }
332
+ //#endregion
333
+ //#region src/install-store.d.ts
334
+ /** Platform identifier used for every stored record and route. */
335
+ declare const PLATFORM = "teams";
336
+ /**
337
+ * Persistence for Teams bot installations, layered over the platform-agnostic
338
+ * `ChannelsStorage` (the same store `@mastra/slack` / `@mastra/telegram` use).
339
+ * Installations are keyed by agent — one bot = one agent — and the per-bot
340
+ * fields live in the record's `data` blob. When an `encryptionKey` is
341
+ * supplied, `appPassword` (the bot's client secret) is AES-256-GCM encrypted
342
+ * at rest.
343
+ */
344
+ declare class TeamsInstallStore {
345
+ #private;
346
+ private readonly storage;
347
+ private readonly encryptionKey?;
348
+ constructor(storage: ChannelsStorage, encryptionKey?: string | undefined);
349
+ /** Whether secrets written through this store are encrypted at rest. */
350
+ get canEncrypt(): boolean;
351
+ /** The active or pending installation for an agent, if any. */
352
+ getByAgent(agentId: string): Promise<TeamsInstallation | null>;
353
+ /** Look up an installation by the routing id in its messaging endpoint path. */
354
+ getByWebhookId(webhookId: string): Promise<TeamsInstallation | null>;
355
+ /** Insert or replace an installation. */
356
+ save(installation: TeamsInstallation): Promise<void>;
357
+ /** All Teams installations (active and pending). */
358
+ list(): Promise<TeamsInstallation[]>;
359
+ /** Remove an agent's installation, if present. */
360
+ deleteByAgent(agentId: string): Promise<void>;
361
+ }
362
+ /** Project an installation to its public, secret-free info for the editor UI. */
363
+ declare function toInstallationInfo(install: TeamsInstallation): ChannelInstallationInfo;
364
+ //#endregion
365
+ //#region src/microsoft-clients.d.ts
366
+ /** The subset of a Graph `application` resource the provider uses. */
367
+ interface EntraApplication {
368
+ /** Directory **object id** — used for subsequent Graph calls (addPassword, delete). */
369
+ id: string;
370
+ /** The application (client) id — the bot's Microsoft App ID. */
371
+ appId: string;
372
+ }
373
+ /**
374
+ * Create an Entra application for a per-agent bot.
375
+ * @see https://learn.microsoft.com/graph/api/application-post-applications
376
+ */
377
+ declare function createApplication(token: string, options: {
378
+ displayName: string;
379
+ signInAudience: 'AzureADMultipleOrgs' | 'AzureADMyOrg';
380
+ }, graphBaseUrl?: string): Promise<EntraApplication>;
381
+ /**
382
+ * Mint a client secret on an Entra application. The secret text is only
383
+ * returned by this call — it cannot be read back later.
384
+ * @see https://learn.microsoft.com/graph/api/application-addpassword
385
+ */
386
+ declare function addApplicationPassword(token: string, applicationObjectId: string, displayName: string, graphBaseUrl?: string): Promise<string>;
387
+ /**
388
+ * Delete an Entra application. Used to clean up provisioned bots on
389
+ * disconnect and to roll back a partially provisioned connect.
390
+ * @see https://learn.microsoft.com/graph/api/application-delete
391
+ */
392
+ declare function deleteApplication(token: string, applicationObjectId: string, graphBaseUrl?: string): Promise<void>;
393
+ /**
394
+ * A Teams Developer Portal bot registration, as accepted by
395
+ * `POST https://dev.teams.microsoft.com/api/botframework` (the same contract
396
+ * Microsoft's Teams Toolkit CLI uses).
397
+ */
398
+ interface TeamsBotRegistration {
399
+ /** The bot's Microsoft App (client) ID. */
400
+ botId: string;
401
+ name: string;
402
+ description: string;
403
+ iconUrl: string;
404
+ messagingEndpoint: string;
405
+ callingEndpoint: string;
406
+ }
407
+ /** Register a bot with the Teams Developer Portal. */
408
+ declare function createBotRegistration(token: string, registration: TeamsBotRegistration, devPortalBaseUrl?: string): Promise<void>;
409
+ /** Delete a Teams Developer Portal bot registration. */
410
+ declare function deleteBotRegistration(token: string, botId: string, devPortalBaseUrl?: string): Promise<void>;
411
+ /**
412
+ * Validate a bot's `appId`/`appPassword` by minting a Bot Framework token via
413
+ * the OAuth2 client-credentials grant — the same exchange the adapter performs
414
+ * at runtime, so a success here means outbound sends will authenticate.
415
+ * Multi-tenant bots exchange against the `botframework.com` tenant.
416
+ *
417
+ * Throws when Microsoft rejects the credentials; transport failures are
418
+ * surfaced as-is (tagged `isTransportError`) so callers can tell connectivity
419
+ * problems apart from bad credentials.
420
+ */
421
+ declare function validateBotCredentials(options: {
422
+ appId: string;
423
+ appPassword: string;
424
+ appTenantId?: string;
425
+ }, loginBaseUrl?: string): Promise<void>;
426
+ //#endregion
427
+ export { DEV_PORTAL_BASE_URL, DEV_PORTAL_BOTS_URL, type EntraApplication, GRAPH_API_BASE_URL, LOGIN_BASE_URL, PLATFORM, TEAMS_DEV_PORTAL_SCOPE, TEAMS_GRAPH_SCOPE, TeamsAdapter, type TeamsBotRegistration, type TeamsConnectOptions, type TeamsCredentialsConfig, type TeamsDelegatedCredentialsConfig, TeamsInstallStore, type TeamsInstallation, TeamsProvider, type TeamsProviderConfig, type TeamsProviderConfigBase, type TeamsSelfManagedCredentialsConfig, type TeamsTokenResolver, addApplicationPassword, createApplication, createBotRegistration, createTeamsAdapter, deleteApplication, deleteBotRegistration, resolveTeamsAdapterConfig, toInstallationInfo, validateBotCredentials };
428
+ //# sourceMappingURL=index.d.ts.map