🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@wecom/aibot-node-sdk

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wecom/aibot-node-sdk - npm Package Compare versions

Comparing version
1.0.4
to
1.0.5-beta.0
+26
-0
dist/client.d.ts

@@ -184,2 +184,28 @@ import { EventEmitter } from 'eventemitter3';

/**
* 检查指定消息帧是否有未完成的 ack(即上一条消息还未收到回执)
*
* 用于流式场景:调用方可据此决定是否跳过当前中间帧,避免排队积压。
*
* @param frame - 收到的原始 WebSocket 帧
* @returns true 表示有消息正在等待 ack
*/
hasPendingReplyAck(frame: WsFrameHeaders): boolean;
/**
* 非阻塞流式文本回复
*
* 如果上一条同 reqId 的消息尚未收到 ack,则跳过本次发送(返回 'skipped'),
* 避免流式中间帧排队积压导致延迟。
*
* 注意:finish=true 的最终帧不受此限制,始终保证发送(走正常队列)。
*
* @param frame - 收到的原始 WebSocket 帧
* @param streamId - 流式消息 ID
* @param content - 回复内容
* @param finish - 是否结束流式消息
* @param msgItem - 图文混排项(仅在 finish=true 时有效),用于在结束时附带图片内容
* @param feedback - 反馈信息(仅在首次回复时设置)
* @returns Promise<WsFrame> 正常发送时返回回执帧,跳过时返回 'skipped'
*/
replyStreamNonBlocking(frame: WsFrameHeaders, streamId: string, content: string, finish?: boolean, msgItem?: ReplyMsgItem[], feedback?: ReplyFeedback): Promise<WsFrame | 'skipped'>;
/**
* 获取当前连接状态

@@ -186,0 +212,0 @@ */

@@ -57,2 +57,4 @@ 'use strict';

MessageType["File"] = "file";
/** 视频消息 */
MessageType["Video"] = "video";
})(exports.MessageType || (exports.MessageType = {}));

@@ -722,2 +724,13 @@

/**
* 检查指定 reqId 是否有待回执的消息(即上一条消息还未收到 ack)
*
* 用于流式场景:调用方可据此决定是否跳过当前帧,避免排队积压。
*
* @param reqId - 要检查的 req_id
* @returns true 表示有消息正在等待 ack
*/
hasPendingAck(reqId) {
return this.pendingAcks.has(reqId);
}
/**
* 获取当前连接状态

@@ -791,2 +804,5 @@ */

break;
case exports.MessageType.Video:
emitter.emit('message.video', frame);
break;
default:

@@ -1340,2 +1356,37 @@ this.logger.debug(`Received unhandled message type: ${body.msgtype}`);

/**
* 检查指定消息帧是否有未完成的 ack(即上一条消息还未收到回执)
*
* 用于流式场景:调用方可据此决定是否跳过当前中间帧,避免排队积压。
*
* @param frame - 收到的原始 WebSocket 帧
* @returns true 表示有消息正在等待 ack
*/
hasPendingReplyAck(frame) {
const reqId = frame.headers?.req_id || '';
return this.wsManager.hasPendingAck(reqId);
}
/**
* 非阻塞流式文本回复
*
* 如果上一条同 reqId 的消息尚未收到 ack,则跳过本次发送(返回 'skipped'),
* 避免流式中间帧排队积压导致延迟。
*
* 注意:finish=true 的最终帧不受此限制,始终保证发送(走正常队列)。
*
* @param frame - 收到的原始 WebSocket 帧
* @param streamId - 流式消息 ID
* @param content - 回复内容
* @param finish - 是否结束流式消息
* @param msgItem - 图文混排项(仅在 finish=true 时有效),用于在结束时附带图片内容
* @param feedback - 反馈信息(仅在首次回复时设置)
* @returns Promise<WsFrame> 正常发送时返回回执帧,跳过时返回 'skipped'
*/
replyStreamNonBlocking(frame, streamId, content, finish = false, msgItem, feedback) {
// finish=true 的最终帧必须发送,不做跳过判断
if (!finish && this.hasPendingReplyAck(frame)) {
return Promise.resolve('skipped');
}
return this.replyStream(frame, streamId, content, finish, msgItem, feedback);
}
/**
* 获取当前连接状态

@@ -1342,0 +1393,0 @@ */

+54
-2

@@ -84,3 +84,5 @@ import { EventEmitter } from 'eventemitter3';

/** 文件消息 */
File = "file"
File = "file",
/** 视频消息 */
Video = "video"
}

