@microsoft/teams.api
Version:
<p> <a href="https://www.npmjs.com/package/@microsoft/teams.api" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.api/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.api?activeTab=code" t
584 lines (582 loc) • 16.8 kB
JavaScript
'use strict';
class ActivityInput {
/**
* Activity type discriminator.
*/
type;
/**
* Optional activity ID used when updating an existing sent activity.
*/
id;
/**
* Optional recipient account.
*/
recipient;
/**
* ID of the activity this outbound activity replies to.
*/
replyToId;
/**
* Entities attached to the outbound activity.
*/
entities;
/**
* Channel-specific metadata for the outbound activity.
*/
channelData;
/**
* Create an outbound activity input.
* @param type - Activity type discriminator.
* @param value - Initial outbound activity fields.
*/
constructor(type, value = {}) {
Object.assign(this, value);
this.type = type;
}
/**
* Set the activity ID for update scenarios.
* @param value - Activity ID.
*/
withId(value) {
this.id = value;
return this;
}
/**
* Set the activity recipient.
* @param value - Recipient account.
* @param isTargeted - Whether the activity is targeted only to this recipient.
*/
withRecipient(value, isTargeted = false) {
this.recipient = { ...value, isTargeted: isTargeted ? true : void 0 };
return this;
}
/**
* Merge channel-specific metadata into the outbound activity.
* @param value - Channel metadata to merge.
*/
withChannelData(value) {
const merged = { ...this.channelData, ...value };
if (merged.feedbackLoop !== void 0) {
merged.feedbackLoopEnabled = void 0;
} else if (merged.feedbackLoopEnabled === true) {
merged.feedbackLoop = { type: "default" };
merged.feedbackLoopEnabled = void 0;
}
this.channelData = merged;
return this;
}
/**
* Add an entity to the outbound activity.
* @param value - Entity to add.
*/
addEntity(value) {
if (this.isRootLevelMessageEntity(value)) {
this.mergeRootLevelMessageEntity(this.ensureSingleRootLevelMessageEntity(), value);
return this;
}
if (!this.entities) {
this.entities = [];
}
this.entities.push(value);
return this;
}
/**
* Add multiple entities to the outbound activity.
* @param value - Entities to add.
*/
addEntities(...value) {
for (const entity of value) {
this.addEntity(entity);
}
return this;
}
/**
* Add the `Generated By AI` label.
*/
addAiGenerated() {
const messageEntity = this.ensureSingleRootLevelMessageEntity();
if (messageEntity.additionalType?.includes("AIGeneratedContent")) {
return this;
}
if (!messageEntity.additionalType) {
messageEntity.additionalType = [];
}
messageEntity.additionalType.push("AIGeneratedContent");
return this;
}
/**
* Add a Microsoft Purview sensitivity label to the message.
* Replaces any label previously added.
* @param label - The sensitivity label, identified by its Purview label ID.
*/
addSensitivityLabel(label) {
const messageEntity = this.ensureSingleRootLevelMessageEntity();
messageEntity.usageInfo = { ...label, "@type": label["@type"] ?? "CreativeWork" };
return this;
}
/**
* Enable message feedback.
* @param mode - `'default'` shows Teams' built-in thumbs up/down UI.
* `'custom'` triggers a `message/fetchTask` invoke so the bot can return its own task module dialog.
*/
addFeedback(mode = "default") {
if (!this.channelData) {
this.channelData = {};
}
this.channelData.feedbackLoop = { type: mode };
this.channelData.feedbackLoopEnabled = void 0;
return this;
}
/**
* Add citations
* @param position - Citation position in the message text.
* @param appearance - Citation appearance metadata.
*/
addCitation(position, appearance) {
const messageEntity = this.ensureSingleRootLevelMessageEntity();
if (!messageEntity.citation) {
messageEntity.citation = [];
}
messageEntity.citation.push({
"@type": "Claim",
position,
appearance: {
"@type": "DigitalDocument",
abstract: appearance.abstract,
name: appearance.name,
encodingFormat: appearance.text ? "application/vnd.microsoft.card.adaptive" : void 0,
image: appearance.icon ? {
"@type": "ImageObject",
name: appearance.icon
} : void 0,
keywords: appearance.keywords,
text: appearance.text,
url: appearance.url,
usageInfo: appearance.usageInfo ? { ...appearance.usageInfo, "@type": appearance.usageInfo["@type"] ?? "CreativeWork" } : void 0
}
});
return this;
}
/**
* Add a targeted message info entity for prompt preview.
* Skips if already present.
*
* @param messageId the message ID of the targeted message
*/
addTargetedMessageInfo(messageId) {
if (this.entities) {
this.entities = this.entities.filter((e) => e.type !== "quotedReply");
}
if (this.type === "message") {
const msg = this;
if (msg.text) {
msg.text = msg.text.replace(`<quoted messageId="${messageId}"/>`, "").trim();
}
}
if (this.entities?.some((e) => e.type === "targetedMessageInfo")) {
return this;
}
return this.addEntity({
type: "targetedMessageInfo",
messageId
});
}
/**
* Determine whether the activity contains stream metadata.
*/
isStreaming() {
return this.entities?.some((e) => e.type === "streaminfo") || false;
}
/**
* Get or create the base message entity.
* There should only be one root level message entity.
*/
ensureSingleRootLevelMessageEntity() {
let messageEntity = this.entities?.find(
(e) => this.isRootLevelMessageEntity(e)
);
if (!messageEntity) {
messageEntity = {
type: "https://schema.org/Message",
"@type": "Message",
"@context": "https://schema.org",
"@id": ""
};
if (!this.entities) {
this.entities = [];
}
this.entities.push(messageEntity);
}
return messageEntity;
}
isRootLevelMessageEntity(entity) {
return entity.type === "https://schema.org/Message" && entity["@type"] === "Message";
}
mergeRootLevelMessageEntity(target, source) {
const merged = {
...target,
...source
};
if (target.additionalType || source.additionalType) {
merged.additionalType = [
.../* @__PURE__ */ new Set([...target.additionalType || [], ...source.additionalType || []])
];
}
if (target.citation || source.citation) {
const dedupedCitations = /* @__PURE__ */ new Map();
for (const citation of [...target.citation || [], ...source.citation || []]) {
dedupedCitations.set(citation.position, citation);
}
merged.citation = Array.from(dedupedCitations.values());
}
Object.assign(target, merged);
return target;
}
}
class Activity {
/**
* Contains the type of the activity.
*/
type;
/**
* Contains an ID that uniquely identifies the activity on the channel.
*/
id;
/**
* Contains the URL that specifies the channel's service endpoint. Set by the channel.
*/
serviceUrl;
/**
* Contains the date and time that the message was sent, in UTC, expressed in ISO-8601 format.
*/
timestamp;
/**
* A locale name for the contents of the text field.
* The locale name is a combination of an ISO 639 two- or three-letter culture code associated
* with a language
* and an ISO 3166 two-letter subculture code associated with a country or region.
* The locale name can also correspond to a valid BCP-47 language tag.
*/
locale;
/**
* Contains the local date and time of the message, expressed in ISO-8601 format.
*
* For example, 2016-09-23T13:07:49.4714686-07:00.
*/
localTimestamp;
/**
* Contains an ID that uniquely identifies the channel. Set by the channel.
*/
channelId;
/**
* Identifies the sender of the message.
*/
from;
/**
* Identifies the conversation to which the activity belongs.
*/
conversation;
/**
* A reference to another conversation or activity.
* @deprecated This will be removed by end of summer 2026.
*/
relatesTo;
/**
* Identifies the recipient of the message.
*/
recipient;
/**
* Contains the ID of the message to which this message is a reply.
*/
replyToId;
/**
* Represents the entities that were mentioned in the message.
*/
entities;
/**
* Contains channel-specific content.
*/
channelData;
/**
* Information about the tenant in which the message was sent.
*/
get tenant() {
return this.channelData?.tenant;
}
/**
* Information about the channel in which the message was sent.
*/
get channel() {
return this.channelData?.channel;
}
/**
* Information about the team in which the message was sent.
*/
get team() {
return this.channelData?.team;
}
/**
* Information about the tenant in which the message was sent.
*/
get meeting() {
return this.channelData?.meeting;
}
/**
* Notification settings for the message.
*/
get notification() {
return this.channelData?.notification;
}
constructor(value) {
Object.assign(this, {
channelId: "msteams",
...value
});
}
static from(activity) {
return new Activity(activity);
}
toInterface() {
return Object.assign({}, this);
}
clone(options = {}) {
return new Activity({
...this.toInterface(),
...options
});
}
withId(value) {
this.id = value;
return this;
}
withChannelId(value) {
this.channelId = value;
return this;
}
withFrom(value) {
this.from = value;
return this;
}
withConversation(value) {
this.conversation = value;
return this;
}
/**
* @deprecated This will be removed by end of summer 2026.
*/
withRelatesTo(value) {
this.relatesTo = value;
return this;
}
/**
* Set the recipient of this activity, optionally marking it as a targeted message.
* Targeted messages are ephemeral to the specified recipient in a shared conversation.
* @param value - The recipient account
* @param isTargeted - If true, marks this as a targeted message visible only to the recipient (default: false)
* @returns this instance for chaining
*
* @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities.
*/
withRecipient(value, isTargeted = false) {
this.recipient = { ...value, isTargeted: isTargeted ? true : void 0 };
return this;
}
withServiceUrl(value) {
this.serviceUrl = value;
return this;
}
withTimestamp(value) {
this.timestamp = value;
return this;
}
withLocale(value) {
this.locale = value;
return this;
}
withLocalTimestamp(value) {
this.localTimestamp = value;
return this;
}
/**
* @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities.
*/
withChannelData(value) {
const merged = { ...this.channelData, ...value };
if (merged.feedbackLoop !== void 0) {
merged.feedbackLoopEnabled = void 0;
} else if (merged.feedbackLoopEnabled === true) {
merged.feedbackLoop = { type: "default" };
merged.feedbackLoopEnabled = void 0;
}
this.channelData = merged;
return this;
}
/**
* Add an entity.
*/
addEntity(value) {
if (this.isRootLevelMessageEntity(value)) {
this.mergeRootLevelMessageEntity(this.ensureSingleRootLevelMessageEntity(), value);
return this;
}
if (!this.entities) {
this.entities = [];
}
this.entities.push(value);
return this;
}
/**
* Add multiple entities
*/
addEntities(...value) {
for (const entity of value) {
this.addEntity(entity);
}
return this;
}
/**
* Add the `Generated By AI` label.
*
* @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities.
*/
addAiGenerated() {
const messageEntity = this.ensureSingleRootLevelMessageEntity();
if (messageEntity.additionalType?.includes("AIGeneratedContent")) {
return this;
}
if (!messageEntity.additionalType) {
messageEntity.additionalType = [];
}
messageEntity.additionalType.push("AIGeneratedContent");
return this;
}
/**
* Enable message feedback.
* @param mode - `'default'` shows Teams' built-in thumbs up/down UI.
* `'custom'` triggers a `message/fetchTask` invoke so the bot can return its own task module dialog.
*
* @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities.
*/
addFeedback(mode = "default") {
if (!this.channelData) {
this.channelData = {};
}
this.channelData.feedbackLoop = { type: mode };
this.channelData.feedbackLoopEnabled = void 0;
return this;
}
/**
* Add citations
*
* @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities.
*/
addCitation(position, appearance) {
const messageEntity = this.ensureSingleRootLevelMessageEntity();
if (!messageEntity.citation) {
messageEntity.citation = [];
}
messageEntity.citation.push({
"@type": "Claim",
position,
appearance: {
"@type": "DigitalDocument",
abstract: appearance.abstract,
name: appearance.name,
encodingFormat: appearance.text ? "application/vnd.microsoft.card.adaptive" : void 0,
image: appearance.icon ? {
"@type": "ImageObject",
name: appearance.icon
} : void 0,
keywords: appearance.keywords,
text: appearance.text,
url: appearance.url,
usageInfo: appearance.usageInfo ? { ...appearance.usageInfo, "@type": appearance.usageInfo["@type"] ?? "CreativeWork" } : void 0
}
});
return this;
}
/**
* Add a targeted message info entity for prompt preview.
* Skips if already present. In reactive flows, `ctx.send()` and `ctx.reply()`
* populate this automatically — use this helper for proactive or deferred sends.
* An invalid or expired messageId causes the Teams service to silently drop the preview
* while still delivering the message.
*
* @param messageId the message ID of the targeted message (from the incoming activity's `id`)
*
* @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities.
*/
addTargetedMessageInfo(messageId) {
if (this.entities) {
this.entities = this.entities.filter((e) => e.type !== "quotedReply");
}
if (this.type === "message") {
const msg = this;
if (msg.text) {
msg.text = msg.text.replace(`<quoted messageId="${messageId}"/>`, "").trim();
}
}
if (this.entities?.some((e) => e.type === "targetedMessageInfo")) {
return this;
}
return this.addEntity({
type: "targetedMessageInfo",
messageId
});
}
/**
* is this a streaming activity
*/
isStreaming() {
return this.entities?.some((e) => e.type === "streaminfo") || false;
}
/**
* Get or create the base message entity.
* There should only be one root level message entity.
*/
ensureSingleRootLevelMessageEntity() {
let messageEntity = this.entities?.find(
(e) => this.isRootLevelMessageEntity(e)
);
if (!messageEntity) {
messageEntity = {
type: "https://schema.org/Message",
"@type": "Message",
"@context": "https://schema.org",
"@id": ""
};
if (!this.entities) {
this.entities = [];
}
this.entities.push(messageEntity);
}
return messageEntity;
}
isRootLevelMessageEntity(entity) {
return entity.type === "https://schema.org/Message" && entity["@type"] === "Message";
}
mergeRootLevelMessageEntity(target, source) {
const merged = {
...target,
...source
};
if (target.additionalType || source.additionalType) {
merged.additionalType = [
.../* @__PURE__ */ new Set([...target.additionalType || [], ...source.additionalType || []])
];
}
if (target.citation || source.citation) {
const dedupedCitations = /* @__PURE__ */ new Map();
for (const citation of [...target.citation || [], ...source.citation || []]) {
dedupedCitations.set(citation.position, citation);
}
merged.citation = Array.from(dedupedCitations.values());
}
Object.assign(target, merged);
return target;
}
}
exports.Activity = Activity;
exports.ActivityInput = ActivityInput;
//# sourceMappingURL=activity.js.map
//# sourceMappingURL=activity.js.map