@cuylabs/channel-teams-agent-core 0.4.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.
package/dist/index.js ADDED
@@ -0,0 +1,836 @@
1
+ import {
2
+ Conversation,
3
+ ConversationBuilder,
4
+ ConversationReferenceBuilder,
5
+ CreateConversationOptionsBuilder,
6
+ captureM365ConversationReference,
7
+ captureTeamsConversationReference,
8
+ continueM365Conversation,
9
+ restoreM365ConversationReference
10
+ } from "./chunk-ZULHZARA.js";
11
+
12
+ // src/index.ts
13
+ export * from "@cuylabs/channel-teams";
14
+
15
+ // src/adapter.ts
16
+ import {
17
+ createM365ChannelAdapter,
18
+ extractUserIdentity,
19
+ runWithM365TurnContext
20
+ } from "@cuylabs/channel-m365-agent-core";
21
+ import { ActivityTypes } from "@microsoft/agents-activity";
22
+ import { parseTeamsActivity, sendTeamsInvoke } from "@cuylabs/channel-teams";
23
+ function createTeamsChannelAdapter(options) {
24
+ const {
25
+ prepareTurn,
26
+ handlers,
27
+ onInvoke: fallbackInvoke,
28
+ onTurn: onTurnHook,
29
+ strictChannelData,
30
+ ...baseOptions
31
+ } = options;
32
+ const base = createM365ChannelAdapter({
33
+ ...baseOptions,
34
+ prepareTurn: async (request) => {
35
+ const teams = parseTeamsActivity(request.turnContext, {
36
+ strictChannelData
37
+ });
38
+ const prepared = prepareTurn ? await prepareTurn({
39
+ ...request,
40
+ teams,
41
+ channelData: teams.channelData
42
+ }) : void 0;
43
+ return {
44
+ ...prepared ?? {},
45
+ scopeName: prepared?.scopeName?.trim() || "teams-activity",
46
+ scopeAttributes: {
47
+ teamsKind: teams.kind,
48
+ teamsSurface: teams.surface,
49
+ teamsTenantId: teams.tenantId,
50
+ teamsTeamId: teams.teamId,
51
+ teamsChannelId: teams.channelThreadId,
52
+ teamsMeetingId: teams.meetingId,
53
+ teamsInvokeName: teams.invokeName,
54
+ teamsEventType: teams.eventType,
55
+ ...prepared?.scopeAttributes ?? {}
56
+ },
57
+ context: {
58
+ ...prepared?.context ?? {},
59
+ teams
60
+ }
61
+ };
62
+ },
63
+ onInvoke: async (context) => {
64
+ const teams = parseTeamsActivity(context, {
65
+ strictChannelData
66
+ });
67
+ const dispatch = await dispatchTeamsHandler(
68
+ handlers,
69
+ teams.kind,
70
+ await createHandlerContext(options, base, context, teams)
71
+ );
72
+ if (!dispatch.handled && fallbackInvoke) {
73
+ await fallbackInvoke(context);
74
+ } else if (!dispatch.handled) {
75
+ await sendTeamsInvoke(context, void 0, 501);
76
+ }
77
+ }
78
+ });
79
+ async function coreHandler(context) {
80
+ const teams = parseTeamsActivity(context, {
81
+ strictChannelData
82
+ });
83
+ if (teams.channelId !== "msteams") {
84
+ await base.handler(context);
85
+ return;
86
+ }
87
+ const isTeamsSpecificEvent = context.activity.type === ActivityTypes.Event && teams.kind !== "other";
88
+ const isTeamsSpecificActivity = context.activity.type === ActivityTypes.ConversationUpdate || context.activity.type === ActivityTypes.MessageUpdate || context.activity.type === ActivityTypes.MessageDelete || context.activity.type === ActivityTypes.MessageReaction || isTeamsSpecificEvent;
89
+ if (isTeamsSpecificActivity) {
90
+ const dispatch = await dispatchTeamsHandler(
91
+ handlers,
92
+ teams.kind,
93
+ await createHandlerContext(options, base, context, teams)
94
+ );
95
+ if (dispatch.handled) {
96
+ return;
97
+ }
98
+ }
99
+ await base.handler(context);
100
+ }
101
+ async function handler(context) {
102
+ if (onTurnHook) {
103
+ await onTurnHook(context, () => coreHandler(context));
104
+ } else {
105
+ await coreHandler(context);
106
+ }
107
+ }
108
+ return {
109
+ ...base,
110
+ handler,
111
+ m365: base
112
+ };
113
+ }
114
+ async function createHandlerContext(options, base, turnContext, teams = parseTeamsActivity(turnContext)) {
115
+ const conversationId = turnContext.activity.conversation?.id ?? "unknown";
116
+ const channelId = turnContext.activity.channelId ?? "unknown";
117
+ const sessionId = await base.getSessionId(conversationId, channelId);
118
+ const user = extractUserIdentity(turnContext);
119
+ const source = resolveSource(options);
120
+ const ambient = {
121
+ turnContext,
122
+ user,
123
+ sessionId,
124
+ message: (turnContext.activity.text ?? "").trim(),
125
+ teams,
126
+ context: { teams }
127
+ };
128
+ const context = {
129
+ turnContext,
130
+ user,
131
+ teams,
132
+ channelData: teams.channelData,
133
+ sessionId,
134
+ source,
135
+ runAgent(message, runOptions) {
136
+ return runAgentWithTeamsContext(
137
+ ambient,
138
+ source,
139
+ sessionId,
140
+ message,
141
+ runOptions
142
+ );
143
+ },
144
+ async sendInvoke(body, status = 200) {
145
+ setInvokeResponseSent(context, true);
146
+ await sendTeamsInvoke(turnContext, body, status);
147
+ }
148
+ };
149
+ setInvokeResponseSent(context, false);
150
+ return context;
151
+ }
152
+ async function dispatchTeamsHandler(handlers, kind, context) {
153
+ const handler = resolveHandler(handlers, kind);
154
+ if (!handler) {
155
+ return { handled: false };
156
+ }
157
+ const result = await handler(context);
158
+ if (context.turnContext.activity.type === ActivityTypes.Invoke && result !== "continue") {
159
+ if (!getInvokeResponseSent(context) && isTeamsInvokeResult(result)) {
160
+ await context.sendInvoke(result.body, result.status);
161
+ } else if (!getInvokeResponseSent(context) && result === void 0) {
162
+ await context.sendInvoke();
163
+ }
164
+ }
165
+ return { handled: result !== "continue" };
166
+ }
167
+ function resolveHandler(handlers, kind) {
168
+ switch (kind) {
169
+ case "conversation-update":
170
+ return handlers?.conversationUpdate;
171
+ case "members-added":
172
+ return handlers?.membersAdded ?? handlers?.conversationUpdate;
173
+ case "members-removed":
174
+ return handlers?.membersRemoved ?? handlers?.conversationUpdate;
175
+ case "channel-created":
176
+ return handlers?.channelCreated ?? handlers?.conversationUpdate;
177
+ case "channel-deleted":
178
+ return handlers?.channelDeleted ?? handlers?.conversationUpdate;
179
+ case "channel-renamed":
180
+ return handlers?.channelRenamed ?? handlers?.conversationUpdate;
181
+ case "channel-restored":
182
+ return handlers?.channelRestored ?? handlers?.conversationUpdate;
183
+ case "channel-shared":
184
+ return handlers?.channelShared ?? handlers?.conversationUpdate;
185
+ case "channel-unshared":
186
+ return handlers?.channelUnshared ?? handlers?.conversationUpdate;
187
+ case "team-renamed":
188
+ return handlers?.teamRenamed ?? handlers?.conversationUpdate;
189
+ case "team-archived":
190
+ return handlers?.teamArchived ?? handlers?.conversationUpdate;
191
+ case "team-unarchived":
192
+ return handlers?.teamUnarchived ?? handlers?.conversationUpdate;
193
+ case "team-deleted":
194
+ return handlers?.teamDeleted ?? handlers?.conversationUpdate;
195
+ case "team-hard-deleted":
196
+ return handlers?.teamHardDeleted ?? handlers?.conversationUpdate;
197
+ case "team-restored":
198
+ return handlers?.teamRestored ?? handlers?.conversationUpdate;
199
+ case "message-edit":
200
+ return handlers?.messageEdited;
201
+ case "message-delete":
202
+ return handlers?.messageDeleted;
203
+ case "message-restore":
204
+ return handlers?.messageRestored;
205
+ case "reaction":
206
+ return handlers?.reaction;
207
+ case "read-receipt":
208
+ return handlers?.readReceipt;
209
+ case "config-fetch":
210
+ return handlers?.configFetch ?? handlers?.invoke;
211
+ case "config-submit":
212
+ return handlers?.configSubmit ?? handlers?.invoke;
213
+ case "file-consent":
214
+ return handlers?.fileConsent ?? handlers?.invoke;
215
+ case "actionable-message-execute-action":
216
+ return handlers?.actionableMessageExecuteAction ?? handlers?.invoke;
217
+ case "adaptive-card-action":
218
+ return handlers?.adaptiveCardAction ?? handlers?.cardSubmit;
219
+ case "adaptive-card-search":
220
+ return handlers?.adaptiveCardSearch ?? handlers?.searchCommand;
221
+ case "feedback":
222
+ return handlers?.feedbackSubmit ?? handlers?.cardSubmit;
223
+ case "card-submit":
224
+ return handlers?.cardSubmit;
225
+ case "dialog-open":
226
+ return handlers?.dialogOpen;
227
+ case "dialog-submit":
228
+ return handlers?.dialogSubmit;
229
+ case "search-command":
230
+ return handlers?.searchCommand;
231
+ case "message-extension-query":
232
+ return handlers?.messageExtensionQuery ?? handlers?.searchCommand;
233
+ case "message-extension-query-link":
234
+ return handlers?.messageExtensionQueryLink ?? handlers?.searchCommand;
235
+ case "message-extension-anonymous-query-link":
236
+ return handlers?.messageExtensionAnonymousQueryLink ?? handlers?.searchCommand;
237
+ case "select-result":
238
+ return handlers?.selectResult;
239
+ case "message-extension-select-item":
240
+ return handlers?.messageExtensionSelectItem ?? handlers?.selectResult;
241
+ case "message-extension-submit-action":
242
+ return handlers?.messageExtensionSubmitAction ?? handlers?.cardSubmit;
243
+ case "message-extension-fetch-task":
244
+ return handlers?.messageExtensionFetchTask ?? handlers?.dialogOpen;
245
+ case "message-extension-query-setting-url":
246
+ return handlers?.messageExtensionQuerySettingUrl ?? handlers?.invoke;
247
+ case "message-extension-setting":
248
+ return handlers?.messageExtensionSetting ?? handlers?.invoke;
249
+ case "message-extension-card-button-clicked":
250
+ return handlers?.messageExtensionCardButtonClicked ?? handlers?.invoke;
251
+ case "task-fetch":
252
+ return handlers?.taskFetch ?? handlers?.dialogOpen;
253
+ case "task-submit":
254
+ return handlers?.taskSubmit ?? handlers?.dialogSubmit;
255
+ case "tab-fetch":
256
+ return handlers?.tabFetch ?? handlers?.invoke;
257
+ case "tab-submit":
258
+ return handlers?.tabSubmit ?? handlers?.invoke;
259
+ case "invoke":
260
+ return handlers?.invoke;
261
+ case "meeting-start":
262
+ return handlers?.meetingStart;
263
+ case "meeting-end":
264
+ return handlers?.meetingEnd;
265
+ case "participants-join":
266
+ return handlers?.participantsJoin;
267
+ case "participants-leave":
268
+ return handlers?.participantsLeave;
269
+ case "meeting-room-join":
270
+ return handlers?.meetingRoomJoin;
271
+ case "meeting-room-leave":
272
+ return handlers?.meetingRoomLeave;
273
+ case "meeting-stage-view":
274
+ return handlers?.meetingStageView;
275
+ case "meeting-smart-reply":
276
+ return handlers?.meetingSmartReply;
277
+ case "meeting-reaction":
278
+ return handlers?.meetingReaction;
279
+ case "meeting-poll-response":
280
+ return handlers?.meetingPollResponse;
281
+ case "meeting-apps-installed":
282
+ return handlers?.meetingAppsInstalled;
283
+ case "meeting-apps-uninstalled":
284
+ return handlers?.meetingAppsUninstalled;
285
+ case "meeting-recording-started":
286
+ return handlers?.meetingRecordingStarted;
287
+ case "meeting-recording-stopped":
288
+ return handlers?.meetingRecordingStopped;
289
+ case "meeting-focus-change":
290
+ return handlers?.meetingFocusChange;
291
+ case "meeting-screen-share-start":
292
+ return handlers?.meetingScreenShareStart;
293
+ case "meeting-screen-share-stop":
294
+ return handlers?.meetingScreenShareStop;
295
+ default:
296
+ return void 0;
297
+ }
298
+ }
299
+ function isTeamsInvokeResult(value) {
300
+ return !!value && typeof value === "object" && "status" in value;
301
+ }
302
+ function getInvokeResponseSent(context) {
303
+ return context.__invokeResponseSent === true;
304
+ }
305
+ function setInvokeResponseSent(context, value) {
306
+ context.__invokeResponseSent = value;
307
+ }
308
+ function resolveSource(options) {
309
+ if (options.source) return options.source;
310
+ if (options.agent) return options.agent;
311
+ throw new Error(
312
+ "Provide exactly one of TeamsChannelOptions.agent or TeamsChannelOptions.source."
313
+ );
314
+ }
315
+ function runAgentWithTeamsContext(ambient, source, sessionId, message, options) {
316
+ return streamAgentWithTeamsContext(
317
+ ambient,
318
+ source,
319
+ sessionId,
320
+ message,
321
+ options
322
+ );
323
+ }
324
+ async function* streamAgentWithTeamsContext(ambient, source, sessionId, message, options) {
325
+ const contextValue = {
326
+ ...ambient,
327
+ message,
328
+ context: {
329
+ ...ambient.context ?? {},
330
+ teams: ambient.teams
331
+ }
332
+ };
333
+ const iterator = await runWithM365TurnContext(
334
+ contextValue,
335
+ async () => source.chat(sessionId, message, options)[Symbol.asyncIterator]()
336
+ );
337
+ let completed = false;
338
+ try {
339
+ while (true) {
340
+ const result = await runWithM365TurnContext(
341
+ contextValue,
342
+ () => iterator.next()
343
+ );
344
+ if (result.done) {
345
+ completed = true;
346
+ return result.value;
347
+ }
348
+ yield result.value;
349
+ }
350
+ } finally {
351
+ if (!completed && iterator.return) {
352
+ await runWithM365TurnContext(
353
+ contextValue,
354
+ () => iterator.return(void 0)
355
+ );
356
+ }
357
+ }
358
+ }
359
+
360
+ // src/context.ts
361
+ import {
362
+ currentM365TurnContext,
363
+ runWithM365TurnContext as runWithM365TurnContext2
364
+ } from "@cuylabs/channel-m365-agent-core";
365
+ function readTeamsContext(context) {
366
+ const payload = context?.context;
367
+ if (!payload || typeof payload !== "object") return void 0;
368
+ const teams = payload.teams;
369
+ return teams && typeof teams === "object" ? teams : void 0;
370
+ }
371
+ function currentTeamsTurnContext() {
372
+ const current = currentM365TurnContext();
373
+ const teams = readTeamsContext(current);
374
+ if (!current || !teams) return void 0;
375
+ return {
376
+ ...current,
377
+ teams
378
+ };
379
+ }
380
+ function runWithTeamsTurnContext(value, fn) {
381
+ return runWithM365TurnContext2(
382
+ {
383
+ ...value,
384
+ context: {
385
+ ...value.context ?? {},
386
+ teams: value.teams
387
+ }
388
+ },
389
+ fn
390
+ );
391
+ }
392
+
393
+ // src/express.ts
394
+ import {
395
+ adaptJwtMiddleware,
396
+ processWithAdapter
397
+ } from "@cuylabs/channel-m365-agent-core/express-compat";
398
+ async function mountTeamsAgent(source, options = {}) {
399
+ const expressModule = await import("express");
400
+ const hostingModule = await import("@microsoft/agents-hosting");
401
+ const {
402
+ path: routePath = "/api/messages",
403
+ authConfig: providedAuthConfig,
404
+ port: portOption,
405
+ host,
406
+ adapter: providedAdapter,
407
+ app: providedApp,
408
+ ...adapterOptions
409
+ } = options;
410
+ const authConfig = hostingModule.getAuthConfigWithDefaults(providedAuthConfig);
411
+ const cloudAdapter = providedAdapter ?? new hostingModule.CloudAdapter(authConfig);
412
+ const expressApp = providedApp ?? expressModule.default();
413
+ const channelAdapter = createTeamsChannelAdapter({
414
+ source,
415
+ ...adapterOptions
416
+ });
417
+ const jsonParser = expressModule.json();
418
+ const jwtAuthorizer = adaptJwtMiddleware(hostingModule, authConfig);
419
+ expressApp.post(
420
+ routePath,
421
+ jsonParser,
422
+ jwtAuthorizer,
423
+ (req, res) => processWithAdapter(
424
+ cloudAdapter,
425
+ req,
426
+ res,
427
+ (context) => channelAdapter.handler(context)
428
+ )
429
+ );
430
+ const port = portOption === void 0 ? resolvePort(process.env.PORT) : portOption;
431
+ let server;
432
+ if (port !== null) {
433
+ const onListen = () => {
434
+ process.stdout.write(
435
+ `Teams agent listening on port ${port} \u2014 appId: ${authConfig.clientId ?? "(not set)"}
436
+ `
437
+ );
438
+ };
439
+ server = host ? expressApp.listen(port, host, onListen) : expressApp.listen(port, onListen);
440
+ }
441
+ return {
442
+ app: expressApp,
443
+ channelAdapter,
444
+ cloudAdapter,
445
+ server
446
+ };
447
+ }
448
+ function resolvePort(port) {
449
+ if (!port) return 3978;
450
+ const parsed = Number(port);
451
+ if (!Number.isInteger(parsed) || parsed < 0) {
452
+ throw new Error(`Invalid PORT value: ${port}`);
453
+ }
454
+ return parsed;
455
+ }
456
+
457
+ // src/interactive-requests.ts
458
+ var TEAMS_INPUT_REQUEST_APPROVAL_VERB = "cuylabs.agent.input.approval";
459
+ var TEAMS_INPUT_REQUEST_HUMAN_VERB = "cuylabs.agent.input.human";
460
+ var ADAPTIVE_CARD_CONTENT_TYPE = "application/vnd.microsoft.card.adaptive";
461
+ var DEFAULT_MAX_ARGUMENT_CHARS = 1200;
462
+ function createTeamsApprovalRequestCard(input, options = {}) {
463
+ const { request, sessionId, turnId } = normalizeInputRequest(input);
464
+ const body = [
465
+ {
466
+ type: "TextBlock",
467
+ size: "Medium",
468
+ weight: "Bolder",
469
+ text: options.title ?? "Approval required",
470
+ wrap: true
471
+ },
472
+ {
473
+ type: "FactSet",
474
+ facts: [
475
+ { title: "Tool", value: request.tool },
476
+ { title: "Risk", value: request.risk }
477
+ ]
478
+ },
479
+ {
480
+ type: "TextBlock",
481
+ text: request.description,
482
+ wrap: true
483
+ }
484
+ ];
485
+ if (options.includeArguments ?? true) {
486
+ const formattedArgs = formatToolArguments(
487
+ request.args,
488
+ options.maxArgumentChars ?? DEFAULT_MAX_ARGUMENT_CHARS
489
+ );
490
+ if (formattedArgs) {
491
+ body.push({
492
+ type: "TextBlock",
493
+ text: formattedArgs,
494
+ wrap: true,
495
+ fontType: "Monospace",
496
+ isSubtle: true
497
+ });
498
+ }
499
+ }
500
+ const rememberScopes = normalizeRememberScopes(request);
501
+ if (rememberScopes.length > 0) {
502
+ body.push({
503
+ type: "Input.ChoiceSet",
504
+ id: "rememberScope",
505
+ label: "Remember scope",
506
+ style: "compact",
507
+ value: request.defaultRememberScope ?? rememberScopes[0],
508
+ choices: rememberScopes.map((scope) => ({
509
+ title: labelRememberScope(scope),
510
+ value: scope
511
+ }))
512
+ });
513
+ }
514
+ body.push({
515
+ type: "Input.Text",
516
+ id: "feedback",
517
+ label: "Feedback",
518
+ isMultiline: true,
519
+ isRequired: false,
520
+ placeholder: "Optional"
521
+ });
522
+ const baseData = {
523
+ requestId: request.id,
524
+ sessionId,
525
+ ...turnId ? { turnId } : {}
526
+ };
527
+ const actions = [
528
+ {
529
+ type: "Action.Submit",
530
+ title: "Approve",
531
+ data: {
532
+ ...baseData,
533
+ verb: TEAMS_INPUT_REQUEST_APPROVAL_VERB,
534
+ action: "allow"
535
+ }
536
+ },
537
+ {
538
+ type: "Action.Submit",
539
+ title: "Deny",
540
+ data: {
541
+ ...baseData,
542
+ verb: TEAMS_INPUT_REQUEST_APPROVAL_VERB,
543
+ action: "deny"
544
+ }
545
+ }
546
+ ];
547
+ if (rememberScopes.length > 0) {
548
+ actions.push({
549
+ type: "Action.Submit",
550
+ title: "Remember",
551
+ data: {
552
+ ...baseData,
553
+ verb: TEAMS_INPUT_REQUEST_APPROVAL_VERB,
554
+ action: "remember"
555
+ }
556
+ });
557
+ }
558
+ return createAdaptiveCardAttachment(body, actions);
559
+ }
560
+ function createTeamsHumanInputRequestCard(input, options = {}) {
561
+ const { request, sessionId, turnId } = normalizeInputRequest(input);
562
+ const body = [
563
+ {
564
+ type: "TextBlock",
565
+ size: "Medium",
566
+ weight: "Bolder",
567
+ text: options.title ?? request.title,
568
+ wrap: true
569
+ },
570
+ {
571
+ type: "TextBlock",
572
+ text: request.question,
573
+ wrap: true
574
+ }
575
+ ];
576
+ const baseData = {
577
+ requestId: request.id,
578
+ sessionId,
579
+ ...turnId ? { turnId } : {}
580
+ };
581
+ if (request.kind === "choice") {
582
+ body.push({
583
+ type: "Input.ChoiceSet",
584
+ id: "selected",
585
+ label: request.title,
586
+ style: request.allowMultiple ? "expanded" : "compact",
587
+ isMultiSelect: request.allowMultiple ?? false,
588
+ choices: (request.options ?? []).map((option) => ({
589
+ title: option.label,
590
+ value: option.value ?? option.label
591
+ }))
592
+ });
593
+ } else if (request.kind === "text") {
594
+ body.push({
595
+ type: "Input.Text",
596
+ id: "text",
597
+ label: request.title,
598
+ isMultiline: true,
599
+ placeholder: request.placeholder ?? "Type a response"
600
+ });
601
+ } else {
602
+ body.push({
603
+ type: "Input.Text",
604
+ id: "text",
605
+ label: "Details",
606
+ isMultiline: true,
607
+ isRequired: false,
608
+ placeholder: request.placeholder ?? "Optional"
609
+ });
610
+ }
611
+ const actions = request.kind === "confirm" ? [
612
+ {
613
+ type: "Action.Submit",
614
+ title: request.confirmLabel ?? "Confirm",
615
+ data: {
616
+ ...baseData,
617
+ verb: TEAMS_INPUT_REQUEST_HUMAN_VERB,
618
+ responseKind: "confirm",
619
+ confirmed: true
620
+ }
621
+ },
622
+ {
623
+ type: "Action.Submit",
624
+ title: request.denyLabel ?? "Cancel",
625
+ data: {
626
+ ...baseData,
627
+ verb: TEAMS_INPUT_REQUEST_HUMAN_VERB,
628
+ responseKind: "confirm",
629
+ confirmed: false
630
+ }
631
+ }
632
+ ] : [
633
+ {
634
+ type: "Action.Submit",
635
+ title: request.confirmLabel ?? "Submit",
636
+ data: {
637
+ ...baseData,
638
+ verb: TEAMS_INPUT_REQUEST_HUMAN_VERB,
639
+ responseKind: request.kind
640
+ }
641
+ }
642
+ ];
643
+ return createAdaptiveCardAttachment(body, actions);
644
+ }
645
+ function parseTeamsInputRequestSubmit(value) {
646
+ const data = readSubmitData(value);
647
+ const verb = readString(data, "verb");
648
+ const requestId = readString(data, "requestId");
649
+ if (!requestId || verb !== TEAMS_INPUT_REQUEST_APPROVAL_VERB && verb !== TEAMS_INPUT_REQUEST_HUMAN_VERB) {
650
+ return void 0;
651
+ }
652
+ const sessionId = readString(data, "sessionId");
653
+ const turnId = readString(data, "turnId");
654
+ if (verb === TEAMS_INPUT_REQUEST_APPROVAL_VERB) {
655
+ const action = readApprovalAction(data);
656
+ if (!action) {
657
+ return void 0;
658
+ }
659
+ const feedback = readTrimmedString(data, "feedback");
660
+ const rememberScope = action === "remember" ? readRememberScope(data) : void 0;
661
+ return {
662
+ verb,
663
+ requestId,
664
+ ...sessionId ? { sessionId } : {},
665
+ ...turnId ? { turnId } : {},
666
+ payload: {
667
+ kind: "approval",
668
+ action,
669
+ ...feedback ? { feedback } : {},
670
+ ...rememberScope ? { rememberScope } : {}
671
+ }
672
+ };
673
+ }
674
+ const response = readHumanInputResponse(data);
675
+ if (!response) {
676
+ return void 0;
677
+ }
678
+ return {
679
+ verb,
680
+ requestId,
681
+ ...sessionId ? { sessionId } : {},
682
+ ...turnId ? { turnId } : {},
683
+ payload: {
684
+ kind: "human",
685
+ response
686
+ }
687
+ };
688
+ }
689
+ function createAdaptiveCardAttachment(body, actions) {
690
+ return {
691
+ contentType: ADAPTIVE_CARD_CONTENT_TYPE,
692
+ content: {
693
+ type: "AdaptiveCard",
694
+ version: "1.5",
695
+ body,
696
+ actions
697
+ }
698
+ };
699
+ }
700
+ function normalizeInputRequest(input) {
701
+ if ("request" in input) {
702
+ return {
703
+ request: input.request,
704
+ sessionId: input.sessionId ?? input.request.sessionId,
705
+ ...input.turnId ? { turnId: input.turnId } : {}
706
+ };
707
+ }
708
+ return {
709
+ request: input,
710
+ sessionId: input.sessionId
711
+ };
712
+ }
713
+ function formatToolArguments(args, maxChars) {
714
+ let formatted;
715
+ try {
716
+ formatted = JSON.stringify(args, null, 2);
717
+ } catch {
718
+ return "";
719
+ }
720
+ if (!formatted || formatted === "undefined") {
721
+ return "";
722
+ }
723
+ if (formatted.length <= maxChars) {
724
+ return formatted;
725
+ }
726
+ return `${formatted.slice(0, Math.max(0, maxChars - 1))}...`;
727
+ }
728
+ function normalizeRememberScopes(request) {
729
+ const allowed = /* @__PURE__ */ new Set([
730
+ "session",
731
+ "project",
732
+ "user"
733
+ ]);
734
+ return (request.rememberScopes ?? []).filter((scope) => allowed.has(scope));
735
+ }
736
+ function labelRememberScope(scope) {
737
+ switch (scope) {
738
+ case "session":
739
+ return "This session";
740
+ case "project":
741
+ return "This project";
742
+ case "user":
743
+ return "My user";
744
+ }
745
+ }
746
+ function readSubmitData(value) {
747
+ const record = asRecord(value);
748
+ const nested = asRecord(record?.data);
749
+ return {
750
+ ...nested ?? {},
751
+ ...record ?? {}
752
+ };
753
+ }
754
+ function readHumanInputResponse(data) {
755
+ const responseKind = readString(data, "responseKind");
756
+ switch (responseKind) {
757
+ case "text": {
758
+ const text = readString(data, "text") ?? "";
759
+ return { kind: "text", text };
760
+ }
761
+ case "confirm": {
762
+ const confirmed = readBoolean(data, "confirmed");
763
+ if (confirmed === void 0) {
764
+ return void 0;
765
+ }
766
+ const text = readString(data, "text") ?? (confirmed ? "confirmed" : "denied");
767
+ return { kind: "confirm", confirmed, text };
768
+ }
769
+ case "choice": {
770
+ const selected = readSelectedValues(data, "selected");
771
+ return { kind: "choice", selected, text: selected.join(", ") };
772
+ }
773
+ default:
774
+ return void 0;
775
+ }
776
+ }
777
+ function readApprovalAction(data) {
778
+ const action = readString(data, "action");
779
+ return action === "allow" || action === "deny" || action === "remember" ? action : void 0;
780
+ }
781
+ function readRememberScope(data) {
782
+ const scope = readString(data, "rememberScope");
783
+ return scope === "session" || scope === "project" || scope === "user" ? scope : void 0;
784
+ }
785
+ function readSelectedValues(data, key) {
786
+ const value = data[key];
787
+ if (Array.isArray(value)) {
788
+ return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
789
+ }
790
+ if (typeof value === "string") {
791
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
792
+ }
793
+ return [];
794
+ }
795
+ function readTrimmedString(data, key) {
796
+ return readString(data, key)?.trim() || void 0;
797
+ }
798
+ function readString(data, key) {
799
+ const value = data?.[key];
800
+ return typeof value === "string" ? value : void 0;
801
+ }
802
+ function readBoolean(data, key) {
803
+ const value = data[key];
804
+ if (typeof value === "boolean") {
805
+ return value;
806
+ }
807
+ if (value === "true") {
808
+ return true;
809
+ }
810
+ if (value === "false") {
811
+ return false;
812
+ }
813
+ return void 0;
814
+ }
815
+ function asRecord(value) {
816
+ return value && typeof value === "object" ? value : void 0;
817
+ }
818
+ export {
819
+ Conversation,
820
+ ConversationBuilder,
821
+ ConversationReferenceBuilder,
822
+ CreateConversationOptionsBuilder,
823
+ TEAMS_INPUT_REQUEST_APPROVAL_VERB,
824
+ TEAMS_INPUT_REQUEST_HUMAN_VERB,
825
+ captureM365ConversationReference,
826
+ captureTeamsConversationReference,
827
+ continueM365Conversation,
828
+ createTeamsApprovalRequestCard,
829
+ createTeamsChannelAdapter,
830
+ createTeamsHumanInputRequestCard,
831
+ currentTeamsTurnContext,
832
+ mountTeamsAgent,
833
+ parseTeamsInputRequestSubmit,
834
+ restoreM365ConversationReference,
835
+ runWithTeamsTurnContext
836
+ };