@@ -116,2 +118,9 @@ /** 消息发送者信息 */

}
/** 视频结构体 */
interface VideoContent {
/** 视频的下载 url(五分钟内有效,已加密) */
url: string;
/** 解密密钥,长连接模式下返回,每个下载链接的 aeskey 唯一 */
aeskey?: string;
}
/** 图文混排子项 */

@@ -199,2 +208,8 @@ interface MixedMsgItem {

}
/** 视频消息 */
interface VideoMessage extends BaseMessage {
msgtype: MessageType.Video;
/** 视频内容 */
video: VideoContent;
}
/** 回复消息选项 */

@@ -768,2 +783,4 @@ interface ReplyOptions {

'message.file': (data: WsFrame<FileMessage>) => void;
/** 收到视频消息,body 为 VideoMessage */
'message.video': (data: WsFrame<VideoMessage>) => void;
/** 收到事件回调(所有事件类型),body 为 EventMessage */

@@ -988,2 +1005,28 @@ event: (data: WsFrame<EventMessage>) => void;

/**
* 检查指定消息帧是否有未完成的 ack(即上一条消息还未收到回执)
*
* 用于流式场景:调用方可据此决定是否跳过当前中间帧,避免排队积压。
*
* @param frame - 收到的原始 WebSocket 帧
* @returns true 表示有消息正在等待 ack
*/
hasPendingReplyAck(frame: WsFrameHeaders): boolean;
/**
* 非阻塞流式文本回复
*
* 如果上一条同 reqId 的消息尚未收到 ack,则跳过本次发送(返回 'skipped'),
* 避免流式中间帧排队积压导致延迟。
*
* 注意:finish=true 的最终帧不受此限制,始终保证发送(走正常队列)。
*
* @param frame - 收到的原始 WebSocket 帧
* @param streamId - 流式消息 ID
* @param content - 回复内容
* @param finish - 是否结束流式消息
* @param msgItem - 图文混排项(仅在 finish=true 时有效),用于在结束时附带图片内容
* @param feedback - 反馈信息(仅在首次回复时设置)
* @returns Promise<WsFrame> 正常发送时返回回执帧,跳过时返回 'skipped'
*/
replyStreamNonBlocking(frame: WsFrameHeaders, streamId: string, content: string, finish?: boolean, msgItem?: ReplyMsgItem[], feedback?: ReplyFeedback): Promise<WsFrame | 'skipped'>;
/**
* 获取当前连接状态

@@ -1144,2 +1187,11 @@ */

/**
* 检查指定 reqId 是否有待回执的消息(即上一条消息还未收到 ack)
*
* 用于流式场景:调用方可据此决定是否跳过当前帧,避免排队积压。
*
* @param reqId - 要检查的 req_id
* @returns true 表示有消息正在等待 ack
*/
hasPendingAck(reqId: string): boolean;
/**
* 获取当前连接状态

@@ -1231,2 +1283,2 @@ */

export { DefaultLogger, EventType, MessageHandler, MessageType, TemplateCardType, WSAuthFailureError, WSClient, WSReconnectExhaustedError, WeComApiClient, WsCmd, WsConnectionManager, decryptFile, AiBot as default, generateRandomString, generateReqId };
export type { BaseMessage, EnterChatEvent, EventContent, EventFrom, EventMessage, EventMessageWith, FeedbackEventData, FileContent, FileMessage, ImageContent, ImageMessage, Logger, MessageFrom, MixedContent, MixedMessage, MixedMsgItem, QuoteContent, ReplyFeedback, ReplyMsgItem, ReplyOptions, SendMarkdownMsgBody, SendMarkdownParams, SendMediaMsgBody, SendMsgBody, SendTemplateCardMsgBody, SendTextParams, StreamReplyBody, StreamWithTemplateCardReplyBody, TemplateCard, TemplateCardAction, TemplateCardActionMenu, TemplateCardButton, TemplateCardCheckbox, TemplateCardEmphasisContent, TemplateCardEventData, TemplateCardHorizontalContent, TemplateCardImage, TemplateCardImageTextArea, TemplateCardJumpAction, TemplateCardMainTitle, TemplateCardQuoteArea, TemplateCardReplyBody, TemplateCardSelectionItem, TemplateCardSource, TemplateCardSubmitButton, TemplateCardVerticalContent, TextContent, TextMessage, UpdateTemplateCardBody, UploadMediaChunkBody, UploadMediaFinishBody, UploadMediaFinishResult, UploadMediaInitBody, UploadMediaInitResult, UploadMediaOptions, VoiceContent, VoiceMessage, WSClientEventMap, WSClientOptions, WeComMediaType, WelcomeReplyBody, WelcomeTemplateCardReplyBody, WelcomeTextReplyBody, WsFrame, WsFrameHeaders };
export type { BaseMessage, EnterChatEvent, EventContent, EventFrom, EventMessage, EventMessageWith, FeedbackEventData, FileContent, FileMessage, ImageContent, ImageMessage, Logger, MessageFrom, MixedContent, MixedMessage, MixedMsgItem, QuoteContent, ReplyFeedback, ReplyMsgItem, ReplyOptions, SendMarkdownMsgBody, SendMarkdownParams, SendMediaMsgBody, SendMsgBody, SendTemplateCardMsgBody, SendTextParams, StreamReplyBody, StreamWithTemplateCardReplyBody, TemplateCard, TemplateCardAction, TemplateCardActionMenu, TemplateCardButton, TemplateCardCheckbox, TemplateCardEmphasisContent, TemplateCardEventData, TemplateCardHorizontalContent, TemplateCardImage, TemplateCardImageTextArea, TemplateCardJumpAction, TemplateCardMainTitle, TemplateCardQuoteArea, TemplateCardReplyBody, TemplateCardSelectionItem, TemplateCardSource, TemplateCardSubmitButton, TemplateCardVerticalContent, TextContent, TextMessage, UpdateTemplateCardBody, UploadMediaChunkBody, UploadMediaFinishBody, UploadMediaFinishResult, UploadMediaInitBody, UploadMediaInitResult, UploadMediaOptions, VideoContent, VideoMessage, VoiceContent, VoiceMessage, WSClientEventMap, WSClientOptions, WeComMediaType, WelcomeReplyBody, WelcomeTemplateCardReplyBody, WelcomeTextReplyBody, WsFrame, WsFrameHeaders };

@@ -53,2 +53,4 @@ import { EventEmitter } from 'eventemitter3';

MessageType["File"] = "file";
/** 视频消息 */
MessageType["Video"] = "video";
})(MessageType || (MessageType = {}));

