/** * TeamsClient — the public API for interacting with Microsoft Teams. * * This is the primary entry point for the teams-api package. * It wraps authentication, conversation listing, message reading/sending, * and member management behind a clean, strongly-typed interface. * * @example * // Auto-login (macOS with FIDO2 passkey) * const client = await TeamsClient.fromAutoLogin({ * email: "user@company.com", * }); * * // List conversations * const conversations = await client.listConversations(); * * // Read messages * const messages = await client.getMessages(conversations[0].id); * * // Send a message * await client.sendMessage(conversations[0].id, "Hello from the API!"); * * @example * // From an existing token * const client = TeamsClient.fromToken( * "skype-token-here", * "apac", * "optional-bearer-token", * "optional-substrate-token", * ); */ import type { TeamsToken, AutoLoginOptions, InteractiveLoginOptions, ManualTokenOptions, SmartLoginOptions, Conversation, Message, MessageFormat, Member, SentMessage, EditedMessage, DeletedMessage, ReactionResult, ScheduledMessage, GetMessagesOptions, ListConversationsOptions, ListConversationsPageOptions, ConversationsPage, OneOnOneSearchResult, PersonSearchResult, ChatSearchResult, SearchMessagesOptions, MessageSearchPage, MessagesPage, TranscriptResult, MessageContentPart, FileSharingScope, UserProfile, ReplyCheckResult } from "./types.js"; export { acquireTokenViaAutoLogin } from "./auth/auto-login.js"; export { acquireTokenViaInteractiveLogin } from "./auth/interactive.js"; export { acquireTokenViaDebugSession } from "./auth/debug-session.js"; export { acquireTokenViaSmartLogin } from "./smart-login.js"; export type { TeamsToken, AutoLoginOptions, InteractiveLoginOptions, ManualTokenOptions, SmartLoginOptions, Conversation, Message, MessageFormat, Member, SentMessage, EditedMessage, DeletedMessage, ReactionResult, GetMessagesOptions, ListConversationsOptions, ListConversationsPageOptions, ConversationsPage, OneOnOneSearchResult, MessagesPage, Mention, Reaction, Follower, UserProfile, PersonSearchResult, ChatSearchResult, SearchMessagesOptions, MessageSearchResult, MessageSearchPage, TranscriptEntry, TranscriptResult, ImageAttachment, FileAttachment, MessageContentPart, FileSharingScope, } from "./types.js"; export { SYSTEM_STREAM_TYPES } from "./types.js"; export { isTextMessageType } from "./constants.js"; export { parseRawMessage } from "./api/chat-service.js"; export { ApiAuthError, ApiRateLimitError } from "./api/common.js"; export { fetchProfiles } from "./api/middle-tier.js"; export { searchPeople, searchChats } from "./api/substrate.js"; export { fetchTranscript, fetchTranscriptVtt, parseVtt, extractTranscriptUrl, extractMeetingTitle, isSuccessfulRecording, } from "./api/transcripts.js"; export { fetchAmsImage, uploadAmsImage, buildAmsImageTag, parseInlineImages, parseFileAttachments, uploadSharePointFile, buildFilesPropertyJson, createSharePointSharingLink, } from "./api/attachments.js"; export type { SharePointUploadResult } from "./api/attachments.js"; export { describeImageWithOpenAiCompatibleVision } from "./api/image-description.js"; export type { DescribeImageOptions, ImageDescriptionResult, } from "./api/image-description.js"; export { saveToken, loadToken, clearToken } from "./token-store.js"; export { actions } from "./actions/definitions.js"; export { formatOutput } from "./actions/formatters.js"; export type { ActionDefinition, ActionParameter, OutputFormat, } from "./actions/formatters.js"; export declare class TeamsClient { private token; private autoLoginOptions; private smartLoginOptions; private cachedDisplayName; private cachedUserPrincipalName; private userEmail; private constructor(); /** * Create a client with secure token caching and automatic refresh. * * This is the recommended entry point. It: * 1. Checks the macOS Keychain for a cached, non-expired token * 2. If none found, launches auto-login to acquire a fresh token * 3. Saves the token to the Keychain for future use * 4. Automatically re-acquires the token if a 401 occurs mid-session * * Token lifetime is ~24 hours. Cached tokens are reused within 23 hours. */ static create(options: AutoLoginOptions): Promise; /** * Create a client with smart cross-platform login. * * Zero-config default: automatically picks the best auth strategy: * - macOS with Chrome + email: tries auto-login (FIDO2), falls back to interactive * - All other cases: interactive browser login (works everywhere) * * Tokens are cached in the platform credential store and reused * until they expire (~23 hours). */ static connect(options?: SmartLoginOptions): Promise; /** * Create a client by automatically logging in via FIDO2 passkey. * * Launches system Chrome with a fresh profile, completes the Microsoft * Entra ID FIDO2 login flow using a platform authenticator, and * captures the skype token. Zero user interaction required. * * Tokens are cached in the platform credential store. */ static fromAutoLogin(options: AutoLoginOptions): Promise; /** * Create a client by connecting to a running Chrome debug session. * * Requires Chrome started with --remote-debugging-port and Teams * already open and authenticated. * * Tokens are cached in the platform credential store. */ static fromDebugSession(options?: ManualTokenOptions): Promise; /** * Create a client via interactive browser login. * * Opens a visible Chromium window where the user manually logs into * Teams. Works on all platforms (macOS, Windows, Linux) without * requiring FIDO2 passkeys or system Chrome. * * Tokens are cached in the platform credential store. */ static fromInteractiveLogin(options?: InteractiveLoginOptions): Promise; /** * Create a client from an existing token bundle. * * Pass a complete `TeamsToken` to restore all captured tokens, including * `chatBearerToken` for accounts that do not issue a Skype token. * `bearerToken` enables profile/member resolution and `substrateToken` * enables reliable people/chat search. Both are optional; basic chat * operations require either `skypeToken` or `chatBearerToken`. */ static fromToken(token: TeamsToken): TeamsClient; static fromToken(skypeToken: string, region?: string, bearerToken?: string, substrateToken?: string, amsToken?: string, sharePointToken?: string, sharePointHost?: string): TeamsClient; /** * Clear a cached token from the platform credential store. * * Use this to force a fresh login on the next `create()` or `connect()` call. */ static clearCachedToken(email: string): Promise; /** Get the underlying token (for persistence or debugging). */ getToken(): TeamsToken; /** * Set the user's email address (needed for SharePoint file uploads). * * Automatically set when using `create()` or `fromAutoLogin()`. * Call this manually when using `fromToken()`, `fromDebugSession()`, * or `fromInteractiveLogin()` if file upload is needed. */ setEmail(email: string): void; /** * List conversations (chats, group chats, meetings, channels). * * By default, excludes system streams (annotations, notifications, * mentions). Set `excludeSystemStreams: false` to include everything. */ listConversations(options?: ListConversationsOptions): Promise; /** * Fetch one conversation page, preserving its continuation URL. * Follow backwardLink until null, even when a filtered page is empty. * Set enrichNames: false for metadata-only enumeration. */ listConversationsPage(options?: ListConversationsPageOptions): Promise; private prepareConversations; /** * Enrich untitled conversations with display names derived from members. * * - 1:1 chats → other member's display name (e.g. "Alice Smith") * - Group chats → comma-separated member names excluding the current user * (e.g. "Alice, Bob"), matching the Teams UI behavior */ private resolveUntitledDisplayNames; /** * Find a conversation by topic name (case-insensitive partial match). * * When a Substrate token is available, also searches via the Substrate * chat search API for matches by name or member. Falls back to local * topic matching when Substrate is unavailable. */ findConversation(query: string): Promise; /** * Get Teams profiles for one or more user MRIs. */ getProfiles(userIdentifiers: string[]): Promise; /** * Search for people in the organization directory by name. * * Primary: Substrate search API (requires Substrate token). * Fallback: resolves members of recent conversations via the * middle-tier profile API (requires Bearer token). Extracts * member UUIDs directly from 1:1 conversation IDs (zero extra * API calls for those) and scans a limited set of group chats. */ findPeople(query: string, maxResults?: number): Promise; searchMessages(options: SearchMessagesOptions): Promise; /** * Search for chats by name or member name. * * Primary: Substrate search API (requires Substrate token). * Fallback: local topic matching on listed conversations. */ findChats(query: string, maxResults?: number): Promise; /** * Find a 1:1 conversation with a specific person. * * Tries multiple strategies in order: * 1. Self-chat check (if the name matches the current user) * 2. Substrate people/chat search (if Substrate token available) * 3. Profile-based 1:1 matching (if Bearer token available) — * extracts member UUIDs from conversation IDs and resolves * display names via the middle-tier profile API * 4. Message sender scanning (slowest, always available) */ findOneOnOneConversation(personName: string): Promise; /** * Get messages from a conversation. * * Follows pagination links to fetch message history. * Use `limit` to cap the total number of messages returned. * Use `since` to only return messages created after a given timestamp. * Use `maxPages` and `pageSize` to fine-tune pagination behaviour. */ getMessages(conversationId: string, options?: GetMessagesOptions): Promise; /** * Get one page of messages from a conversation. * * Returns the page along with a backwardLink for manual pagination. */ getMessagesPage(conversationId: string, pageSize?: number, backwardLink?: string): Promise; private enrichMessageParticipantDisplayNames; /** * Send a message to a conversation. * * The `format` parameter controls how `content` is interpreted: * - `"text"` — plain text, sent as-is * - `"markdown"` (default) — converted from Markdown to HTML * - `"html"` — raw HTML, sent as-is * * The `subject` parameter sets the post title, which is displayed prominently * above the message body in channel posts. */ sendMessage(conversationId: string, content: string, format?: MessageFormat, amsReferences?: string[], subject?: string, quoteMessageId?: string): Promise; /** * Check whether a message has thread replies. * * Fetches a small batch of messages from the thread context and filters out * the root message and system events to determine if real replies exist. */ checkForReplies(conversationId: string, messageId: string): Promise; /** * Edit an existing message in a conversation. * * The `format` parameter controls how `content` is interpreted: * - `"text"` — plain text, sent as-is * - `"markdown"` (default) — converted from Markdown to HTML * - `"html"` — raw HTML, sent as-is */ editMessage(conversationId: string, messageId: string, content: string, format?: MessageFormat, quoteMessageId?: string): Promise; /** * Look up a message in a conversation and build quote HTML for it. * * Fetches up to 200 recent messages (newest-first) to find the target. * Since quotes typically reference recent messages, this handles the * common case efficiently with a single page fetch. */ private buildQuoteHtmlForMessage; /** Delete a message from a conversation. */ deleteMessage(conversationId: string, messageId: string): Promise; /** * Add a reaction (emotion) to a message. * * Accepts user-friendly shortcuts (e.g. "horse") which are automatically * resolved to the Teams emoji ID (e.g. "1f40e_horse"). * Standard reactions ("like", "heart", "laugh", "surprised") work as-is. */ addReaction(conversationId: string, messageId: string, reactionKey: string): Promise; /** * Remove a reaction (emotion) from a message. * * Accepts user-friendly shortcuts (e.g. "horse") which are automatically * resolved to the Teams emoji ID (e.g. "1f40e_horse"). * Only removes the current user's reaction of the specified type. */ removeReaction(conversationId: string, messageId: string, reactionKey: string): Promise; /** * Schedule a message to be sent at a future time. * * The `format` parameter controls how `content` is interpreted: * - `"text"` — plain text, sent as-is * - `"markdown"` (default) — converted from Markdown to HTML * - `"html"` — raw HTML, sent as-is */ scheduleMessage(conversationId: string, content: string, scheduleAt: Date, format?: MessageFormat, amsReferences?: string[], subject?: string): Promise; /** * Download an image attachment from the AMS (Async Media Service). * * @param amsObjectId - The AMS object ID from an ImageAttachment * @param fullSize - If true, download the full-size image; otherwise compressed (default: false) * @returns Binary image data with content type and size */ downloadImage(amsObjectId: string, fullSize?: boolean): Promise<{ data: Buffer; contentType: string; size: number; }>; /** * Download a file attachment from SharePoint. * * @param fileUrl - The direct SharePoint file URL from a FileAttachment * @param itemId - The SharePoint item ID (unique GUID) from a FileAttachment * @returns Binary file data with content type, size, and file name */ downloadFile(fileUrl: string, itemId: string): Promise<{ data: Buffer; contentType: string; size: number; fileName: string; }>; /** * Send a message with inline images. * * Uploads each image to AMS, sets permissions for the conversation, * and constructs the message HTML with embedded `` tags. * * Content sections and images are interleaved in order. Use `contentParts` * to specify the sequence of text and image content. * * @example * await client.sendMessageWithImages(conversationId, [ * { type: "text", text: "Check out this screenshot:" }, * { type: "image", data: imageBuffer, fileName: "screenshot.png", contentType: "image/png" }, * { type: "text", text: "And another one:" }, * { type: "image", data: image2Buffer, fileName: "screenshot2.png", contentType: "image/png" }, * ]); */ sendMessageWithImages(conversationId: string, contentParts: MessageContentPart[], subject?: string): Promise; /** * Send a message with file attachments (uploaded to SharePoint). * * Uploads each file to the sender's OneDrive "Microsoft Teams Chat Files" * folder, then sends a message referencing the uploaded files via * `properties.files` JSON. * * Content sections, images, and files are handled together. Images are * uploaded to AMS (inline), files to SharePoint (as attachments). * * Requires a SharePoint token (captured during authentication) and the * user's email (set via `setEmail()` or automatically during `create()`). * * @example * await client.sendMessageWithFiles(conversationId, [ * { type: "text", text: "Here's the document:" }, * { type: "file", data: fileBuffer, fileName: "report.md" }, * ]); * * @param fileSharingScope - Default sharing scope for all files in this message. * Individual files can override this via `part.sharingScope`. * - `"chat"` (default) — share with chat participants only. * - `"organization"` — anyone in the org with the link. * - `"none"` — no sharing link; only the uploader can access. */ sendMessageWithFiles(conversationId: string, contentParts: MessageContentPart[], fileSharingScope?: FileSharingScope, subject?: string): Promise; /** * Get members of a conversation. * * Display names are resolved via the Teams middle-tier profile API when a * Bearer token is available. Falls back to scanning message history when it * is not. */ getMembers(conversationId: string): Promise; /** * Get the meeting transcript for a conversation. * * Searches messages for a successful recording, extracts the AMS * transcript URL, fetches the VTT, and parses it into structured entries. */ getTranscript(conversationId: string): Promise; /** * Resolve emails of all members in a conversation (for user-scoped sharing). */ private resolveMemberEmails; /** * Convert a per-file or default sharing scope into SharingLinkOptions. */ private resolveFileSharingOptions; /** * Get the display name of the currently authenticated user. */ getCurrentUserDisplayName(): Promise; private resolveCurrentUserIdentity; /** * Re-acquire the token and update the cached version. * * Called automatically by `withTokenRefresh` on 401 errors. * Supports both auto-login and smart login paths. */ private refreshToken; /** * Wrap an operation with automatic token refresh on 401. * * If the operation throws an `ApiAuthError` and auto-login or * smart-login options are configured, the token is re-acquired * and the operation retried exactly once. */ private withTokenRefresh; } //# sourceMappingURL=teams-client.d.ts.map