@memberjunction/ai-bridge-teams 5.44.0 → 5.45.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 @@
1
+ {"version":3,"file":"real-teams-bindings.js","sourceRoot":"","sources":["../src/real-teams-bindings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * @fileoverview Production clients behind the Teams binding seams — the **Microsoft Graph
3
+ * cloud-communications control plane** ({@link RealGraphCallsClient} over `@microsoft/microsoft-graph-client`)
4
+ * and the **ACS application-hosted-media audio plane** ({@link PumpBackedAcsMedia} over a server-owned
5
+ * per-call audio pump).
6
+ *
7
+ * ## Why this split (mirrors the Twilio REST / Media-Streams split)
8
+ * Just like the Twilio binding — REST in-package ({@link import('./real-twilio-bindings')}) and the
9
+ * bidirectional Media-Streams **websocket** owned by the MJAPI ingress — the Teams binding splits along the
10
+ * same line:
11
+ * - The **Graph control plane** (`POST /communications/calls`, roster, chat, mute, hangup) is a request/
12
+ * response REST surface this package can drive directly. {@link RealGraphCallsClient} implements
13
+ * {@link IGraphCallsLike} over `@microsoft/microsoft-graph-client`.
14
+ * - The **ACS audio plane** (per-participant inbound PCM + the bot's outbound PCM) is a long-lived
15
+ * application-hosted-media socket. That socket is a **server** concern (it spans the whole call and the
16
+ * `ws` / native-media dependency lives in MJServer), so this package exposes the {@link IAcsMediaPump}
17
+ * seam and a tiny {@link PumpBackedAcsMedia} adapter the server's per-call registry feeds — exactly as
18
+ * `ITwilioMediaPump` + the server's `TwilioCallMediaRegistry` do for telephony.
19
+ *
20
+ * ## Optional peer SDK (CLAUDE rule 8, category 2)
21
+ * `@microsoft/microsoft-graph-client` is an OPTIONAL PEER SDK — NEVER statically imported, so this provider
22
+ * package builds and unit-tests with no Graph install and no network. It is lazily loaded (once, memoized)
23
+ * at first use via the injectable {@link GraphModuleLoader}; tests inject a fake factory. None of the Graph
24
+ * SDK's own types leak past this file — everything crosses the seam through the minimal structural interfaces
25
+ * below, keeping {@link RealTeamsBindings} SDK-agnostic. The package declares it in `optionalDependencies`.
26
+ *
27
+ * @module @memberjunction/ai-bridge-teams
28
+ * @author MemberJunction.com
29
+ * @see {@link IGraphCallsLike} / {@link IAcsMediaLike} — the seams these implement.
30
+ * @see `/plans/realtime/bridges-and-widget/meeting-vendor-bindings-teams-slack.md` §2 (M1 A).
31
+ */
32
+ import type { GraphCallParticipant, GraphCreateCallRequest, GraphCreateCallResult, IGraphCallsLike, IAcsMediaLike, AcsInboundAudioFrame } from './real-teams-bindings.js';
33
+ /** One fluent Graph request (`client.api(path)`) — the subset of verbs we issue. */
34
+ export interface GraphRequestLike {
35
+ /** Issues `POST {path}` with a JSON body; resolves the parsed response. */
36
+ post(body: unknown): Promise<unknown>;
37
+ /** Issues `GET {path}`; resolves the parsed response. */
38
+ get(): Promise<unknown>;
39
+ /** Issues `DELETE {path}`; resolves when the resource is removed. */
40
+ delete(): Promise<unknown>;
41
+ }
42
+ /** The constructed Graph client surface — just the `api(path)` request-builder entry point. */
43
+ export interface GraphClientLike {
44
+ /** Begins a fluent request against a Graph resource path (e.g. `/communications/calls`). */
45
+ api(path: string): GraphRequestLike;
46
+ }
47
+ /**
48
+ * The `@microsoft/microsoft-graph-client` module surface we use: the `Client.init({ authProvider })`
49
+ * static factory. Declared structurally so the SDK's real `Client` type never leaks.
50
+ */
51
+ export interface GraphModuleLike {
52
+ /** The `Client` class with its `init` static factory. */
53
+ Client: {
54
+ /** Constructs an authenticated Graph client from an auth-provider callback. */
55
+ init(options: GraphClientInitOptions): GraphClientLike;
56
+ };
57
+ }
58
+ /** The `Client.init` options subset we pass — just the bearer-token `authProvider` callback. */
59
+ export interface GraphClientInitOptions {
60
+ /**
61
+ * The Graph auth-provider callback. The SDK invokes it for each request and expects the bearer access
62
+ * token (string) via the supplied `done(error, token)` continuation.
63
+ */
64
+ authProvider(done: (error: Error | null, accessToken: string | null) => void): void;
65
+ }
66
+ /** Loads the `@microsoft/microsoft-graph-client` module. Overridable in tests; defaults to a lazy dynamic import. */
67
+ export type GraphModuleLoader = () => Promise<GraphModuleLike>;
68
+ /** Credentials {@link RealGraphCallsClient} authenticates Graph with. Resolved upstream via MJ config — never inlined. */
69
+ export interface GraphCallsClientCredentials {
70
+ /** A pre-resolved OAuth bearer / application token for the bot's Graph calls (resolved upstream). */
71
+ AccessToken: string;
72
+ /** The Azure tenant id the bot operates in (carried for diagnostics + cross-tenant joins). */
73
+ TenantId?: string;
74
+ /** The bot's Azure AD application (client) id (carried for diagnostics). */
75
+ AppId?: string;
76
+ }
77
+ /**
78
+ * Lazily loads the `@microsoft/microsoft-graph-client` module exactly once and memoizes it. A static import
79
+ * is impossible here (optional peer SDK, may be uninstalled in non-Teams deployments); the
80
+ * `optionalDependencies` entry keeps it in the dependency graph (CLAUDE rule 8, category 2 — optional peer
81
+ * SDK loaded only when the Teams provider is configured).
82
+ */
83
+ export declare const defaultGraphModuleLoader: GraphModuleLoader;
84
+ /**
85
+ * A real {@link IGraphCallsLike} over the Microsoft Graph cloud-communications REST API
86
+ * (`@microsoft/microsoft-graph-client`).
87
+ *
88
+ * - `CreateCall` → `POST /communications/calls` with an app-hosted-media join-by-URL body; reads
89
+ * the created call id + the bot participant id from the response.
90
+ * - `DeleteCall` → `DELETE /communications/calls/{id}` (the bot's call-leg hangup).
91
+ * - `GetParticipants` → `GET /communications/calls/{id}/participants`; maps each to {@link GraphCallParticipant}.
92
+ * - `PostChatMessage` → `POST /chats/{threadId}/messages` against the meeting thread.
93
+ * - `MuteParticipant` → `POST /communications/calls/{id}/participants/{pid}/mute`.
94
+ * - `OnParticipantsUpdated`/`OnCallEnded` → arrive over the Graph change-notification **webhook** (the MJAPI
95
+ * ingress), not a client subscription; this REST client retains the handlers so the
96
+ * ingress can drive them via {@link DriveParticipantsUpdated} / {@link DriveCallEnded}.
97
+ *
98
+ * The constructed Graph client is built once on first use and reused for the life of the instance.
99
+ */
100
+ export declare class RealGraphCallsClient implements IGraphCallsLike {
101
+ private readonly credentials;
102
+ private readonly loadModule;
103
+ /** Memoized client-build promise so concurrent callers share one construction. */
104
+ private clientPromise?;
105
+ /** Retained webhook handlers, keyed by call id — driven by the MJAPI Graph-notification ingress. */
106
+ private readonly participantsHandlers;
107
+ private readonly endedHandlers;
108
+ /**
109
+ * @param credentials Resolved Graph credentials (bearer token + tenant/app ids).
110
+ * @param loadModule The Graph module loader (defaults to the lazy dynamic import).
111
+ */
112
+ constructor(credentials: GraphCallsClientCredentials, loadModule?: GraphModuleLoader);
113
+ /** @inheritdoc */
114
+ CreateCall(request: GraphCreateCallRequest): Promise<GraphCreateCallResult>;
115
+ /** @inheritdoc */
116
+ DeleteCall(callId: string): Promise<void>;
117
+ /** @inheritdoc */
118
+ GetParticipants(callId: string): Promise<GraphCallParticipant[]>;
119
+ /** @inheritdoc */
120
+ PostChatMessage(threadId: string, text: string): Promise<void>;
121
+ /** @inheritdoc */
122
+ MuteParticipant(callId: string, participantId: string): Promise<void>;
123
+ /** @inheritdoc — retains the handler; the MJAPI Graph-notification ingress drives it via {@link DriveParticipantsUpdated}. */
124
+ OnParticipantsUpdated(callId: string, handler: (participants: GraphCallParticipant[]) => void): void;
125
+ /** @inheritdoc — retains the handler; the MJAPI Graph-notification ingress drives it via {@link DriveCallEnded}. */
126
+ OnCallEnded(callId: string, handler: () => void): void;
127
+ /**
128
+ * Drives the retained `participantsUpdated` handler for a call from a Graph change notification (called by
129
+ * the MJAPI ingress — Graph delivers roster changes over the webhook, not a client subscription).
130
+ */
131
+ DriveParticipantsUpdated(callId: string, participants: GraphCallParticipant[]): void;
132
+ /** Drives the retained `callEnded` handler for a call from a Graph change notification (called by the MJAPI ingress). */
133
+ DriveCallEnded(callId: string): void;
134
+ /** Builds (once) and returns the constructed Graph client with the bot's bearer-token auth provider. */
135
+ private ensureClient;
136
+ /** Constructs the Graph client, supplying the resolved bot bearer token via the SDK's `authProvider` callback. */
137
+ private buildClient;
138
+ }
139
+ /** The Graph `POST /communications/calls` body subset we construct for a join-by-URL app-hosted-media bot call. */
140
+ export interface GraphCallPostBody {
141
+ '@odata.type': '#microsoft.graph.call';
142
+ callbackUri?: string;
143
+ mediaConfig: {
144
+ '@odata.type': '#microsoft.graph.appHostedMediaConfig';
145
+ };
146
+ chatInfo: {
147
+ '@odata.type': '#microsoft.graph.chatInfo';
148
+ threadId: string;
149
+ };
150
+ meetingInfo: {
151
+ '@odata.type': '#microsoft.graph.joinMeetingIdMeetingInfo' | '#microsoft.graph.organizerMeetingInfo';
152
+ joinWebUrl?: string;
153
+ };
154
+ tenantId?: string;
155
+ }
156
+ /**
157
+ * **Pure** mapping of the bridge's {@link GraphCreateCallRequest} onto the Graph call POST body. Isolated so
158
+ * the request shape unit-tests directly and the live client reuses it verbatim.
159
+ */
160
+ export declare function buildGraphCallBody(request: GraphCreateCallRequest): GraphCallPostBody;
161
+ /** Reads the `{ id, myParticipantId }` of the created call out of the Graph response, without leaking SDK types. */
162
+ export declare function readCreateCallResult(response: unknown): GraphCreateCallResult;
163
+ /** Reads a Graph participants-collection response (`{ value: [...] }`) into {@link GraphCallParticipant}s. */
164
+ export declare function readParticipantsCollection(response: unknown): GraphCallParticipant[];
165
+ /** Reads one Graph participant resource into the bridge's {@link GraphCallParticipant} shape. */
166
+ export declare function readGraphParticipant(raw: unknown): GraphCallParticipant;
167
+ /**
168
+ * The server-owned per-call audio pump the ACS application-hosted-media plane runs on — the analogue of
169
+ * `ITwilioMediaPump` for telephony. The long-lived ACS audio socket is a server concern (it spans the whole
170
+ * call and the native-media / `ws` dependency lives in MJServer), so this seam lets the in-package binding
171
+ * push the bot's outbound PCM and register for inbound per-participant PCM without ever owning the socket.
172
+ * Production wires it over the server's per-call ACS media registry; tests inject a fake.
173
+ */
174
+ export interface IAcsMediaPump {
175
+ /** The ACS audio-socket sample rate in Hz (e.g. 16000) — drives T0 resampling in {@link RealTeamsBindings}. */
176
+ readonly SampleRate: number;
177
+ /** Sends one outbound PCM16 frame on the bot's outbound audio socket for the call (the agent's voice). */
178
+ Send(callId: string, pcm: ArrayBuffer): void;
179
+ /** Registers the inbound per-participant audio handler for the call's socket (latest handler wins). */
180
+ OnFrame(callId: string, handler: (frame: AcsInboundAudioFrame) => void): void;
181
+ /**
182
+ * Registers the raised-hand handler for the call when the platform/registry surfaces it. **Optional** —
183
+ * absence is tolerated by {@link RealTeamsBindings} (the handler simply never fires).
184
+ */
185
+ OnHandRaise?(callId: string, handler: (participantId: string, raised: boolean) => void): void;
186
+ }
187
+ /**
188
+ * Adapts the server-owned per-call {@link IAcsMediaPump} to the call-scoped {@link IAcsMediaLike} surface
189
+ * {@link RealTeamsBindings} drives. The binding supplies the Graph **call id** on every per-frame call (it
190
+ * resolves the id at `join()` and threads it through), so this adapter routes each call straight onto the
191
+ * shared pump keyed by that id — no call-id needs to be known at construction. Mirrors how
192
+ * `TwilioCallMediaRegistry` backs the telephony media seam.
193
+ */
194
+ export declare class PumpBackedAcsMedia implements IAcsMediaLike {
195
+ private readonly pump;
196
+ /**
197
+ * @param pump The server-owned per-call ACS audio pump (keyed by Graph call id).
198
+ */
199
+ constructor(pump: IAcsMediaPump);
200
+ /** @inheritdoc */
201
+ get SampleRate(): number;
202
+ /** @inheritdoc — routes to the pump keyed by the call id the binding supplies. */
203
+ SendAudioFrame(callId: string, pcm: ArrayBuffer): void;
204
+ /** @inheritdoc — routes to the pump keyed by the call id the binding supplies. */
205
+ OnAudioFrame(callId: string, handler: (frame: AcsInboundAudioFrame) => void): void;
206
+ /** @inheritdoc — only wires hand-raise when the underlying pump exposes it (tolerated absence). */
207
+ OnHandRaise(callId: string, handler: (participantId: string, raised: boolean) => void): void;
208
+ }
209
+ //# sourceMappingURL=teams-graph-acs-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams-graph-acs-client.d.ts","sourceRoot":"","sources":["../src/teams-graph-acs-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,256 @@
1
+ /**
2
+ * @fileoverview Production clients behind the Teams binding seams — the **Microsoft Graph
3
+ * cloud-communications control plane** ({@link RealGraphCallsClient} over `@microsoft/microsoft-graph-client`)
4
+ * and the **ACS application-hosted-media audio plane** ({@link PumpBackedAcsMedia} over a server-owned
5
+ * per-call audio pump).
6
+ *
7
+ * ## Why this split (mirrors the Twilio REST / Media-Streams split)
8
+ * Just like the Twilio binding — REST in-package ({@link import('./real-twilio-bindings')}) and the
9
+ * bidirectional Media-Streams **websocket** owned by the MJAPI ingress — the Teams binding splits along the
10
+ * same line:
11
+ * - The **Graph control plane** (`POST /communications/calls`, roster, chat, mute, hangup) is a request/
12
+ * response REST surface this package can drive directly. {@link RealGraphCallsClient} implements
13
+ * {@link IGraphCallsLike} over `@microsoft/microsoft-graph-client`.
14
+ * - The **ACS audio plane** (per-participant inbound PCM + the bot's outbound PCM) is a long-lived
15
+ * application-hosted-media socket. That socket is a **server** concern (it spans the whole call and the
16
+ * `ws` / native-media dependency lives in MJServer), so this package exposes the {@link IAcsMediaPump}
17
+ * seam and a tiny {@link PumpBackedAcsMedia} adapter the server's per-call registry feeds — exactly as
18
+ * `ITwilioMediaPump` + the server's `TwilioCallMediaRegistry` do for telephony.
19
+ *
20
+ * ## Optional peer SDK (CLAUDE rule 8, category 2)
21
+ * `@microsoft/microsoft-graph-client` is an OPTIONAL PEER SDK — NEVER statically imported, so this provider
22
+ * package builds and unit-tests with no Graph install and no network. It is lazily loaded (once, memoized)
23
+ * at first use via the injectable {@link GraphModuleLoader}; tests inject a fake factory. None of the Graph
24
+ * SDK's own types leak past this file — everything crosses the seam through the minimal structural interfaces
25
+ * below, keeping {@link RealTeamsBindings} SDK-agnostic. The package declares it in `optionalDependencies`.
26
+ *
27
+ * @module @memberjunction/ai-bridge-teams
28
+ * @author MemberJunction.com
29
+ * @see {@link IGraphCallsLike} / {@link IAcsMediaLike} — the seams these implement.
30
+ * @see `/plans/realtime/bridges-and-widget/meeting-vendor-bindings-teams-slack.md` §2 (M1 A).
31
+ */
32
+ /**
33
+ * Lazily loads the `@microsoft/microsoft-graph-client` module exactly once and memoizes it. A static import
34
+ * is impossible here (optional peer SDK, may be uninstalled in non-Teams deployments); the
35
+ * `optionalDependencies` entry keeps it in the dependency graph (CLAUDE rule 8, category 2 — optional peer
36
+ * SDK loaded only when the Teams provider is configured).
37
+ */
38
+ export const defaultGraphModuleLoader = async () => {
39
+ try {
40
+ const mod = await import('@microsoft/microsoft-graph-client');
41
+ const resolved = unwrapGraphModule(mod);
42
+ if (!isGraphModule(resolved)) {
43
+ throw new Error('the @microsoft/microsoft-graph-client module did not export a Client.init factory');
44
+ }
45
+ return resolved;
46
+ }
47
+ catch (err) {
48
+ const message = err instanceof Error ? err.message : String(err);
49
+ throw new Error("RealGraphCallsClient could not load the '@microsoft/microsoft-graph-client' SDK. Install it in the " +
50
+ 'deployment that runs the Teams meeting bridge (it is an optional peer dependency). ' +
51
+ `Underlying error: ${message}`);
52
+ }
53
+ };
54
+ /** Unwraps the Graph module from CJS/ESM interop (`module` or `module.default`). */
55
+ function unwrapGraphModule(mod) {
56
+ if (isGraphModule(mod)) {
57
+ return mod;
58
+ }
59
+ if (mod && typeof mod === 'object' && 'default' in mod) {
60
+ const inner = mod.default;
61
+ if (isGraphModule(inner)) {
62
+ return inner;
63
+ }
64
+ }
65
+ return mod;
66
+ }
67
+ /** Structural guard: a value is a {@link GraphModuleLike} when it exposes a `Client.init` function. */
68
+ function isGraphModule(value) {
69
+ if (value == null || typeof value !== 'object') {
70
+ return false;
71
+ }
72
+ const client = value.Client;
73
+ return client != null && typeof client.init === 'function';
74
+ }
75
+ /**
76
+ * A real {@link IGraphCallsLike} over the Microsoft Graph cloud-communications REST API
77
+ * (`@microsoft/microsoft-graph-client`).
78
+ *
79
+ * - `CreateCall` → `POST /communications/calls` with an app-hosted-media join-by-URL body; reads
80
+ * the created call id + the bot participant id from the response.
81
+ * - `DeleteCall` → `DELETE /communications/calls/{id}` (the bot's call-leg hangup).
82
+ * - `GetParticipants` → `GET /communications/calls/{id}/participants`; maps each to {@link GraphCallParticipant}.
83
+ * - `PostChatMessage` → `POST /chats/{threadId}/messages` against the meeting thread.
84
+ * - `MuteParticipant` → `POST /communications/calls/{id}/participants/{pid}/mute`.
85
+ * - `OnParticipantsUpdated`/`OnCallEnded` → arrive over the Graph change-notification **webhook** (the MJAPI
86
+ * ingress), not a client subscription; this REST client retains the handlers so the
87
+ * ingress can drive them via {@link DriveParticipantsUpdated} / {@link DriveCallEnded}.
88
+ *
89
+ * The constructed Graph client is built once on first use and reused for the life of the instance.
90
+ */
91
+ export class RealGraphCallsClient {
92
+ /**
93
+ * @param credentials Resolved Graph credentials (bearer token + tenant/app ids).
94
+ * @param loadModule The Graph module loader (defaults to the lazy dynamic import).
95
+ */
96
+ constructor(credentials, loadModule = defaultGraphModuleLoader) {
97
+ /** Retained webhook handlers, keyed by call id — driven by the MJAPI Graph-notification ingress. */
98
+ this.participantsHandlers = new Map();
99
+ this.endedHandlers = new Map();
100
+ this.credentials = credentials;
101
+ this.loadModule = loadModule;
102
+ }
103
+ /** @inheritdoc */
104
+ async CreateCall(request) {
105
+ const client = await this.ensureClient();
106
+ const body = buildGraphCallBody(request);
107
+ const response = await client.api('/communications/calls').post(body);
108
+ return readCreateCallResult(response);
109
+ }
110
+ /** @inheritdoc */
111
+ async DeleteCall(callId) {
112
+ const client = await this.ensureClient();
113
+ await client.api(`/communications/calls/${encodeURIComponent(callId)}`).delete();
114
+ }
115
+ /** @inheritdoc */
116
+ async GetParticipants(callId) {
117
+ const client = await this.ensureClient();
118
+ const response = await client.api(`/communications/calls/${encodeURIComponent(callId)}/participants`).get();
119
+ return readParticipantsCollection(response);
120
+ }
121
+ /** @inheritdoc */
122
+ async PostChatMessage(threadId, text) {
123
+ const client = await this.ensureClient();
124
+ await client.api(`/chats/${encodeURIComponent(threadId)}/messages`).post({ body: { content: text } });
125
+ }
126
+ /** @inheritdoc */
127
+ async MuteParticipant(callId, participantId) {
128
+ const client = await this.ensureClient();
129
+ await client
130
+ .api(`/communications/calls/${encodeURIComponent(callId)}/participants/${encodeURIComponent(participantId)}/mute`)
131
+ .post({});
132
+ }
133
+ /** @inheritdoc — retains the handler; the MJAPI Graph-notification ingress drives it via {@link DriveParticipantsUpdated}. */
134
+ OnParticipantsUpdated(callId, handler) {
135
+ this.participantsHandlers.set(callId, handler);
136
+ }
137
+ /** @inheritdoc — retains the handler; the MJAPI Graph-notification ingress drives it via {@link DriveCallEnded}. */
138
+ OnCallEnded(callId, handler) {
139
+ this.endedHandlers.set(callId, handler);
140
+ }
141
+ /**
142
+ * Drives the retained `participantsUpdated` handler for a call from a Graph change notification (called by
143
+ * the MJAPI ingress — Graph delivers roster changes over the webhook, not a client subscription).
144
+ */
145
+ DriveParticipantsUpdated(callId, participants) {
146
+ this.participantsHandlers.get(callId)?.(participants);
147
+ }
148
+ /** Drives the retained `callEnded` handler for a call from a Graph change notification (called by the MJAPI ingress). */
149
+ DriveCallEnded(callId) {
150
+ this.endedHandlers.get(callId)?.();
151
+ }
152
+ /** Builds (once) and returns the constructed Graph client with the bot's bearer-token auth provider. */
153
+ ensureClient() {
154
+ if (!this.clientPromise) {
155
+ this.clientPromise = this.buildClient();
156
+ }
157
+ return this.clientPromise;
158
+ }
159
+ /** Constructs the Graph client, supplying the resolved bot bearer token via the SDK's `authProvider` callback. */
160
+ async buildClient() {
161
+ const mod = await this.loadModule();
162
+ const token = this.credentials.AccessToken;
163
+ if (!token) {
164
+ throw new Error('RealGraphCallsClient requires a resolved AccessToken (the bot bearer token).');
165
+ }
166
+ return mod.Client.init({ authProvider: (done) => done(null, token) });
167
+ }
168
+ }
169
+ /**
170
+ * **Pure** mapping of the bridge's {@link GraphCreateCallRequest} onto the Graph call POST body. Isolated so
171
+ * the request shape unit-tests directly and the live client reuses it verbatim.
172
+ */
173
+ export function buildGraphCallBody(request) {
174
+ return {
175
+ '@odata.type': '#microsoft.graph.call',
176
+ mediaConfig: { '@odata.type': '#microsoft.graph.appHostedMediaConfig' },
177
+ chatInfo: { '@odata.type': '#microsoft.graph.chatInfo', threadId: request.ThreadId },
178
+ meetingInfo: { '@odata.type': '#microsoft.graph.joinMeetingIdMeetingInfo', joinWebUrl: request.JoinWebUrl },
179
+ ...(request.TenantId ? { tenantId: request.TenantId } : {}),
180
+ };
181
+ }
182
+ /** Reads the `{ id, myParticipantId }` of the created call out of the Graph response, without leaking SDK types. */
183
+ export function readCreateCallResult(response) {
184
+ const obj = asRecord(response);
185
+ const callId = readString(obj?.id);
186
+ if (!callId) {
187
+ throw new Error('Graph POST /communications/calls returned no call id.');
188
+ }
189
+ const botParticipantId = readString(obj?.myParticipantId) ?? callId;
190
+ return { CallId: callId, BotParticipantId: botParticipantId };
191
+ }
192
+ /** Reads a Graph participants-collection response (`{ value: [...] }`) into {@link GraphCallParticipant}s. */
193
+ export function readParticipantsCollection(response) {
194
+ const obj = asRecord(response);
195
+ const value = obj?.value;
196
+ if (!Array.isArray(value)) {
197
+ return [];
198
+ }
199
+ return value.map(readGraphParticipant);
200
+ }
201
+ /** Reads one Graph participant resource into the bridge's {@link GraphCallParticipant} shape. */
202
+ export function readGraphParticipant(raw) {
203
+ const p = asRecord(raw);
204
+ const info = asRecord(p?.info);
205
+ const identity = asRecord(info?.identity);
206
+ const user = asRecord(identity?.user);
207
+ const mediaStreams = Array.isArray(p?.mediaStreams) ? p?.mediaStreams : undefined;
208
+ return {
209
+ id: readString(p?.id) ?? '',
210
+ displayName: readString(user?.displayName),
211
+ role: readString(p?.role) ?? readString(p?.meetingRole),
212
+ // Graph marks the bot leg via `isMuted`/`isInLobby` flags; `info.identity.application` distinguishes
213
+ // an application identity (the bot) from a `user` identity.
214
+ isSelf: identity?.application != null && mediaStreams != null,
215
+ };
216
+ }
217
+ /** Narrows an unknown value to a record, or `undefined`. */
218
+ function asRecord(value) {
219
+ return value != null && typeof value === 'object' ? value : undefined;
220
+ }
221
+ /** Reads a value as a non-empty string, or `undefined`. */
222
+ function readString(value) {
223
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
224
+ }
225
+ /**
226
+ * Adapts the server-owned per-call {@link IAcsMediaPump} to the call-scoped {@link IAcsMediaLike} surface
227
+ * {@link RealTeamsBindings} drives. The binding supplies the Graph **call id** on every per-frame call (it
228
+ * resolves the id at `join()` and threads it through), so this adapter routes each call straight onto the
229
+ * shared pump keyed by that id — no call-id needs to be known at construction. Mirrors how
230
+ * `TwilioCallMediaRegistry` backs the telephony media seam.
231
+ */
232
+ export class PumpBackedAcsMedia {
233
+ /**
234
+ * @param pump The server-owned per-call ACS audio pump (keyed by Graph call id).
235
+ */
236
+ constructor(pump) {
237
+ this.pump = pump;
238
+ }
239
+ /** @inheritdoc */
240
+ get SampleRate() {
241
+ return this.pump.SampleRate;
242
+ }
243
+ /** @inheritdoc — routes to the pump keyed by the call id the binding supplies. */
244
+ SendAudioFrame(callId, pcm) {
245
+ this.pump.Send(callId, pcm);
246
+ }
247
+ /** @inheritdoc — routes to the pump keyed by the call id the binding supplies. */
248
+ OnAudioFrame(callId, handler) {
249
+ this.pump.OnFrame(callId, handler);
250
+ }
251
+ /** @inheritdoc — only wires hand-raise when the underlying pump exposes it (tolerated absence). */
252
+ OnHandRaise(callId, handler) {
253
+ this.pump.OnHandRaise?.(callId, handler);
254
+ }
255
+ }
256
+ //# sourceMappingURL=teams-graph-acs-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams-graph-acs-client.js","sourceRoot":"","sources":["../src/teams-graph-acs-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @fileoverview Microsoft Graph change-notification **ingress** pure helpers — the validation-token
3
+ * handshake, the `clientState` shared-secret check, and the call/participant notification → normalized
4
+ * state mapper, plus a `buildJoinByUrlRequest` convenience. These are the framework-free pieces of the
5
+ * MJAPI Teams ingress: no Express, no network, no DB, so they unit-test directly and the MJAPI router can
6
+ * call them verbatim once the live wiring lands.
7
+ *
8
+ * The remaining **live** ingress — the `POST /meetings/teams/notifications` endpoint, the
9
+ * `Meeting.JoinByUrl(agentIdentityId, joinUrl)` mutation, and the Azure AD app registration (Graph
10
+ * cloud-communications + chat permissions with tenant admin consent) — is documented in
11
+ * `plans/realtime/bridges-and-widget/spikes/M1-teams-binding-notes.md` and is gated on real Teams/Azure
12
+ * credentials + a publicly reachable Graph webhook URL.
13
+ *
14
+ * @module @memberjunction/ai-bridge-teams
15
+ * @author MemberJunction.com
16
+ * @see `/plans/realtime/bridges-and-widget/meeting-vendor-bindings-teams-slack.md` §2 (M1 B/C).
17
+ */
18
+ import { GraphCallParticipant, GraphCreateCallRequest } from './real-teams-bindings.js';
19
+ /**
20
+ * The result of the Graph change-notification **validation-token handshake**. When Microsoft Graph creates
21
+ * (or renews) a subscription, it first calls the notification URL with a `?validationToken=…` query param and
22
+ * expects the endpoint to echo that exact token back as `text/plain` with `200`. {@link validateGraphNotification}
23
+ * returns this discriminated result so the router can either echo the token (handshake) or proceed to process
24
+ * a real notification (with the `clientState` already verified).
25
+ */
26
+ export type GraphNotificationValidation = {
27
+ /** A subscription-validation handshake — echo {@link ValidationToken} back as `text/plain` 200. */
28
+ Kind: 'validation';
29
+ /** The exact token to echo back (Graph rejects the subscription on any mismatch). */
30
+ ValidationToken: string;
31
+ } | {
32
+ /** A real change notification whose `clientState` matched the expected shared secret — process it. */
33
+ Kind: 'notification';
34
+ } | {
35
+ /** Reject — either a missing/blank token on a handshake, or a `clientState` mismatch on a notification. */
36
+ Kind: 'reject';
37
+ /** A short machine-readable reason (for logging; never surfaced to the caller). */
38
+ Reason: 'empty-validation-token' | 'client-state-mismatch';
39
+ };
40
+ /**
41
+ * Performs the Graph change-notification gate, pure + exported so the MJAPI router calls it on every
42
+ * `POST /meetings/teams/notifications` request (these can't carry an MJ JWT — the handshake + `clientState`
43
+ * shared secret are the gate):
44
+ *
45
+ * 1. If the request carries a `validationToken` query param, it's the subscription-validation handshake →
46
+ * return `{ Kind: 'validation', ValidationToken }` (the router echoes it back as `text/plain` 200). A
47
+ * blank token rejects.
48
+ * 2. Otherwise it's a real notification. Every notification in the batch carries a `clientState`; verify
49
+ * each (constant-time) against the secret we set when creating the subscription. Any mismatch rejects the
50
+ * whole batch (an attacker who can't produce the secret must not drive bot behavior).
51
+ *
52
+ * @param validationToken The `?validationToken=…` query param value, when present (the handshake).
53
+ * @param expectedClientState The shared secret set on subscription creation (resolved upstream — never inlined).
54
+ * @param notificationClientStates The `clientState` of each notification in the POST body (empty for handshake).
55
+ * @returns The discriminated validation result.
56
+ */
57
+ export declare function validateGraphNotification(validationToken: string | undefined, expectedClientState: string, notificationClientStates: ReadonlyArray<string | undefined>): GraphNotificationValidation;
58
+ /** The normalized lifecycle state of a Teams call, mapped from a Graph call/participant notification. */
59
+ export type NormalizedCallState = 'establishing' | 'established' | 'terminating' | 'terminated' | 'unknown';
60
+ /** A normalized view of a Graph call/participant change notification — what the ingress hands the engine. */
61
+ export interface NormalizedCallNotification {
62
+ /** The Graph call id the notification is about (`/communications/calls/{id}`). */
63
+ callId: string;
64
+ /** The normalized call lifecycle state. */
65
+ state: NormalizedCallState;
66
+ /** The current participants, normalized (empty when the notification carries no roster). */
67
+ participants: GraphCallParticipant[];
68
+ }
69
+ /** One raw Graph change-notification item (the subset of the `value[]` array fields we read). */
70
+ export interface GraphChangeNotification {
71
+ /** The resource path the change is about (e.g. `communications/calls/{id}` or `.../participants`). */
72
+ resource?: string;
73
+ /** The shared secret we set on subscription creation (verified by {@link validateGraphNotification}). */
74
+ clientState?: string;
75
+ /** The notification's resource payload (the call or participants snapshot). */
76
+ resourceData?: GraphCallResourceData;
77
+ }
78
+ /** The `resourceData` payload of a Graph call/participant notification (the subset we read). */
79
+ export interface GraphCallResourceData {
80
+ /** The Graph call id, when the notification carries it directly. */
81
+ id?: string;
82
+ /** The call's lifecycle state string (`'establishing'` / `'established'` / `'terminated'`, etc.). */
83
+ state?: string;
84
+ /** The participants snapshot, when the notification is a `participantsUpdated`. */
85
+ participants?: GraphCallParticipant[];
86
+ }
87
+ /**
88
+ * **Pure** mapping of a Graph call/participant change notification to a {@link NormalizedCallNotification}
89
+ * (`{ callId, state, participants }`). Resolves the call id from `resourceData.id` or the `resource` path,
90
+ * normalizes the lifecycle state, and passes the participants snapshot through unchanged. Exported so the
91
+ * MJAPI router maps each notification → engine session lifecycle without re-parsing Graph's resource shapes.
92
+ *
93
+ * @param notification One Graph change-notification item.
94
+ * @returns The normalized call notification.
95
+ * @throws When no call id can be resolved (a notification with no identifiable call is unactionable).
96
+ */
97
+ export declare function parseCallNotification(notification: GraphChangeNotification): NormalizedCallNotification;
98
+ /**
99
+ * Builds the Graph `POST /communications/calls` request body for an on-demand **join-by-URL** trigger, the
100
+ * payload the live `Meeting.JoinByUrl(agentIdentityId, joinUrl)` mutation hands the engine. Thin wrapper over
101
+ * {@link buildGraphCreateCallRequest} that constructs the minimal {@link TeamsJoinArgs} from a join URL + bot
102
+ * name; pure so the router and tests share one request shape.
103
+ *
104
+ * @param joinUrl The Teams meeting join URL to join.
105
+ * @param botDisplayName The bot's display name in the participant list (defaults to `'AI Agent'`).
106
+ * @param tenantId The Azure tenant id, when joining cross-tenant.
107
+ * @returns The Graph create-call request body.
108
+ * @throws When the join URL carries no resolvable meeting thread id.
109
+ */
110
+ export declare function buildJoinByUrlRequest(joinUrl: string, botDisplayName?: string, tenantId?: string): GraphCreateCallRequest;
111
+ //# sourceMappingURL=teams-ingress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams-ingress.d.ts","sourceRoot":"","sources":["../src/teams-ingress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAA+B,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAGlH;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,GACjC;IACI,mGAAmG;IACnG,IAAI,EAAE,YAAY,CAAC;IACnB,qFAAqF;IACrF,eAAe,EAAE,MAAM,CAAC;CAC3B,GACD;IACI,sGAAsG;IACtG,IAAI,EAAE,cAAc,CAAC;CACxB,GACD;IACI,2GAA2G;IAC3G,IAAI,EAAE,QAAQ,CAAC;IACf,mFAAmF;IACnF,MAAM,EAAE,wBAAwB,GAAG,uBAAuB,CAAC;CAC9D,CAAC;AAER;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CACrC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,mBAAmB,EAAE,MAAM,EAC3B,wBAAwB,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,GAC5D,2BAA2B,CAY7B;AAED,yGAAyG;AACzG,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,aAAa,GAAG,aAAa,GAAG,YAAY,GAAG,SAAS,CAAC;AAE5G,6GAA6G;AAC7G,MAAM,WAAW,0BAA0B;IACvC,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,KAAK,EAAE,mBAAmB,CAAC;IAC3B,4FAA4F;IAC5F,YAAY,EAAE,oBAAoB,EAAE,CAAC;CACxC;AAED,iGAAiG;AACjG,MAAM,WAAW,uBAAuB;IACpC,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yGAAyG;IACzG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED,gGAAgG;AAChG,MAAM,WAAW,qBAAqB;IAClC,oEAAoE;IACpE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,uBAAuB,GAAG,0BAA0B,CAavG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,MAAM,EACf,cAAc,SAAa,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAClB,sBAAsB,CAOxB"}