@@ -718,2 +720,13 @@

/**
* 检查指定 reqId 是否有待回执的消息(即上一条消息还未收到 ack)
*
* 用于流式场景:调用方可据此决定是否跳过当前帧,避免排队积压。
*
* @param reqId - 要检查的 req_id
* @returns true 表示有消息正在等待 ack
*/
hasPendingAck(reqId) {
return this.pendingAcks.has(reqId);
}
/**
* 获取当前连接状态

@@ -787,2 +800,5 @@ */

break;
case MessageType.Video:
emitter.emit('message.video', frame);
break;
default:

@@ -1336,2 +1352,37 @@ this.logger.debug(`Received unhandled message type: ${body.msgtype}`);

/**
* 检查指定消息帧是否有未完成的 ack(即上一条消息还未收到回执)
*
* 用于流式场景:调用方可据此决定是否跳过当前中间帧,避免排队积压。
*
* @param frame - 收到的原始 WebSocket 帧
* @returns true 表示有消息正在等待 ack
*/
hasPendingReplyAck(frame) {
const reqId = frame.headers?.req_id || '';
return this.wsManager.hasPendingAck(reqId);
}
/**
* 非阻塞流式文本回复
*
* 如果上一条同 reqId 的消息尚未收到 ack,则跳过本次发送(返回 'skipped'),
* 避免流式中间帧排队积压导致延迟。
*
* 注意:finish=true 的最终帧不受此限制,始终保证发送(走正常队列)。
*
* @param frame - 收到的原始 WebSocket 帧
* @param streamId - 流式消息 ID
* @param content - 回复内容
* @param finish - 是否结束流式消息
* @param msgItem - 图文混排项(仅在 finish=true 时有效),用于在结束时附带图片内容
* @param feedback - 反馈信息(仅在首次回复时设置)
* @returns Promise<WsFrame> 正常发送时返回回执帧,跳过时返回 'skipped'
*/
replyStreamNonBlocking(frame, streamId, content, finish = false, msgItem, feedback) {
// finish=true 的最终帧必须发送,不做跳过判断
if (!finish && this.hasPendingReplyAck(frame)) {
return Promise.resolve('skipped');
}
return this.replyStream(frame, streamId, content, finish, msgItem, feedback);
}
/**
* 获取当前连接状态

@@ -1338,0 +1389,0 @@ */

+3
-1
/**
* 事件相关类型定义
*/
import type { BaseMessage, TextMessage, ImageMessage, MixedMessage, VoiceMessage, FileMessage } from './message';
import type { BaseMessage, TextMessage, ImageMessage, MixedMessage, VoiceMessage, FileMessage, VideoMessage } from './message';
import type { WsFrame } from './api';

@@ -87,2 +87,4 @@ /** 事件类型枚举 */

'message.file': (data: WsFrame<FileMessage>) => void;
/** 收到视频消息,body 为 VideoMessage */
'message.video': (data: WsFrame<VideoMessage>) => void;
/** 收到事件回调(所有事件类型),body 为 EventMessage */

@@ -89,0 +91,0 @@ event: (data: WsFrame<EventMessage>) => void;

@@ -7,5 +7,5 @@ /**

export type { WSClientOptions } from './config';
export { MessageType, type BaseMessage, type TextMessage, type ImageMessage, type MixedMessage, type VoiceMessage, type FileMessage, type MessageFrom, type TextContent, type ImageContent, type MixedContent, type MixedMsgItem, type VoiceContent, type FileContent, type QuoteContent, type ReplyOptions, type SendTextParams, type SendMarkdownParams, } from './message';
export { MessageType, type BaseMessage, type TextMessage, type ImageMessage, type MixedMessage, type VoiceMessage, type FileMessage, type VideoMessage, type MessageFrom, type TextContent, type ImageContent, type MixedContent, type MixedMsgItem, type VoiceContent, type VideoContent, type FileContent, type QuoteContent, type ReplyOptions, type SendTextParams, type SendMarkdownParams, } from './message';
export { WsCmd, TemplateCardType } from './api';
export type { WsFrame, WsFrameHeaders, StreamReplyBody, ReplyMsgItem, ReplyFeedback, WelcomeTextReplyBody, WelcomeTemplateCardReplyBody, WelcomeReplyBody, TemplateCardMainTitle, TemplateCardButton, TemplateCardSource, TemplateCardActionMenu, TemplateCardEmphasisContent, TemplateCardQuoteArea, TemplateCardHorizontalContent, TemplateCardJumpAction, TemplateCardAction, TemplateCardVerticalContent, TemplateCardImage, TemplateCardImageTextArea, TemplateCardSubmitButton, TemplateCardSelectionItem, TemplateCardCheckbox, TemplateCard, TemplateCardReplyBody, StreamWithTemplateCardReplyBody, UpdateTemplateCardBody, SendMarkdownMsgBody, SendTemplateCardMsgBody, SendMsgBody, SendMediaMsgBody, WeComMediaType, UploadMediaOptions, UploadMediaFinishResult, UploadMediaInitBody, UploadMediaInitResult, UploadMediaChunkBody, UploadMediaFinishBody, } from './api';
export { EventType, type EventFrom, type EnterChatEvent, type TemplateCardEventData, type FeedbackEventData, type DisconnectedEventData, type EventContent, type EventMessage, type EventMessageWith, type WSClientEventMap, } from './event';

@@ -16,3 +16,5 @@ /**

/** 文件消息 */
File = "file"
File = "file",
/** 视频消息 */
Video = "video"
}

@@ -48,2 +50,9 @@ /** 消息发送者信息 */

}
/** 视频结构体 */
export interface VideoContent {
/** 视频的下载 url(五分钟内有效,已加密) */
url: string;
/** 解密密钥,长连接模式下返回,每个下载链接的 aeskey 唯一 */
aeskey?: string;
}
/** 图文混排子项 */

@@ -131,2 +140,8 @@ export interface MixedMsgItem {

}
/** 视频消息 */
export interface VideoMessage extends BaseMessage {
msgtype: MessageType.Video;
/** 视频内容 */
video: VideoContent;
}
/** 回复消息选项 */

@@ -133,0 +148,0 @@ export interface ReplyOptions {

@@ -149,2 +149,11 @@ import { type ClientOptions as WsClientOptions } from 'ws';

/**
* 检查指定 reqId 是否有待回执的消息(即上一条消息还未收到 ack)
*
* 用于流式场景:调用方可据此决定是否跳过当前帧,避免排队积压。
*
* @param reqId - 要检查的 req_id
* @returns true 表示有消息正在等待 ack
*/
hasPendingAck(reqId: string): boolean;
/**
* 获取当前连接状态

@@ -151,0 +160,0 @@ */

{
"name": "@wecom/aibot-node-sdk",
"version": "1.0.4",
"version": "1.0.5-beta.0",
"description": "企业微信智能机器人 Node.js SDK - WebSocket 长连接通道",

@@ -5,0 +5,0 @@ "main": "dist/index.cjs.js",

+90
-88

@@ -98,24 +98,24 @@ # @wecom/aibot-node-sdk

| 方法 | 说明 | 返回值 |
| --- | --- | --- |
| `connect()` | 建立 WebSocket 连接,连接后自动认证 | `this`(支持链式调用) |
| `disconnect()` | 主动断开连接 | `void` |
| `reply(frame, body, cmd?)` | 通过 WebSocket 通道发送回复消息(通用方法) | `Promise<WsFrame>` |
| `replyStream(frame, streamId, content, finish?, msgItem?, feedback?)` | 发送流式文本回复(支持 Markdown) | `Promise<WsFrame>` |
| `replyWelcome(frame, body)` | 发送欢迎语回复(文本或模板卡片),需 5s 内调用 | `Promise<WsFrame>` |
| `replyTemplateCard(frame, templateCard, feedback?)` | 回复模板卡片消息 | `Promise<WsFrame>` |
| `replyStreamWithCard(frame, streamId, content, finish?, options?)` | 流式消息 + 模板卡片组合回复 | `Promise<WsFrame>` |
| `updateTemplateCard(frame, templateCard, userids?)` | 更新模板卡片(响应 template_card_event),需 5s 内调用 | `Promise<WsFrame>` |
| `sendMessage(chatid, body)` | 主动发送消息(Markdown / 模板卡片 / 媒体),无需回调帧 | `Promise<WsFrame>` |
| `uploadMedia(fileBuffer, options)` | 上传临时素材(三步分片上传),返回 `media_id` | `Promise<UploadMediaFinishResult>` |
| `replyMedia(frame, mediaType, mediaId, videoOptions?)` | 被动回复媒体消息(file/image/voice/video) | `Promise<WsFrame>` |
| `sendMediaMessage(chatid, mediaType, mediaId, videoOptions?)` | 主动发送媒体消息 | `Promise<WsFrame>` |
| `downloadFile(url, aesKey)` | 下载文件并 AES 解密,返回 Buffer 及文件名 | `Promise<{ buffer: Buffer; filename?: string }>` |
| 方法 | 说明 | 返回值 |
| --------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------ |
| `connect()` | 建立 WebSocket 连接,连接后自动认证 | `this`(支持链式调用) |
| `disconnect()` | 主动断开连接 | `void` |
| `reply(frame, body, cmd?)` | 通过 WebSocket 通道发送回复消息(通用方法) | `Promise<WsFrame>` |
| `replyStream(frame, streamId, content, finish?, msgItem?, feedback?)` | 发送流式文本回复(支持 Markdown) | `Promise<WsFrame>` |
| `replyWelcome(frame, body)` | 发送欢迎语回复(文本或模板卡片),需 5s 内调用 | `Promise<WsFrame>` |
| `replyTemplateCard(frame, templateCard, feedback?)` | 回复模板卡片消息 | `Promise<WsFrame>` |
| `replyStreamWithCard(frame, streamId, content, finish?, options?)` | 流式消息 + 模板卡片组合回复 | `Promise<WsFrame>` |
| `updateTemplateCard(frame, templateCard, userids?)` | 更新模板卡片(响应 template_card_event),需 5s 内调用 | `Promise<WsFrame>` |
| `sendMessage(chatid, body)` | 主动发送消息(Markdown / 模板卡片 / 媒体),无需回调帧 | `Promise<WsFrame>` |
| `uploadMedia(fileBuffer, options)` | 上传临时素材(三步分片上传),返回 `media_id` | `Promise<UploadMediaFinishResult>` |
| `replyMedia(frame, mediaType, mediaId, videoOptions?)` | 被动回复媒体消息(file/image/voice/video) | `Promise<WsFrame>` |
| `sendMediaMessage(chatid, mediaType, mediaId, videoOptions?)` | 主动发送媒体消息 | `Promise<WsFrame>` |
| `downloadFile(url, aesKey)` | 下载文件并 AES 解密,返回 Buffer 及文件名 | `Promise<{ buffer: Buffer; filename?: string }>` |
#### 属性
| 属性 | 说明 | 类型 |
| --- | --- | --- |
| `isConnected` | 当前 WebSocket 连接状态 | `boolean` |
| `api` | 内部 API 客户端实例(高级用途) | `WeComApiClient` |
| 属性 | 说明 | 类型 |
| ------------- | ------------------------------- | ---------------- |
| `isConnected` | 当前 WebSocket 连接状态 | `boolean` |
| `api` | 内部 API 客户端实例(高级用途) | `WeComApiClient` |

@@ -357,12 +357,12 @@ ---

| 参数 | 类型 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| `botId` | `string` | ✅ | — | 机器人 ID(企业微信后台获取) |
| `secret` | `string` | ✅ | — | 机器人 Secret(企业微信后台获取) |
| `reconnectInterval` | `number` | — | `1000` | 重连基础延迟(毫秒),实际延迟按指数退避递增(1s → 2s → 4s → ... → 30s 上限) |
| `maxReconnectAttempts` | `number` | — | `10` | 最大重连次数(`-1` 表示无限重连) |
| `heartbeatInterval` | `number` | — | `30000` | 心跳间隔(毫秒) |
| `requestTimeout` | `number` | — | `10000` | HTTP 请求超时时间(毫秒) |
| `wsUrl` | `string` | — | `wss://openws.work.weixin.qq.com` | 自定义 WebSocket 连接地址 |
| `logger` | `Logger` | — | `DefaultLogger` | 自定义日志实例 |
| 参数 | 类型 | 必填 | 默认值 | 说明 |
| ---------------------- | -------- | ---- | --------------------------------- | ----------------------------------------------------------------------------- |
| `botId` | `string` | ✅ | — | 机器人 ID(企业微信后台获取) |
| `secret` | `string` | ✅ | — | 机器人 Secret(企业微信后台获取) |
| `reconnectInterval` | `number` | — | `1000` | 重连基础延迟(毫秒),实际延迟按指数退避递增(1s → 2s → 4s → ... → 30s 上限) |
| `maxReconnectAttempts` | `number` | — | `10` | 最大重连次数(`-1` 表示无限重连) |
| `heartbeatInterval` | `number` | — | `30000` | 心跳间隔(毫秒) |
| `requestTimeout` | `number` | — | `10000` | HTTP 请求超时时间(毫秒) |
| `wsUrl` | `string` | — | `wss://openws.work.weixin.qq.com` | 自定义 WebSocket 连接地址 |
| `logger` | `Logger` | — | `DefaultLogger` | 自定义日志实例 |

@@ -375,19 +375,20 @@ ---

| 事件 | 回调参数 | 说明 |
| --- | --- | --- |
| `connected` | — | WebSocket 连接建立 |
| `authenticated` | — | 认证成功 |
| `disconnected` | `reason: string` | 连接断开 |
| `reconnecting` | `attempt: number` | 正在重连(第 N 次) |
| `error` | `error: Error` | 发生错误 |
| `message` | `frame: WsFrame<BaseMessage>` | 收到消息(所有类型) |
| `message.text` | `frame: WsFrame<TextMessage>` | 收到文本消息 |
| `message.image` | `frame: WsFrame<ImageMessage>` | 收到图片消息 |
| `message.mixed` | `frame: WsFrame<MixedMessage>` | 收到图文混排消息 |
| `message.voice` | `frame: WsFrame<VoiceMessage>` | 收到语音消息 |
| `message.file` | `frame: WsFrame<FileMessage>` | 收到文件消息 |
| `event` | `frame: WsFrame<EventMessage>` | 收到事件回调(所有事件类型) |
| `event.enter_chat` | `frame: WsFrame<EventMessage>` | 收到进入会话事件(用户当天首次进入单聊会话) |
| `event.template_card_event` | `frame: WsFrame<EventMessage>` | 收到模板卡片事件(用户点击卡片按钮) |
| `event.feedback_event` | `frame: WsFrame<EventMessage>` | 收到用户反馈事件 |
| 事件 | 回调参数 | 说明 |
| --------------------------- | ------------------------------ | -------------------------------------------- |
| `connected` | — | WebSocket 连接建立 |
| `authenticated` | — | 认证成功 |
| `disconnected` | `reason: string` | 连接断开 |
| `reconnecting` | `attempt: number` | 正在重连(第 N 次) |
| `error` | `error: Error` | 发生错误 |
| `message` | `frame: WsFrame<BaseMessage>` | 收到消息(所有类型) |
| `message.text` | `frame: WsFrame<TextMessage>` | 收到文本消息 |
| `message.image` | `frame: WsFrame<ImageMessage>` | 收到图片消息 |
| `message.mixed` | `frame: WsFrame<MixedMessage>` | 收到图文混排消息 |
| `message.voice` | `frame: WsFrame<VoiceMessage>` | 收到语音消息 |
| `message.file` | `frame: WsFrame<FileMessage>` | 收到文件消息 |
| `message.video` | `frame: WsFrame<VideoMessage>` | 收到视频消息 |
| `event` | `frame: WsFrame<EventMessage>` | 收到事件回调(所有事件类型) |
| `event.enter_chat` | `frame: WsFrame<EventMessage>` | 收到进入会话事件(用户当天首次进入单聊会话) |
| `event.template_card_event` | `frame: WsFrame<EventMessage>` | 收到模板卡片事件(用户点击卡片按钮) |
| `event.feedback_event` | `frame: WsFrame<EventMessage>` | 收到用户反馈事件 |

@@ -400,26 +401,27 @@ ---

| 类型 | 值 | 说明 |
| --- | --- | --- |
| `Text` | `'text'` | 文本消息 |
| 类型 | 值 | 说明 |
| ------- | --------- | -------------------------------------------------------- |
| `Text` | `'text'` | 文本消息 |
| `Image` | `'image'` | 图片消息(URL 已加密,使用消息中的 `image.aeskey` 解密) |
| `Mixed` | `'mixed'` | 图文混排消息(包含 text / image 子项) |
| `Voice` | `'voice'` | 语音消息(已转文本) |
| `File` | `'file'` | 文件消息(URL 已加密,使用消息中的 `file.aeskey` 解密) |
| `Mixed` | `'mixed'` | 图文混排消息(包含 text / image 子项) |
| `Voice` | `'voice'` | 语音消息(已转文本) |
| `File` | `'file'` | 文件消息(URL 已加密,使用消息中的 `file.aeskey` 解密) |
| `Video` | `'video'` | 视频消息(URL 已加密,使用消息中的 `video.aeskey` 解密) |
SDK 支持以下事件类型(`EventType` 枚举):
| 类型 | 值 | 说明 |
| --- | --- | --- |
| `EnterChat` | `'enter_chat'` | 进入会话事件:用户当天首次进入机器人单聊会话 |
| `TemplateCardEvent` | `'template_card_event'` | 模板卡片事件:用户点击模板卡片按钮 |
| `FeedbackEvent` | `'feedback_event'` | 用户反馈事件:用户对机器人回复进行反馈 |
| 类型 | 值 | 说明 |
| ------------------- | ----------------------- | -------------------------------------------- |
| `EnterChat` | `'enter_chat'` | 进入会话事件:用户当天首次进入机器人单聊会话 |
| `TemplateCardEvent` | `'template_card_event'` | 模板卡片事件:用户点击模板卡片按钮 |
| `FeedbackEvent` | `'feedback_event'` | 用户反馈事件:用户对机器人回复进行反馈 |
SDK 支持以下媒体类型(`WeComMediaType` 类型):
| 类型 | 值 | 说明 |
| --- | --- | --- |
| — | `'file'` | 文件 |
| — | `'image'` | 图片 |
| — | `'voice'` | 语音 |
| — | `'video'` | 视频 |
| 类型 | 值 | 说明 |
| ---- | --------- | ---- |
| — | `'file'` | 文件 |
| — | `'image'` | 图片 |
| — | `'voice'` | 语音 |
| — | `'video'` | 视频 |

@@ -432,8 +434,8 @@ ---

| 类型 | 值 | 说明 |
| --- | --- | --- |
| `TextNotice` | `'text_notice'` | 文本通知模版卡片 |
| `NewsNotice` | `'news_notice'` | 图文展示模版卡片 |
| `ButtonInteraction` | `'button_interaction'` | 按钮交互模版卡片 |
| `VoteInteraction` | `'vote_interaction'` | 投票选择模版卡片 |
| 类型 | 值 | 说明 |
| --------------------- | ------------------------ | ---------------- |
| `TextNotice` | `'text_notice'` | 文本通知模版卡片 |
| `NewsNotice` | `'news_notice'` | 图文展示模版卡片 |
| `ButtonInteraction` | `'button_interaction'` | 按钮交互模版卡片 |
| `VoteInteraction` | `'vote_interaction'` | 投票选择模版卡片 |
| `MultipleInteraction` | `'multiple_interaction'` | 多项选择模版卡片 |

@@ -527,15 +529,15 @@

| 方向 | 常量 | 值 | 说明 |
| --- | --- | --- | --- |
| 开发者 → 企微 | `SUBSCRIBE` | `aibot_subscribe` | 认证订阅 |
| 开发者 → 企微 | `HEARTBEAT` | `ping` | 心跳 |
| 开发者 → 企微 | `RESPONSE` | `aibot_respond_msg` | 回复消息 |
| 开发者 → 企微 | `RESPONSE_WELCOME` | `aibot_respond_welcome_msg` | 回复欢迎语 |
| 开发者 → 企微 | `RESPONSE_UPDATE` | `aibot_respond_update_msg` | 更新模板卡片 |
| 开发者 → 企微 | `SEND_MSG` | `aibot_send_msg` | 主动发送消息 |
| 开发者 → 企微 | `UPLOAD_MEDIA_INIT` | `aibot_upload_media_init` | 上传素材 - 初始化 |
| 开发者 → 企微 | `UPLOAD_MEDIA_CHUNK` | `aibot_upload_media_chunk` | 上传素材 - 分片 |
| 开发者 → 企微 | `UPLOAD_MEDIA_FINISH` | `aibot_upload_media_finish` | 上传素材 - 完成 |
| 企微 → 开发者 | `CALLBACK` | `aibot_msg_callback` | 消息推送回调 |
| 企微 → 开发者 | `EVENT_CALLBACK` | `aibot_event_callback` | 事件推送回调 |
| 方向 | 常量 | 值 | 说明 |
| ------------- | --------------------- | --------------------------- | ----------------- |
| 开发者 → 企微 | `SUBSCRIBE` | `aibot_subscribe` | 认证订阅 |
| 开发者 → 企微 | `HEARTBEAT` | `ping` | 心跳 |
| 开发者 → 企微 | `RESPONSE` | `aibot_respond_msg` | 回复消息 |
| 开发者 → 企微 | `RESPONSE_WELCOME` | `aibot_respond_welcome_msg` | 回复欢迎语 |
| 开发者 → 企微 | `RESPONSE_UPDATE` | `aibot_respond_update_msg` | 更新模板卡片 |
| 开发者 → 企微 | `SEND_MSG` | `aibot_send_msg` | 主动发送消息 |
| 开发者 → 企微 | `UPLOAD_MEDIA_INIT` | `aibot_upload_media_init` | 上传素材 - 初始化 |
| 开发者 → 企微 | `UPLOAD_MEDIA_CHUNK` | `aibot_upload_media_chunk` | 上传素材 - 分片 |
| 开发者 → 企微 | `UPLOAD_MEDIA_FINISH` | `aibot_upload_media_finish` | 上传素材 - 完成 |
| 企微 → 开发者 | `CALLBACK` | `aibot_msg_callback` | 消息推送回调 |
| 企微 → 开发者 | `EVENT_CALLBACK` | `aibot_event_callback` | 事件推送回调 |

@@ -760,8 +762,8 @@ ---

| 类别 | 导出项 |
| --- | --- |
| **类** | `WSClient`、`WeComApiClient`、`WsConnectionManager`、`MessageHandler`、`DefaultLogger` |
| **函数** | `generateReqId`、`generateRandomString`、`decryptFile` |
| **枚举** | `MessageType`、`EventType`、`TemplateCardType`、`WsCmd` |
| **类型** | `WSClientOptions`、`WSClientEventMap`、`WsFrame`、`WsFrameHeaders`、`BaseMessage`、`TextMessage`、`ImageMessage`、`MixedMessage`、`VoiceMessage`、`FileMessage`、`EventMessage`、`TemplateCard`、`StreamReplyBody`、`ReplyMsgItem`、`ReplyFeedback`、`Logger` 等 |
| 类别 | 导出项 |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **类** | `WSClient`、`WeComApiClient`、`WsConnectionManager`、`MessageHandler`、`DefaultLogger` |
| **函数** | `generateReqId`、`generateRandomString`、`decryptFile` |
| **枚举** | `MessageType`、`EventType`、`TemplateCardType`、`WsCmd` |
| **类型** | `WSClientOptions`、`WSClientEventMap`、`WsFrame`、`WsFrameHeaders`、`BaseMessage`、`TextMessage`、`ImageMessage`、`MixedMessage`、`VoiceMessage`、`FileMessage`、`VideoMessage`、`EventMessage`、`TemplateCard`、`StreamReplyBody`、`ReplyMsgItem`、`ReplyFeedback`、`Logger` 等 |

@@ -768,0 +770,0 @@ ---

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display