{"version":3,"file":"index.esm.js","sources":["../src/types/common.ts","../src/types/message.ts","../src/types/api.ts","../src/types/event.ts","../src/api.ts","../src/utils.ts","../src/ws.ts","../src/message-handler.ts","../src/crypto.ts","../src/logger.ts","../src/client.ts","../src/wecom-crypto/index.ts","../src/index.ts"],"sourcesContent":["/**\n * 通用基础类型定义\n */\n\n/** 日志接口 */\nexport interface Logger {\n  debug(message: string, ...args: any[]): void;\n  info(message: string, ...args: any[]): void;\n  warn(message: string, ...args: any[]): void;\n  error(message: string, ...args: any[]): void;\n}\n\n/**\n * 认证失败重试次数用尽错误\n *\n * 当 WebSocket 认证连续失败次数达到 maxAuthFailureAttempts 时抛出。\n * 通常表示 botId/secret 配置错误，重试无法恢复。\n */\nexport class WSAuthFailureError extends Error {\n  readonly code = 'WS_AUTH_FAILURE_EXHAUSTED';\n\n  constructor(maxAttempts: number) {\n    super(`Max auth failure attempts exceeded (${maxAttempts})`);\n    this.name = 'WSAuthFailureError';\n  }\n}\n\n/**\n * 连接断开重连次数用尽错误\n *\n * 当 WebSocket 连接断开后重连次数达到 maxReconnectAttempts 时抛出。\n * 通常表示网络或服务端持续不可用。\n */\nexport class WSReconnectExhaustedError extends Error {\n  readonly code = 'WS_RECONNECT_EXHAUSTED';\n\n  constructor(maxAttempts: number) {\n    super(`Max reconnect attempts exceeded (${maxAttempts})`);\n    this.name = 'WSReconnectExhaustedError';\n  }\n}\n","/**\n * 消息相关类型定义\n * 按照企业微信智能机器人接收消息协议定义\n */\n\n/** 消息类型枚举 */\nexport enum MessageType {\n  /** 文本消息 */\n  Text = 'text',\n  /** 图片消息 */\n  Image = 'image',\n  /** 图文混排消息 */\n  Mixed = 'mixed',\n  /** 语音消息 */\n  Voice = 'voice',\n  /** 文件消息 */\n  File = 'file',\n  /** 视频消息 */\n  Video = 'video'\n}\n\n/** 消息发送者信息 */\nexport interface MessageFrom {\n  /** 操作者的 userid */\n  userid: string;\n}\n\n/** 文本结构体 */\nexport interface TextContent {\n  /** 文本消息内容 */\n  content: string;\n}\n\n/** 图片结构体 */\nexport interface ImageContent {\n  /** 图片的下载 url（五分钟内有效，已加密） */\n  url: string;\n  /** 解密密钥，长连接模式下返回，每个下载链接的 aeskey 唯一 */\n  aeskey?: string;\n}\n\n/** 语音结构体 */\nexport interface VoiceContent {\n  /** 语音转换成文本的内容 */\n  content: string;\n}\n\n/** 文件结构体 */\nexport interface FileContent {\n  /** 文件的下载 url（五分钟内有效，已加密） */\n  url: string;\n  /** 解密密钥，长连接模式下返回，每个下载链接的 aeskey 唯一 */\n  aeskey?: string;\n}\n\n/** 视频结构体 */\nexport interface VideoContent {\n  /** 视频的下载 url（五分钟内有效，已加密） */\n  url: string;\n  /** 解密密钥，长连接模式下返回，每个下载链接的 aeskey 唯一 */\n  aeskey?: string;\n}\n\n/** 图文混排子项 */\nexport interface MixedMsgItem {\n  /** 图文混排中的类型：text / image */\n  msgtype: 'text' | 'image';\n  /** 文本内容（msgtype 为 text 时存在） */\n  text?: TextContent;\n  /** 图片内容（msgtype 为 image 时存在） */\n  image?: ImageContent;\n}\n\n/** 图文混排结构体 */\nexport interface MixedContent {\n  /** 图文混排消息项列表 */\n  msg_item: MixedMsgItem[];\n}\n\n/** 引用结构体 */\nexport interface QuoteContent {\n  /** 引用的类型：text / image / mixed / voice / file */\n  msgtype: 'text' | 'image' | 'mixed' | 'voice' | 'file';\n  /** 引用的文本内容 */\n  text?: TextContent;\n  /** 引用的图片内容 */\n  image?: ImageContent;\n  /** 引用的图文混排内容 */\n  mixed?: MixedContent;\n  /** 引用的语音内容 */\n  voice?: VoiceContent;\n  /** 引用的文件内容 */\n  file?: FileContent;\n}\n\n/** 基础消息结构 */\nexport interface BaseMessage {\n  /** 本次回调的唯一性标志，用于事件排重 */\n  msgid: string;\n  /** 智能机器人 id */\n  aibotid: string;\n  /** 会话 id，仅群聊类型时返回 */\n  chatid?: string;\n  /** 会话类型：single 单聊, group 群聊 */\n  chattype: 'single' | 'group';\n  /** 事件触发者信息 */\n  from: MessageFrom;\n  /** 事件产生的时间戳 */\n  create_time?: number;\n  /** 支持主动回复消息的临时 url */\n  response_url?: string;\n  /** 消息类型 */\n  msgtype: MessageType | string;\n  /** 引用内容（若用户引用了其他消息则有该字段） */\n  quote?: QuoteContent;\n  /** 原始数据 */\n  [key: string]: any;\n}\n\n/** 文本消息 */\nexport interface TextMessage extends BaseMessage {\n  msgtype: MessageType.Text;\n  /** 文本消息内容 */\n  text: TextContent;\n}\n\n/** 图片消息 */\nexport interface ImageMessage extends BaseMessage {\n  msgtype: MessageType.Image;\n  /** 图片内容 */\n  image: ImageContent;\n}\n\n/** 图文混排消息 */\nexport interface MixedMessage extends BaseMessage {\n  msgtype: MessageType.Mixed;\n  /** 图文混排内容 */\n  mixed: MixedContent;\n}\n\n/** 语音消息 */\nexport interface VoiceMessage extends BaseMessage {\n  msgtype: MessageType.Voice;\n  /** 语音内容 */\n  voice: VoiceContent;\n}\n\n/** 文件消息 */\nexport interface FileMessage extends BaseMessage {\n  msgtype: MessageType.File;\n  /** 文件内容 */\n  file: FileContent;\n}\n\n/** 视频消息 */\nexport interface VideoMessage extends BaseMessage {\n  msgtype: MessageType.Video;\n  /** 视频内容 */\n  video: VideoContent;\n}\n\n/** 回复消息选项 */\nexport interface ReplyOptions {\n  /** 回复的消息 ID */\n  msgid: string;\n  /** 聊天 ID */\n  chatid: string;\n}\n\n/** 发送文本消息参数 */\nexport interface SendTextParams extends ReplyOptions {\n  content: string;\n}\n\n/** 发送 Markdown 消息参数 */\nexport interface SendMarkdownParams extends ReplyOptions {\n  content: string;\n}\n","/**\n * API 相关类型定义\n */\n\n/** WebSocket 命令类型常量 */\nexport const WsCmd = {\n  // ========== 开发者 → 企业微信 ==========\n  /** 认证订阅 */\n  SUBSCRIBE: 'aibot_subscribe',\n  /** 心跳 */\n  HEARTBEAT: 'ping',\n  /** 回复消息 */\n  RESPONSE: 'aibot_respond_msg',\n  /** 回复欢迎语 */\n  RESPONSE_WELCOME: 'aibot_respond_welcome_msg',\n  /** 更新模板卡片 */\n  RESPONSE_UPDATE: 'aibot_respond_update_msg',\n  /** 主动发送消息 */\n  SEND_MSG: 'aibot_send_msg',\n  /** 上传临时素材 - 初始化 */\n  UPLOAD_MEDIA_INIT: 'aibot_upload_media_init',\n  /** 上传临时素材 - 分片上传 */\n  UPLOAD_MEDIA_CHUNK: 'aibot_upload_media_chunk',\n  /** 上传临时素材 - 完成上传 */\n  UPLOAD_MEDIA_FINISH: 'aibot_upload_media_finish',\n\n  // ========== 企业微信 → 开发者 ==========\n  /** 消息推送回调 */\n  CALLBACK: 'aibot_msg_callback',\n  /** 事件推送回调 */\n  EVENT_CALLBACK: 'aibot_event_callback',\n} as const;\n\n/**\n * WebSocket 帧结构\n *\n * 发送和接收统一使用 { cmd, headers, body } 格式：\n * - 认证发送：{ cmd: \"aibot_subscribe\", headers: { req_id }, body: { secret, bot_id } }\n * - 消息推送：{ cmd: \"aibot_msg_callback\", headers: { req_id }, body: { msgid, msgtype, ... } }\n * - 事件推送：{ cmd: \"aibot_event_callback\", headers: { req_id }, body: { event_type, ... } }\n * - 回复消息：{ cmd: \"aibot_respond_msg\", headers: { req_id }, body: { msgtype, stream: { ... } } }\n * - 回复欢迎语：{ cmd: \"aibot_respond_welcome_msg\", headers: { req_id }, body: { ... } }\n * - 更新模板卡片：{ cmd: \"aibot_respond_update_msg\", headers: { req_id }, body: { ... } }\n * - 心跳发送：{ cmd: \"ping\", headers: { req_id } }\n * - 认证/心跳响应：{ headers: { req_id }, errcode: 0, errmsg: \"ok\" }\n */\nexport interface WsFrame<T = any> {\n  /** 命令类型；认证/心跳响应时可能为空 */\n  cmd?: string;\n  /** 请求头信息 */\n  headers: {\n    req_id: string;\n    [key: string]: any;\n  };\n  /** 消息体 */\n  body?: T;\n  /** 响应错误码，认证/心跳响应时存在 */\n  errcode?: number;\n  /** 响应错误信息，认证/心跳响应时存在 */\n  errmsg?: string;\n}\n\n/** 仅包含 headers 的 WsFrame 子集，用于 reply / replyStream 等方法的参数类型 */\nexport type WsFrameHeaders = Pick<WsFrame, 'headers'>;\n\n// ========== 回复消息中的通用子结构 ==========\n\n/** 回复消息中的图文混排子项 */\nexport interface ReplyMsgItem {\n  /** 类型：image */\n  msgtype: 'image';\n  /** 图片内容 */\n  image: {\n    /** Base64 编码的图片数据，图片（base64编码前）最大不能超过10M，支持JPG、PNG格式 */\n    base64: string;\n    /** 图片内容（base64编码前）的 MD5 值 */\n    md5: string;\n  };\n}\n\n/** 回复消息中的反馈信息 */\nexport interface ReplyFeedback {\n  /** 反馈 ID，有效长度为 256 字节以内，必须是 utf-8 编码 */\n  id: string;\n}\n\n// ========== 流式回复消息体 ==========\n\n/** 流式回复消息体 */\nexport interface StreamReplyBody {\n  msgtype: 'stream';\n  stream: {\n    /** 流式消息 ID，首次回复时设置，后续使用相同 ID 刷新内容 */\n    id: string;\n    /** 是否结束流式消息 */\n    finish?: boolean;\n    /** 回复内容（支持 Markdown），最长不超过 20480 个字节，必须是 utf8 编码 */\n    content?: string;\n    /** 图文混排消息列表，目前仅当 finish=true 时支持设置，最多 10 个 */\n    msg_item?: ReplyMsgItem[];\n    /** 反馈信息，首次回复时设置 */\n    feedback?: ReplyFeedback;\n  };\n}\n\n// ========== 欢迎语回复消息体 ==========\n\n/** 欢迎语回复消息体（文本类型） */\nexport interface WelcomeTextReplyBody {\n  msgtype: 'text';\n  text: {\n    /** 欢迎语文本内容 */\n    content: string;\n  };\n}\n\n/** 欢迎语回复消息体（模板卡片类型） */\nexport interface WelcomeTemplateCardReplyBody {\n  msgtype: 'template_card';\n  template_card: TemplateCard;\n}\n\n/** 欢迎语回复消息体联合类型 */\nexport type WelcomeReplyBody = WelcomeTextReplyBody | WelcomeTemplateCardReplyBody;\n\n// ========== 模板卡片回复消息体 ==========\n\n/** 模板卡片回复消息体 */\nexport interface TemplateCardReplyBody {\n  /** 消息类型，固定值 template_card */\n  msgtype: 'template_card';\n  /** 模板卡片内容 */\n  template_card: TemplateCard;\n}\n\n// ========== 流式消息 + 模板卡片组合回复消息体 ==========\n\n/** 流式消息 + 模板卡片组合回复消息体 */\nexport interface StreamWithTemplateCardReplyBody {\n  msgtype: 'stream_with_template_card';\n  stream: StreamReplyBody['stream'];\n  template_card?: TemplateCard;\n}\n\n// ========== 更新模板卡片消息体 ==========\n\n/** 更新模板卡片消息体 */\nexport interface UpdateTemplateCardBody {\n  /** 响应类型，固定值 update_template_card */\n  response_type: 'update_template_card';\n  /** 要替换模版卡片消息的 userid 列表。若不填，则表示替换当前消息涉及到的所有用户 */\n  userids?: string[];\n  /** 要替换的模版卡片内容 */\n  template_card: TemplateCard;\n}\n\n// ========== 模板卡片结构体及子结构体 ==========\n\n/** 卡片类型枚举 */\nexport enum TemplateCardType {\n  /** 文本通知模版卡片 */\n  TextNotice = 'text_notice',\n  /** 图文展示模版卡片 */\n  NewsNotice = 'news_notice',\n  /** 按钮交互模版卡片 */\n  ButtonInteraction = 'button_interaction',\n  /** 投票选择模版卡片 */\n  VoteInteraction = 'vote_interaction',\n  /** 多项选择模版卡片 */\n  MultipleInteraction = 'multiple_interaction',\n}\n\n/** 卡片来源样式信息 */\nexport interface TemplateCardSource {\n  /** 来源图片的 url */\n  icon_url?: string;\n  /** 来源图片的描述，建议不超过 13 个字 */\n  desc?: string;\n  /** 来源文字的颜色，0(默认)灰色，1 黑色，2 红色，3 绿色 */\n  desc_color?: 0 | 1 | 2 | 3;\n}\n\n/** 卡片右上角更多操作按钮 */\nexport interface TemplateCardActionMenu {\n  /** 更多操作界面的描述 */\n  desc: string;\n  /** 操作列表，长度取值范围为 [1, 3] */\n  action_list: Array<{\n    /** 操作的描述文案 */\n    text: string;\n    /** 操作 key 值，最长支持 1024 字节，不可重复 */\n    key: string;\n  }>;\n}\n\n/** 模板卡片主标题 */\nexport interface TemplateCardMainTitle {\n  /** 一级标题，建议不超过 26 个字 */\n  title?: string;\n  /** 标题辅助信息，建议不超过 30 个字 */\n  desc?: string;\n}\n\n/** 关键数据样式 */\nexport interface TemplateCardEmphasisContent {\n  /** 关键数据样式的数据内容，建议不超过 10 个字 */\n  title?: string;\n  /** 关键数据样式的数据描述内容，建议不超过 15 个字 */\n  desc?: string;\n}\n\n/** 引用文献样式 */\nexport interface TemplateCardQuoteArea {\n  /** 引用文献样式区域点击事件，0 或不填代表没有点击事件，1 代表跳转 url，2 代表跳转小程序 */\n  type?: 0 | 1 | 2;\n  /** 点击跳转的 url，type 是 1 时必填 */\n  url?: string;\n  /** 点击跳转的小程序的 appid，type 是 2 时必填 */\n  appid?: string;\n  /** 点击跳转的小程序的 pagepath，type 是 2 时选填 */\n  pagepath?: string;\n  /** 引用文献样式的标题 */\n  title?: string;\n  /** 引用文献样式的引用文案 */\n  quote_text?: string;\n}\n\n/** 二级标题+文本列表 */\nexport interface TemplateCardHorizontalContent {\n  /** 链接类型，0 或不填代表普通文本，1 代表跳转 url，3 代表点击跳转成员详情 */\n  type?: 0 | 1 | 3;\n  /** 二级标题，建议不超过 5 个字 */\n  keyname: string;\n  /** 二级文本，建议不超过 26 个字 */\n  value?: string;\n  /** 链接跳转的 url，type 是 1 时必填 */\n  url?: string;\n  /** 成员详情的 userid，type 是 3 时必填 */\n  userid?: string;\n}\n\n/** 跳转指引样式 */\nexport interface TemplateCardJumpAction {\n  /** 跳转链接类型，0 或不填代表不是链接，1 代表跳转 url，2 代表跳转小程序，3 代表触发消息智能回复 */\n  type?: 0 | 1 | 2 | 3;\n  /** 跳转链接样式的文案内容，建议不超过 13 个字 */\n  title: string;\n  /** 跳转链接的 url，type 是 1 时必填 */\n  url?: string;\n  /** 跳转链接的小程序的 appid，type 是 2 时必填 */\n  appid?: string;\n  /** 跳转链接的小程序的 pagepath，type 是 2 时选填 */\n  pagepath?: string;\n  /** 智能问答问题，最长不超过 200 个字节，type 为 3 时必填 */\n  question?: string;\n}\n\n/** 整体卡片的点击跳转事件 */\nexport interface TemplateCardAction {\n  /** 卡片跳转类型，0 或不填代表不是链接，1 代表跳转 url，2 代表打开小程序 */\n  type: 0 | 1 | 2;\n  /** 跳转事件的 url，type 是 1 时必填 */\n  url?: string;\n  /** 跳转事件的小程序的 appid，type 是 2 时必填 */\n  appid?: string;\n  /** 跳转事件的小程序的 pagepath，type 是 2 时选填 */\n  pagepath?: string;\n}\n\n/** 卡片二级垂直内容 */\nexport interface TemplateCardVerticalContent {\n  /** 卡片二级标题，建议不超过 26 个字 */\n  title: string;\n  /** 二级普通文本，建议不超过 112 个字 */\n  desc?: string;\n}\n\n/** 图片样式 */\nexport interface TemplateCardImage {\n  /** 图片的 url */\n  url: string;\n  /** 图片的宽高比，宽高比要小于 2.25，大于 1.3，不填默认 1.3 */\n  aspect_ratio?: number;\n}\n\n/** 左图右文样式 */\nexport interface TemplateCardImageTextArea {\n  /** 左图右文样式区域点击事件，0 或不填代表没有点击事件，1 代表跳转 url，2 代表跳转小程序 */\n  type?: 0 | 1 | 2;\n  /** 点击跳转的 url，type 是 1 时必填 */\n  url?: string;\n  /** 点击跳转的小程序的 appid，type 是 2 时必填 */\n  appid?: string;\n  /** 点击跳转的小程序的 pagepath，type 是 2 时选填 */\n  pagepath?: string;\n  /** 左图右文样式的标题 */\n  title?: string;\n  /** 左图右文样式的描述 */\n  desc?: string;\n  /** 左图右文样式的图片 url */\n  image_url: string;\n}\n\n/** 提交按钮样式 */\nexport interface TemplateCardSubmitButton {\n  /** 按钮文案，建议不超过 10 个字 */\n  text: string;\n  /** 提交按钮的 key，最长支持 1024 字节 */\n  key: string;\n}\n\n/** 下拉式选择器 */\nexport interface TemplateCardSelectionItem {\n  /** 下拉式选择器题目的 key，最长支持 1024 字节，不可重复 */\n  question_key: string;\n  /** 选择器的标题，建议不超过 13 个字 */\n  title?: string;\n  /** 是否不可选，false 为可选，true 为不可选（仅更新模版卡片时有效） */\n  disable?: boolean;\n  /** 默认选定的 id，不填或错填默认第一个 */\n  selected_id?: string;\n  /** 选项列表，不超过 10 个，最少 1 个 */\n  option_list: Array<{\n    /** 选项 id，最长支持 128 字节，不可重复 */\n    id: string;\n    /** 选项文案，建议不超过 10 个字 */\n    text: string;\n  }>;\n}\n\n/** 模板卡片按钮 */\nexport interface TemplateCardButton {\n  /** 按钮文案，建议不超过 10 个字 */\n  text: string;\n  /** 按钮样式，1~4，不填或错填默认 1 */\n  style?: number;\n  /** 按钮 key 值，最长支持 1024 字节，不可重复 */\n  key: string;\n}\n\n/** 选择题样式（投票选择） */\nexport interface TemplateCardCheckbox {\n  /** 选择题 key 值，最长支持 1024 字节 */\n  question_key: string;\n  /** 是否不可选，false 为可选，true 为不可选（仅更新模版卡片时有效） */\n  disable?: boolean;\n  /** 选择题模式，单选：0，多选：1，不填默认 0 */\n  mode?: 0 | 1;\n  /** 选项列表，不超过 20 个，最少 1 个 */\n  option_list: Array<{\n    /** 选项 id，最长支持 128 字节，不可重复 */\n    id: string;\n    /** 选项文案描述，建议不超过 11 个字 */\n    text: string;\n    /** 该选项是否默认选中 */\n    is_checked?: boolean;\n  }>;\n}\n\n/** 模板卡片结构（通用类型，包含所有可能的字段） */\nexport interface TemplateCard {\n  /** 卡片类型 */\n  card_type: string;\n  /** 卡片来源样式信息 */\n  source?: TemplateCardSource;\n  /** 卡片右上角更多操作按钮 */\n  action_menu?: TemplateCardActionMenu;\n  /** 模版卡片的主要内容 */\n  main_title?: TemplateCardMainTitle;\n  /** 关键数据样式，建议不与引用样式共用 */\n  emphasis_content?: TemplateCardEmphasisContent;\n  /** 引用文献样式，建议不与关键数据共用 */\n  quote_area?: TemplateCardQuoteArea;\n  /** 二级普通文本，建议不超过 112 个字 */\n  sub_title_text?: string;\n  /** 二级标题+文本列表，列表长度不超过 6 */\n  horizontal_content_list?: TemplateCardHorizontalContent[];\n  /** 跳转指引样式的列表，列表长度不超过 3 */\n  jump_list?: TemplateCardJumpAction[];\n  /** 整体卡片的点击跳转事件 */\n  card_action?: TemplateCardAction;\n  /** 图片样式（news_notice 类型卡片使用） */\n  card_image?: TemplateCardImage;\n  /** 左图右文样式（news_notice 类型卡片使用） */\n  image_text_area?: TemplateCardImageTextArea;\n  /** 卡片二级垂直内容，列表长度不超过 4（news_notice 类型卡片使用） */\n  vertical_content_list?: TemplateCardVerticalContent[];\n  /** 下拉式的选择器（button_interaction 类型卡片使用） */\n  button_selection?: TemplateCardSelectionItem;\n  /** 按钮列表，列表长度不超过 6（button_interaction 类型卡片使用） */\n  button_list?: TemplateCardButton[];\n  /** 选择题样式（vote_interaction 类型卡片使用） */\n  checkbox?: TemplateCardCheckbox;\n  /** 下拉式选择器列表，最多支持 3 个（multiple_interaction 类型卡片使用） */\n  select_list?: TemplateCardSelectionItem[];\n  /** 提交按钮样式（vote_interaction / multiple_interaction 类型卡片使用） */\n  submit_button?: TemplateCardSubmitButton;\n  /** 任务 ID，同一个机器人不能重复，只能由数字、字母和\"_-@\"组成，最长 128 字节 */\n  task_id?: string;\n  /** 反馈信息 */\n  feedback?: ReplyFeedback;\n}\n\n/** 模板卡片回复消息体 */\nexport interface TemplateCardReplyBody {\n  /** 消息类型，固定值 template_card */\n  msgtype: 'template_card';\n  /** 模板卡片内容 */\n  template_card: TemplateCard;\n}\n\n// ========== 主动发送消息体 ==========\n\n/** 主动发送 Markdown 消息体 */\nexport interface SendMarkdownMsgBody {\n  /** 消息类型，固定值 markdown */\n  msgtype: 'markdown';\n  /** markdown 消息内容 */\n  markdown: {\n    /** markdown 文本内容 */\n    content: string;\n  };\n}\n\n/** 主动发送模板卡片消息体 */\nexport interface SendTemplateCardMsgBody {\n  /** 消息类型，固定值 template_card */\n  msgtype: 'template_card';\n  /** 模板卡片内容 */\n  template_card: TemplateCard;\n}\n\n/** 主动发送消息体联合类型 */\nexport type SendMsgBody = SendMarkdownMsgBody | SendTemplateCardMsgBody | SendMediaMsgBody;\n\n/** 更新模板卡片消息体 */\nexport interface UpdateTemplateCardBody {\n  /** 响应类型，固定值 update_template_card */\n  response_type: 'update_template_card';\n  /** 要替换模版卡片消息的 userid 列表。若不填，则表示替换当前消息涉及到的所有用户 */\n  userids?: string[];\n  /** 要替换的模版卡片内容 */\n  template_card: TemplateCard;\n}\n\n// ========== 媒体消息类型 ==========\n\n/** 企业微信媒体类型 */\nexport type WeComMediaType = 'file' | 'image' | 'voice' | 'video';\n\n/** 媒体消息发送体（主动发送 + 被动回复共用） */\nexport interface SendMediaMsgBody {\n  /** 消息类型 */\n  msgtype: WeComMediaType;\n  /** 文件消息 */\n  file?: { media_id: string };\n  /** 图片消息 */\n  image?: { media_id: string };\n  /** 语音消息 */\n  voice?: { media_id: string };\n  /** 视频消息 */\n  video?: {\n    media_id: string;\n    /** 视频消息的标题，不超过128个字节，超过会自动截断 */\n    title?: string;\n    /** 视频消息的描述，不超过512个字节，超过会自动截断 */\n    description?: string;\n  };\n}\n\n// ========== 上传临时素材相关类型 ==========\n\n/** 上传素材初始化请求 body */\nexport interface UploadMediaInitBody {\n  /** 素材类型 */\n  type: WeComMediaType;\n  /** 文件名 */\n  filename: string;\n  /** 文件总大小（字节） */\n  total_size: number;\n  /** 分片总数 */\n  total_chunks: number;\n  /** 文件 MD5 值（可选） */\n  md5?: string;\n}\n\n/** 上传素材初始化响应 body */\nexport interface UploadMediaInitResult {\n  /** 上传会话 ID */\n  upload_id: string;\n}\n\n/** 上传素材分片请求 body */\nexport interface UploadMediaChunkBody {\n  /** 上传会话 ID */\n  upload_id: string;\n  /** 分片索引（从 1 开始） */\n  chunk_index: number;\n  /** 分片数据（Base64 编码） */\n  base64_data: string;\n}\n\n/** 完成上传请求 body */\nexport interface UploadMediaFinishBody {\n  /** 上传会话 ID */\n  upload_id: string;\n}\n\n/** 完成上传响应 body */\nexport interface UploadMediaFinishResult {\n  /** 素材类型 */\n  type: WeComMediaType;\n  /** 临时素材 media_id，3天内有效 */\n  media_id: string;\n  /** 创建时间 */\n  created_at: string;\n}\n\n/** uploadMedia 方法选项 */\nexport interface UploadMediaOptions {\n  /** 素材类型 */\n  type: WeComMediaType;\n  /** 文件名 */\n  filename: string;\n}\n","/**\n * 事件相关类型定义\n */\n\nimport type {\n  BaseMessage,\n  TextMessage,\n  ImageMessage,\n  MixedMessage,\n  VoiceMessage,\n  FileMessage,\n  VideoMessage,\n} from './message';\nimport type { WsFrame } from './api';\n\n/** 事件类型枚举 */\nexport enum EventType {\n  /** 进入会话事件：用户当天首次进入机器人单聊会话 */\n  EnterChat = 'enter_chat',\n  /** 模板卡片事件：用户点击模板卡片按钮 */\n  TemplateCardEvent = 'template_card_event',\n  /** 用户反馈事件：用户对机器人回复进行反馈 */\n  FeedbackEvent = 'feedback_event',\n  /** 连接断开事件：有新连接建立时，服务端向旧连接发送此事件并主动断开 */\n  Disconnected = 'disconnected_event',\n}\n\n/** 事件发送者信息（比 MessageFrom 多了 corpid 字段） */\nexport interface EventFrom {\n  /** 事件触发者的 userid */\n  userid: string;\n  /** 事件触发者的 corpid，企业内部机器人不返回 */\n  corpid?: string;\n}\n\n/** 进入会话事件 */\nexport interface EnterChatEvent {\n  /** 事件类型 */\n  eventtype: EventType.EnterChat;\n}\n\n/** 模板卡片事件 */\nexport interface TemplateCardEventData {\n  /** 事件类型 */\n  eventtype: EventType.TemplateCardEvent;\n  /** 用户点击的按钮 key */\n  event_key?: string;\n  /** 任务 ID */\n  task_id?: string;\n}\n\n/** 用户反馈事件 */\nexport interface FeedbackEventData {\n  /** 事件类型 */\n  eventtype: EventType.FeedbackEvent;\n}\n\n/** 连接断开事件：有新连接建立时，服务端向旧连接推送此事件并主动断开旧连接 */\nexport interface DisconnectedEventData {\n  /** 事件类型 */\n  eventtype: EventType.Disconnected;\n}\n\n/** 事件内容联合类型 */\nexport type EventContent = EnterChatEvent | TemplateCardEventData | FeedbackEventData | DisconnectedEventData;\n\n/** 事件回调消息结构 */\nexport interface EventMessage {\n  /** 本次回调的唯一性标志，用于事件排重 */\n  msgid: string;\n  /** 事件产生的时间戳 */\n  create_time: number;\n  /** 智能机器人 id */\n  aibotid: string;\n  /** 会话 id，仅群聊类型时返回 */\n  chatid?: string;\n  /** 会话类型：single 单聊, group 群聊 */\n  chattype?: 'single' | 'group';\n  /** 事件触发者信息 */\n  from: EventFrom;\n  /** 消息类型，事件回调固定为 event */\n  msgtype: 'event';\n  /** 事件内容 */\n  event: EventContent;\n}\n\n/** 带有特定事件类型的事件消息 */\nexport type EventMessageWith<E extends EventContent> = Omit<EventMessage, 'event'> & { event: E };\n\n/** WSClient 事件映射类型 */\nexport interface WSClientEventMap {\n  /** 收到消息（所有类型），body 为 BaseMessage */\n  message: (data: WsFrame<BaseMessage>) => void;\n  /** 收到文本消息，body 为 TextMessage */\n  'message.text': (data: WsFrame<TextMessage>) => void;\n  /** 收到图片消息，body 为 ImageMessage */\n  'message.image': (data: WsFrame<ImageMessage>) => void;\n  /** 收到图文混排消息，body 为 MixedMessage */\n  'message.mixed': (data: WsFrame<MixedMessage>) => void;\n  /** 收到语音消息，body 为 VoiceMessage */\n  'message.voice': (data: WsFrame<VoiceMessage>) => void;\n  /** 收到文件消息，body 为 FileMessage */\n  'message.file': (data: WsFrame<FileMessage>) => void;\n  /** 收到视频消息，body 为 VideoMessage */\n  'message.video': (data: WsFrame<VideoMessage>) => void;\n  /** 收到事件回调（所有事件类型），body 为 EventMessage */\n  event: (data: WsFrame<EventMessage>) => void;\n  /** 收到进入会话事件，body 为 EventMessage（event 字段为 EnterChatEvent） */\n  'event.enter_chat': (data: WsFrame<EventMessageWith<EnterChatEvent>>) => void;\n  /** 收到模板卡片事件，body 为 EventMessage（event 字段为 TemplateCardEventData） */\n  'event.template_card_event': (data: WsFrame<EventMessageWith<TemplateCardEventData>>) => void;\n  /** 收到用户反馈事件，body 为 EventMessage（event 字段为 FeedbackEventData） */\n  'event.feedback_event': (data: WsFrame<EventMessageWith<FeedbackEventData>>) => void;\n  /** 收到连接断开事件：有新连接建立，服务端主动断开当前旧连接 */\n  'event.disconnected_event': (data: WsFrame<EventMessageWith<DisconnectedEventData>>) => void;\n  /** 连接建立 */\n  connected: () => void;\n  /** 认证成功 */\n  authenticated: () => void;\n  /** 连接断开 */\n  disconnected: (reason: string) => void;\n  /** 重连中 */\n  reconnecting: (attempt: number) => void;\n  /** 发生错误 */\n  error: (error: Error) => void;\n}\n","import axios, { AxiosInstance } from 'axios';\nimport type { Logger } from './types';\n\n/**\n * 企业微信 API 客户端\n * 仅负责文件下载等 HTTP 辅助功能，消息收发均走 WebSocket 通道\n */\nexport class WeComApiClient {\n  private httpClient: AxiosInstance;\n  private logger: Logger;\n\n  constructor(logger: Logger, timeout: number = 10000) {\n    this.logger = logger;\n\n    this.httpClient = axios.create({\n      timeout,\n      headers: {\n        'Content-Type': 'application/json',\n      },\n    });\n  }\n\n  /**\n   * 下载文件（返回原始 Buffer 及文件名）\n   */\n  async downloadFileRaw(url: string): Promise<{ buffer: Buffer; filename?: string }> {\n    this.logger.info('Downloading file...');\n\n    try {\n      const response = await this.httpClient.get(url, {\n        responseType: 'arraybuffer',\n      });\n\n      // 从 Content-Disposition 头中解析文件名\n      const contentDisposition = response.headers['content-disposition'] as string | undefined;\n      let filename: string | undefined;\n      if (contentDisposition) {\n        // 优先匹配 filename*=UTF-8''xxx 格式（RFC 5987）\n        const utf8Match = contentDisposition.match(/filename\\*=UTF-8''([^;\\s]+)/i);\n        if (utf8Match) {\n          filename = decodeURIComponent(utf8Match[1]);\n        } else {\n          // 匹配 filename=\"xxx\" 或 filename=xxx 格式\n          const match = contentDisposition.match(/filename=\"?([^\";\\s]+)\"?/i);\n          if (match) {\n            filename = decodeURIComponent(match[1]);\n          }\n        }\n      }\n\n      this.logger.info('File downloaded successfully');\n      return { buffer: Buffer.from(response.data), filename };\n    } catch (error: any) {\n      this.logger.error('File download failed:', error.message);\n      throw error;\n    }\n  }\n}\n","import crypto from 'crypto';\n\n/**\n * 通用工具方法\n */\n\n/**\n * 生成随机字符串\n *\n * @param length - 随机字符串长度，默认 8\n * @returns 随机字符串\n */\nexport function generateRandomString(length: number = 8): string {\n  return crypto.randomBytes(Math.ceil(length / 2)).toString('hex').substring(0, length);\n}\n\n/**\n * 生成唯一请求 ID\n *\n * 格式：`{prefix}_{timestamp}_{random}`\n *\n * @param prefix - 前缀，通常为 cmd 名称\n * @returns 唯一请求 ID\n */\nexport function generateReqId(prefix: string): string {\n  const timestamp = Date.now();\n  const random = generateRandomString();\n  return `${prefix}_${timestamp}_${random}`;\n}\n","import WebSocket, { type ClientOptions as WsClientOptions } from 'ws';\nimport type { Logger, WsFrame } from './types';\nimport { WsCmd, WSAuthFailureError, WSReconnectExhaustedError } from './types';\nimport { generateReqId } from './utils';\n\n/** SDK 内置默认 WebSocket 连接地址 */\nconst DEFAULT_WS_URL = 'wss://openws.work.weixin.qq.com';\n\n/**\n * WebSocket 长连接管理器\n * 负责维护与企业微信的 WebSocket 长连接，包括心跳、重连、认证等\n */\n/** 回复队列中的单个任务项 */\ninterface ReplyQueueItem {\n  /** 要发送的帧数据 */\n  frame: WsFrame;\n  /** 发送成功（收到回执）时的 resolve，传入回执帧 */\n  resolve: (ackFrame: WsFrame) => void;\n  /** 发送失败（超时/errcode非0）时的 reject，errcode非0时传入回执帧，超时时传入Error */\n  reject: (reason: any) => void;\n}\n\nexport class WsConnectionManager {\n  private ws: WebSocket | null = null;\n  private logger: Logger;\n  private wsUrl: string;\n  private wsOptions: WsClientOptions;\n  private heartbeatInterval: number;\n  private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n  private maxReconnectAttempts: number;\n  private maxAuthFailureAttempts: number;\n  private reconnectAttempts: number = 0;\n  private authFailureAttempts: number = 0;\n  private isManualClose: boolean = false;\n  /** 标记最近一次连接关闭是否因认证失败触发（用于 scheduleReconnect 区分重连类型） */\n  private lastCloseWasAuthFailure: boolean = false;\n\n  /** 认证凭证 */\n  private botId: string = '';\n  private botSecret: string = '';\n  /** 额外的认证参数（如 scene、plug_version 等），会展开到认证帧 body 中 */\n  private extraAuthParams: Record<string, any> = {};\n\n  /** Number of consecutive missed heartbeat acks (pong) */\n  private missedPongCount: number = 0;\n  /** Max missed pong before treating connection as dead */\n  private readonly maxMissedPong: number = 2;\n  /** Base delay (ms) for exponential back-off reconnection */\n  private reconnectBaseDelay: number = 1000;\n  /** Upper cap (ms) for reconnect delay */\n  private readonly reconnectMaxDelay: number = 30000;\n  /** 重连定时器引用，用于在 disconnect/connect 时取消挂起的重连 */\n  private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n  /** 按 req_id 分组的回复发送队列，保证同一 req_id 的消息串行发送 */\n  private replyQueues: Map<string, ReplyQueueItem[]> = new Map();\n  /** 正在等待回执的 req_id 集合，value 包含超时定时器、resolve/reject 和序列号 */\n  private pendingAcks: Map<string, {\n    resolve: (ackFrame: WsFrame) => void;\n    reject: (reason: any) => void;\n    timer: ReturnType<typeof setTimeout>;\n    seq: number;\n  }> = new Map();\n  /** 自增序列号，用于区分同一 reqId 的不同 pending，防止超时与 ack 竞态 */\n  private pendingAckSeq: number = 0;\n  /** 回执超时时间（毫秒） */\n  private readonly replyAckTimeout: number = 5000;\n  /** 单个 req_id 的回复队列最大长度，超过后新消息将被拒绝 */\n  private maxReplyQueueSize: number = 500;\n\n  /** 连接建立回调（WebSocket open 事件，认证尚未完成） */\n  public onConnected: (() => void) | null = null;\n  /** 认证成功回调 */\n  public onAuthenticated: (() => void) | null = null;\n  /** 连接断开回调 */\n  public onDisconnected: ((reason: string) => void) | null = null;\n  /** 收到消息回调 */\n  public onMessage: ((frame: WsFrame) => void) | null = null;\n  /** 重连回调 */\n  public onReconnecting: ((attempt: number) => void) | null = null;\n  /** 错误回调 */\n  public onError: ((error: Error) => void) | null = null;\n  /** 服务端主动断开回调（新连接建立导致旧连接被断开） */\n  public onServerDisconnect: ((reason: string) => void) | null = null;\n\n  constructor(\n    logger: Logger,\n    heartbeatInterval: number = 30000,\n    reconnectBaseDelay: number = 1000,\n    maxReconnectAttempts: number = 10,\n    wsUrl?: string,\n    wsOptions?: WsClientOptions,\n    maxReplyQueueSize?: number,\n    maxAuthFailureAttempts?: number,\n  ) {\n    this.logger = logger;\n    this.heartbeatInterval = heartbeatInterval;\n    this.reconnectBaseDelay = reconnectBaseDelay;\n    this.maxReconnectAttempts = maxReconnectAttempts;\n    this.maxAuthFailureAttempts = maxAuthFailureAttempts ?? 5;\n    this.wsUrl = wsUrl || DEFAULT_WS_URL;\n    this.wsOptions = wsOptions || {};\n    if (maxReplyQueueSize !== undefined) {\n      this.maxReplyQueueSize = maxReplyQueueSize;\n    }\n  }\n\n  /**\n   * 设置认证凭证\n   */\n  setCredentials(botId: string, botSecret: string, extraAuthParams?: Record<string, any>): void {\n    this.botId = botId;\n    this.botSecret = botSecret;\n    this.extraAuthParams = extraAuthParams || {};\n  }\n\n  /**\n   * 建立 WebSocket 连接（使用 SDK 内置默认地址）\n   */\n  connect(): void {\n    this.isManualClose = false;\n\n    // 取消挂起的重连定时器，防止与当前 connect 竞态\n    if (this.reconnectTimer) {\n      clearTimeout(this.reconnectTimer);\n      this.reconnectTimer = null;\n    }\n\n    // 清理可能未完全关闭的旧连接\n    if (this.ws) {\n      this.ws.removeAllListeners();\n      this.ws.terminate();\n      this.ws = null;\n    }\n\n    this.logger.info(`Connecting to WebSocket: ${this.wsUrl}...`);\n\n    try {\n      this.ws = new WebSocket(this.wsUrl, this.wsOptions);\n      this.setupEventHandlers();\n    } catch (error: any) {\n      this.logger.error('Failed to create WebSocket connection:', error.message);\n      this.onError?.(error);\n      this.scheduleReconnect();\n    }\n  }\n\n  /**\n   * 设置 WebSocket 事件处理器\n   */\n  private setupEventHandlers(): void {\n    if (!this.ws) return;\n\n    this.ws.on('open', () => {\n      this.logger.info('WebSocket connection established, sending auth...');\n      // 注意：不在 open 时重置 reconnectAttempts，因为 TCP 连接成功不代表认证会成功。\n      // 只有在认证成功后才重置所有计数器（见 handleFrame 中的认证响应处理）。\n      this.missedPongCount = 0;\n      this.lastCloseWasAuthFailure = false;\n      // 连接建立后立即发送认证帧\n      this.sendAuth();\n      this.onConnected?.();\n    });\n\n    this.ws.on('message', (data: WebSocket.Data) => {\n      try {\n        const raw = data.toString().replace(\n          /[\\x00-\\x08\\x0B-\\x0D\\x0E-\\x1F]/g,\n          \"\",\n        );\n        const frame = JSON.parse(raw) as WsFrame;\n        this.handleFrame(frame);\n      } catch (error: any) {\n        this.logger.error('Failed to parse WebSocket message:', error.message);\n      }\n    });\n\n    this.ws.on('close', (code: number, reason: Buffer) => {\n      const reasonStr = reason.toString() || `code: ${code}`;\n      this.logger.warn(`WebSocket connection closed: ${reasonStr}`);\n      this.stopHeartbeat();\n      this.clearPendingMessages(`WebSocket connection closed (${reasonStr})`);\n      this.onDisconnected?.(reasonStr);\n      // 释放旧 WebSocket 实例引用，便于 GC 回收\n      this.ws = null;\n\n      if (!this.isManualClose) {\n        this.scheduleReconnect();\n      }\n    });\n\n    this.ws.on('error', (error: Error) => {\n      this.logger.error('WebSocket error:', error.message);\n      this.onError?.(error);\n    });\n\n    this.ws.on('ping', () => {\n      this.ws?.pong();\n    });\n  }\n\n\n\n  /**\n   * 发送认证帧\n   *\n   * 格式：{ cmd: \"aibot_subscribe\", headers: { req_id }, body: { secret, bot_id } }\n   */\n  private sendAuth(): void {\n    try {\n      this.send({\n        cmd: WsCmd.SUBSCRIBE,\n        headers: { req_id: generateReqId(WsCmd.SUBSCRIBE) },\n        body: {\n          bot_id: this.botId,\n          secret: this.botSecret,\n          ...this.extraAuthParams,\n        },\n      });\n      this.logger.info('Auth frame sent');\n    } catch (error: any) {\n      this.logger.error('Failed to send auth frame:', error.message);\n    }\n  }\n\n  /**\n   * 处理收到的帧数据\n   *\n   * 接收帧结构：\n   * - 消息推送：{ cmd: \"aibot_msg_callback\", headers: { req_id }, body: { ... } }\n   * - 认证/心跳响应：{ headers: { req_id }, errcode: 0, errmsg: \"ok\" }\n   */\n  private handleFrame(frame: WsFrame): void {\n    const cmd = frame.cmd || '';\n    const reqId = frame.headers?.req_id || '';\n\n    // 消息推送：cmd 为 \"aibot_msg_callback\"\n    if (frame.cmd === WsCmd.CALLBACK) {\n      this.logger.debug(`[server -> plugin] cmd=${cmd}, reqId=${reqId}, body=${JSON.stringify(frame.body)}`);\n      this.onMessage?.(frame);\n      return;\n    }\n\n    // 事件推送：cmd 为 \"aibot_event_callback\"\n    if (frame.cmd === WsCmd.EVENT_CALLBACK) {\n      this.logger.debug(`[server -> plugin] cmd=${cmd}, reqId=${reqId}, body=${JSON.stringify(frame.body)}`);\n\n      // 检测 disconnected_event：有新连接建立，服务端通知旧连接即将被断开\n      if (frame.body?.event?.eventtype === 'disconnected_event') {\n        this.logger.warn('Received disconnected_event: a new connection has been established, this connection will be closed by server');\n        // 先分发事件给上层（让用户可以监听 event.disconnected_event）\n        this.onMessage?.(frame);\n        // 停止心跳、清理待处理消息\n        this.stopHeartbeat();\n        this.clearPendingMessages('Server disconnected due to new connection');\n        // 标记为非手动断开但阻止自动重连（服务端正常行为，重连也会被再次断开）\n        this.isManualClose = true;\n        // 通知上层服务端主动断开\n        this.onServerDisconnect?.('New connection established, server disconnected this connection');\n        // 主动关闭 socket，避免连接处于僵尸状态\n        if (this.ws) {\n          this.ws.removeAllListeners();\n          this.ws.terminate();\n          this.ws = null;\n        }\n        return;\n      }\n\n      this.onMessage?.(frame);\n      return;\n    }\n\n    // 无 cmd 的帧：认证响应、心跳响应或回复消息回执，通过 req_id 前缀区分类型，再判断 errcode\n    const actualReqId = frame.headers?.req_id || '';\n\n    // 认证响应（优先于 pendingAcks 检查，避免误判）\n    if (actualReqId.startsWith(WsCmd.SUBSCRIBE)) {\n      if (frame.errcode !== 0) {\n        this.logger.error(`Authentication failed: errcode=${frame.errcode}, errmsg=${frame.errmsg}`);\n        this.onError?.(new Error(`Authentication failed: ${frame.errmsg} (code: ${frame.errcode})`));\n        // 标记为认证失败，close 事件中 scheduleReconnect 会据此使用 authFailureAttempts 计数器\n        this.lastCloseWasAuthFailure = true;\n        // 认证失败，主动关闭连接，触发 close 事件进而执行 scheduleReconnect 重连逻辑\n        if (this.ws) {\n          this.ws.terminate();\n        }\n        return;\n      }\n      this.logger.info('Authentication successful');\n      // 认证成功：重置所有重连计数器\n      this.reconnectAttempts = 0;\n      this.authFailureAttempts = 0;\n      this.startHeartbeat();\n      this.onAuthenticated?.();\n      return;\n    }\n\n    // 心跳响应（优先于 pendingAcks 检查，避免误判）\n    if (actualReqId.startsWith(WsCmd.HEARTBEAT)) {\n      if (frame.errcode !== 0) {\n        this.logger.warn(`Heartbeat ack error: errcode=${frame.errcode}, errmsg=${frame.errmsg}`);\n        return;\n      }\n      this.missedPongCount = 0;\n      return;\n    }\n\n    // 检查是否是回复消息的回执（req_id 存在于 pendingAcks 中）\n    if (this.pendingAcks.has(actualReqId)) {\n      this.handleReplyAck(actualReqId, frame);\n      return;\n    }\n\n    // 未知帧类型 — 只记录警告，不传给 onMessage（避免 body=undefined 导致下游误处理）\n    this.logger.warn('Received unknown frame (ignored):', JSON.stringify(frame));\n  }\n\n  /**\n   * 启动心跳定时器\n   */\n  private startHeartbeat(): void {\n    this.stopHeartbeat();\n    this.heartbeatTimer = setInterval(() => {\n      this.sendHeartbeat();\n    }, this.heartbeatInterval);\n    this.logger.debug(`Heartbeat timer started, interval: ${this.heartbeatInterval}ms`);\n  }\n\n  /**\n   * 停止心跳定时器\n   */\n  private stopHeartbeat(): void {\n    if (this.heartbeatTimer) {\n      clearInterval(this.heartbeatTimer);\n      this.heartbeatTimer = null;\n      this.logger.debug('Heartbeat timer stopped');\n    }\n  }\n\n  /**\n   * 发送心跳\n   * If consecutive missed pong count reaches the threshold, treat the\n   * connection as dead and trigger reconnection.\n   *\n   * 格式：{ cmd: \"ping\", headers: { req_id } }\n   */\n  private sendHeartbeat(): void {\n    // Check missed pong BEFORE sending the next heartbeat\n    if (this.missedPongCount >= this.maxMissedPong) {\n      this.logger.warn(\n        `No heartbeat ack received for ${this.missedPongCount} consecutive pings, connection considered dead`,\n      );\n      this.stopHeartbeat();\n      // Force-close the underlying socket so the 'close' handler fires\n      if (this.ws) {\n        this.ws.terminate();\n      }\n      return;\n    }\n\n    this.missedPongCount++;\n    try {\n      this.send({\n        cmd: WsCmd.HEARTBEAT,\n        headers: { req_id: generateReqId(WsCmd.HEARTBEAT) },\n      });\n    } catch (error: any) {\n      this.logger.error('Failed to send heartbeat:', error.message);\n    }\n  }\n\n  /**\n   * 安排重连\n   *\n   * 区分两种重连场景，使用独立的计数器和最大重试次数：\n   * - 认证失败（lastCloseWasAuthFailure=true）：使用 authFailureAttempts / maxAuthFailureAttempts\n   * - 连接断开（lastCloseWasAuthFailure=false）：使用 reconnectAttempts / maxReconnectAttempts\n   *\n   * disconnected_event（被踢下线）不会触发重连，因为 isManualClose 已被设为 true。\n   */\n  private scheduleReconnect(): void {\n    if (this.lastCloseWasAuthFailure) {\n      // 认证失败场景\n      if (this.maxAuthFailureAttempts !== -1 && this.authFailureAttempts >= this.maxAuthFailureAttempts) {\n        this.logger.error(`Max auth failure attempts reached (${this.maxAuthFailureAttempts}), giving up`);\n        this.onError?.(new WSAuthFailureError(this.maxAuthFailureAttempts));\n        return;\n      }\n      this.authFailureAttempts++;\n\n      const delay = Math.min(\n        this.reconnectBaseDelay * Math.pow(2, this.authFailureAttempts - 1),\n        this.reconnectMaxDelay,\n      );\n\n      this.logger.info(`Auth failed, reconnecting in ${delay}ms (auth attempt ${this.authFailureAttempts}/${this.maxAuthFailureAttempts})...`);\n      this.onReconnecting?.(this.authFailureAttempts);\n\n      this.reconnectTimer = setTimeout(() => {\n        this.reconnectTimer = null;\n        if (this.isManualClose) return;\n        this.connect();\n      }, delay);\n    } else {\n      // 连接断开场景（网络异常、心跳超时等）\n      if (this.maxReconnectAttempts !== -1 && this.reconnectAttempts >= this.maxReconnectAttempts) {\n        this.logger.error(`Max reconnect attempts reached (${this.maxReconnectAttempts}), giving up`);\n        this.onError?.(new WSReconnectExhaustedError(this.maxReconnectAttempts));\n        return;\n      }\n      this.reconnectAttempts++;\n\n      const delay = Math.min(\n        this.reconnectBaseDelay * Math.pow(2, this.reconnectAttempts - 1),\n        this.reconnectMaxDelay,\n      );\n\n      this.logger.info(`Connection lost, reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);\n      this.onReconnecting?.(this.reconnectAttempts);\n\n      this.reconnectTimer = setTimeout(() => {\n        this.reconnectTimer = null;\n        if (this.isManualClose) return;\n        this.connect();\n      }, delay);\n    }\n  }\n\n  /**\n   * 发送数据帧\n   *\n   * 统一格式：{ cmd, headers: { req_id }, body }\n   */\n  send(frame: WsFrame): void {\n    if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n      const data = JSON.stringify(frame);\n      this.ws.send(data);\n    } else {\n      throw new Error('WebSocket not connected, unable to send data');\n    }\n  }\n\n  /**\n   * 通过 WebSocket 通道发送回复消息（串行队列版本）\n   *\n   * 同一个 req_id 的消息会被放入队列中串行发送：\n   * 发送一条后等待服务端回执，收到回执或超时后才发送下一条。\n   *\n   * 格式：{ cmd: \"aibot_respond_msg\", headers: { req_id }, body: { ... } }\n   *\n   * @param reqId - 透传回调中的 req_id\n   * @param body - 回复消息体（如 StreamReplyBody）\n   * @param cmd - 发送的命令类型，默认 WsCmd.RESPONSE\n   * @returns Promise，收到回执时 resolve(回执帧)，超时或errcode非0时 reject(Error)\n   */\n  sendReply(reqId: string, body: any, cmd: string = WsCmd.RESPONSE): Promise<WsFrame> {\n    // // 日志中截断 base64_data，避免分片上传时日志过大\n    // const logBody = body?.base64_data\n    //   ? { ...body, base64_data: `<${body.base64_data.length} chars>` }\n    //   : body;\n    // this.logger.debug(`[ws] sendReply: reqId=${reqId}, cmd=${cmd}, body=${JSON.stringify(logBody)}`);\n    return new Promise<WsFrame>((resolve, reject) => {\n      const frame: WsFrame = {\n        cmd,\n        headers: { req_id: reqId },\n        body,\n      };\n\n      const item: ReplyQueueItem = { frame, resolve, reject };\n\n      // 入队\n      if (!this.replyQueues.has(reqId)) {\n        this.replyQueues.set(reqId, []);\n      }\n\n      const queue = this.replyQueues.get(reqId)!;\n\n      // 防止队列无限增长导致内存泄漏\n      if (queue.length >= this.maxReplyQueueSize) {\n        this.logger.warn(`Reply queue for reqId ${reqId} exceeds max size (${this.maxReplyQueueSize}), rejecting new message`);\n        reject(new Error(`Reply queue for reqId ${reqId} exceeds max size (${this.maxReplyQueueSize})`));\n        return;\n      }\n\n      queue.push(item);\n\n      // 如果队列中只有这一条，说明当前空闲，立即开始处理\n      if (queue.length === 1) {\n        this.processReplyQueue(reqId);\n      }\n    });\n  }\n\n  /**\n   * 处理指定 req_id 的回复队列\n   * 取出队列头部的消息发送，并设置回执超时\n   */\n  private processReplyQueue(reqId: string): void {\n    const queue = this.replyQueues.get(reqId);\n    if (!queue || queue.length === 0) {\n      // 队列为空，清理\n      this.replyQueues.delete(reqId);\n      return;\n    }\n\n    const item = queue[0];\n\n    try {\n      // 发送帧\n      this.send(item.frame);\n      this.logger.debug(`Reply message sent via WebSocket, reqId: ${reqId}, queue length: ${queue.length}`);\n    } catch (error: any) {\n      this.logger.error(`Failed to send reply for reqId ${reqId}:`, error.message);\n      // 发送失败：reject 当前项，用 queueMicrotask 异步继续处理下一条，避免同步递归栈溢出\n      queue.shift();\n      item.reject(error);\n      queueMicrotask(() => this.processReplyQueue(reqId));\n      return;\n    }\n\n    // 分配唯一序列号，用于超时回调中校验是否是当前 pending\n    const seq = ++this.pendingAckSeq;\n\n    // 设置回执超时定时器\n    const timer = setTimeout(() => {\n      // 校验 seq：如果不匹配，说明这是过期的超时回调（当前 pending 已被正常 ack 处理过），直接忽略\n      const currentPending = this.pendingAcks.get(reqId);\n      if (!currentPending || currentPending.seq !== seq) {\n        return;\n      }\n\n      this.logger.warn(`Reply ack timeout (${this.replyAckTimeout}ms) for reqId: ${reqId}`);\n      this.pendingAcks.delete(reqId);\n\n      // 超时：reject 当前项，然后继续处理队列中的下一条\n      queue.shift();\n      item.reject(new Error(`Reply ack timeout (${this.replyAckTimeout}ms) for reqId: ${reqId}`));\n\n      this.processReplyQueue(reqId);\n    }, this.replyAckTimeout);\n\n    // 注册到待回执 Map\n    this.pendingAcks.set(reqId, {\n      resolve: item.resolve,\n      reject: item.reject,\n      timer,\n      seq,\n    });\n  }\n\n  /**\n   * 处理回复消息的回执\n   * 收到回执后释放队列锁，继续处理下一条\n   */\n  private handleReplyAck(reqId: string, frame: WsFrame): void {\n    const pending = this.pendingAcks.get(reqId);\n    if (!pending) return;\n\n    // 清除超时定时器\n    clearTimeout(pending.timer);\n    this.pendingAcks.delete(reqId);\n\n    const queue = this.replyQueues.get(reqId);\n\n    if (frame.errcode !== 0) {\n      this.logger.warn(`Reply ack error: reqId=${reqId}, errcode=${frame.errcode}, errmsg=${frame.errmsg}`);\n      // 失败：reject 当前项\n      if (queue) {\n        queue.shift();\n      }\n      pending.reject(frame);\n    } else {\n      this.logger.debug(`Reply ack received for reqId: ${reqId}`);\n      // 成功：resolve 当前项，传入完整回执帧\n      if (queue) {\n        queue.shift();\n      }\n      pending.resolve(frame);\n    }\n\n    // 继续处理队列中的下一条\n    this.processReplyQueue(reqId);\n  }\n\n  /**\n   * 主动断开连接\n   */\n  /**\n   * 清理所有待处理的消息和回执\n   * @param reason - 清理原因，用于 reject 的错误信息\n   */\n  private clearPendingMessages(reason: string): void {\n    // 收集所有已在 pendingAcks 中的 reject 函数引用，用于后续去重\n    const pendingRejects = new Set<(reason: any) => void>();\n\n    // 先清理 pendingAcks：清除定时器并 reject 正在等待回执的消息\n    for (const [reqId, pending] of this.pendingAcks) {\n      clearTimeout(pending.timer);\n      pendingRejects.add(pending.reject);\n      pending.reject(new Error(`${reason}, reply for reqId: ${reqId} cancelled`));\n    }\n    this.pendingAcks.clear();\n\n    // 再清理 replyQueues：跳过已经在 pendingAcks 中被 reject 过的队首 item，避免双重 reject\n    for (const [reqId, queue] of this.replyQueues) {\n      for (const item of queue) {\n        if (pendingRejects.has(item.reject)) {\n          continue; // 已在 pendingAcks 中被 reject 过，跳过\n        }\n        item.reject(new Error(`${reason}, reply for reqId: ${reqId} cancelled`));\n      }\n    }\n    this.replyQueues.clear();\n  }\n\n  disconnect(): void {\n    this.isManualClose = true;\n    this.stopHeartbeat();\n    this.clearPendingMessages('Connection manually closed');\n\n    // 取消挂起的重连定时器\n    if (this.reconnectTimer) {\n      clearTimeout(this.reconnectTimer);\n      this.reconnectTimer = null;\n    }\n\n    if (this.ws) {\n      this.ws.terminate();\n      this.ws = null;\n    }\n\n    this.logger.info('WebSocket connection manually closed');\n  }\n\n  /**\n   * 检查指定 reqId 是否有待回执的消息（即上一条消息还未收到 ack）\n   *\n   * 用于流式场景：调用方可据此决定是否跳过当前帧，避免排队积压。\n   *\n   * @param reqId - 要检查的 req_id\n   * @returns true 表示有消息正在等待 ack\n   */\n  hasPendingAck(reqId: string): boolean {\n    return this.pendingAcks.has(reqId);\n  }\n\n  /**\n   * 获取当前连接状态\n   */\n  get isConnected(): boolean {\n    return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n  }\n}\n","import type {\n  BaseMessage,\n  WsFrame,\n  Logger,\n  WSClientEventMap,\n} from './types';\nimport { MessageType, WsCmd } from './types';\nimport type { EventMessage } from './types';\nimport type { WSClient } from './client';\n\n/**\n * 消息处理器\n * 负责解析 WebSocket 帧并分发为具体的消息事件和事件回调\n */\nexport class MessageHandler {\n  private logger: Logger;\n\n  constructor(logger: Logger) {\n    this.logger = logger;\n  }\n\n  /**\n   * 处理收到的 WebSocket 帧，解析并触发对应的消息/事件\n   *\n   * WebSocket 推送帧结构：\n   * - 消息推送：{ cmd: \"aibot_msg_callback\", headers: { req_id: \"xxx\" }, body: { msgid, msgtype, ... } }\n   * - 事件推送：{ cmd: \"aibot_event_callback\", headers: { req_id: \"xxx\" }, body: { msgid, msgtype: \"event\", event: { ... } } }\n   *\n   * @param frame - WebSocket 接收帧\n   * @param emitter - WSClient 实例，用于触发事件\n   */\n  handleFrame(frame: WsFrame, emitter: WSClient): void {\n    try {\n      const body = frame.body;\n\n      if (!body || !body.msgtype) {\n        this.logger.warn('Received invalid message format:', JSON.stringify(frame).substring(0, 200));\n        return;\n      }\n\n      // 事件推送回调处理\n      if (frame.cmd === WsCmd.EVENT_CALLBACK) {\n        this.handleEventCallback(frame, emitter);\n        return;\n      }\n\n      // 消息推送回调处理\n      this.handleMessageCallback(frame, emitter);\n    } catch (error: any) {\n      this.logger.error('Failed to handle message:', error.message);\n    }\n  }\n\n  /**\n   * 处理消息推送回调 (aibot_msg_callback)\n   */\n  private handleMessageCallback(frame: WsFrame, emitter: WSClient): void {\n    const body = frame.body as BaseMessage;\n\n    // 触发通用消息事件\n    emitter.emit('message', frame);\n\n    // 根据 body 中的消息类型触发特定事件\n    switch (body.msgtype) {\n      case MessageType.Text:\n        emitter.emit('message.text', frame);\n        break;\n      case MessageType.Image:\n        emitter.emit('message.image', frame);\n        break;\n      case MessageType.Mixed:\n        emitter.emit('message.mixed', frame);\n        break;\n      case MessageType.Voice:\n        emitter.emit('message.voice', frame);\n        break;\n      case MessageType.File:\n        emitter.emit('message.file', frame);\n        break;\n      case MessageType.Video:\n        emitter.emit('message.video', frame);\n        break;\n      default:\n        this.logger.debug(`Received unhandled message type: ${body.msgtype}`);\n        break;\n    }\n  }\n\n  /**\n   * 处理事件推送回调 (aibot_event_callback)\n   */\n  private handleEventCallback(frame: WsFrame, emitter: WSClient): void {\n    const body = frame.body as EventMessage;\n\n    // 触发通用事件\n    emitter.emit('event', frame);\n\n    // 根据事件类型触发特定事件\n    const eventType = body.event?.eventtype;\n    if (eventType) {\n      const eventKey = `event.${eventType}` as keyof WSClientEventMap;\n      emitter.emit(eventKey, frame);\n    } else {\n      this.logger.debug('Received event callback without eventtype:', JSON.stringify(body).substring(0, 200));\n    }\n  }\n}\n","import crypto from 'crypto';\n\n/**\n * 加解密工具模块\n * 提供文件加解密相关的功能函数\n */\n\n/**\n * 使用 AES-256-CBC 解密文件\n *\n * @param encryptedBuffer - 加密的文件数据\n * @param aesKey - Base64 编码的 AES-256 密钥\n * @returns 解密后的文件 Buffer\n */\nexport function decryptFile(encryptedBuffer: Buffer, aesKey: string): Buffer {\n  // 参数验证\n  if (!encryptedBuffer || encryptedBuffer.length === 0) {\n    throw new Error('decryptFile: encryptedBuffer is empty or not provided');\n  }\n\n  if (!aesKey || typeof aesKey !== 'string') {\n    throw new Error('decryptFile: aesKey must be a non-empty string');\n  }\n\n  // 将 Base64 编码的 aesKey 解码为 Buffer\n  const key = Buffer.from(aesKey, 'base64');\n\n  // IV 取 aesKey 解码后的前 16 字节\n  const iv = key.subarray(0, 16);\n\n  try {\n    const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);\n    // 关闭自动 padding，因为文档要求 PKCS#7 填充至 32 字节的倍数，\n    // 而 Node.js 默认按 16 字节 block 去除 padding，会导致 bad decrypt 错误\n    decipher.setAutoPadding(false);\n\n    const decrypted = Buffer.concat([\n      decipher.update(encryptedBuffer),\n      decipher.final(),\n    ]);\n\n    // 手动去除 PKCS#7 填充（支持 32 字节 block）\n    const padLen = decrypted[decrypted.length - 1];\n    if (padLen < 1 || padLen > 32 || padLen > decrypted.length) {\n      throw new Error(`Invalid PKCS#7 padding value: ${padLen}`);\n    }\n    // 验证所有 padding 字节是否一致\n    for (let i = decrypted.length - padLen; i < decrypted.length; i++) {\n      if (decrypted[i] !== padLen) {\n        throw new Error('Invalid PKCS#7 padding: padding bytes mismatch');\n      }\n    }\n\n    return decrypted.subarray(0, decrypted.length - padLen);\n  } catch (error: any) {\n    throw new Error(`decryptFile: Decryption failed - ${error.message}. This may indicate corrupted data or an incorrect aesKey.`);\n  }\n}\n","import type { Logger } from './types';\n\n/**\n * 默认日志实现\n * 带有日志级别和时间戳的控制台日志\n */\nexport class DefaultLogger implements Logger {\n  private prefix: string;\n\n  constructor(prefix: string = 'AiBotSDK') {\n    this.prefix = prefix;\n  }\n\n  private formatTime(): string {\n    return new Date().toISOString();\n  }\n\n  debug(message: string, ...args: any[]): void {\n    console.debug(`[${this.formatTime()}] [${this.prefix}] [DEBUG] ${message}`, ...args);\n  }\n\n  info(message: string, ...args: any[]): void {\n    console.info(`[${this.formatTime()}] [${this.prefix}] [INFO] ${message}`, ...args);\n  }\n\n  warn(message: string, ...args: any[]): void {\n    console.warn(`[${this.formatTime()}] [${this.prefix}] [WARN] ${message}`, ...args);\n  }\n\n  error(message: string, ...args: any[]): void {\n    console.error(`[${this.formatTime()}] [${this.prefix}] [ERROR] ${message}`, ...args);\n  }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type {\n  WSClientOptions,\n  WSClientEventMap,\n  WsFrame,\n  WsFrameHeaders,\n  StreamReplyBody,\n  ReplyMsgItem,\n  ReplyFeedback,\n  WelcomeTextReplyBody,\n  WelcomeTemplateCardReplyBody,\n  UpdateTemplateCardBody,\n  TemplateCard,\n  TemplateCardReplyBody,\n  StreamWithTemplateCardReplyBody,\n  SendMarkdownMsgBody,\n  SendTemplateCardMsgBody,\n  SendMediaMsgBody,\n  SendMsgBody,\n  WeComMediaType,\n  UploadMediaOptions,\n  UploadMediaFinishResult,\n} from './types';\nimport { WsCmd } from './types';\nimport { createHash } from 'crypto';\nimport type { Logger } from './types';\nimport { WeComApiClient } from './api';\nimport { WsConnectionManager } from './ws';\nimport { MessageHandler } from './message-handler';\nimport { decryptFile } from './crypto';\nimport { DefaultLogger } from './logger';\nimport { generateReqId } from './utils';\n\nexport class WSClient extends EventEmitter<WSClientEventMap> {\n  private options: Required<WSClientOptions>;\n  private apiClient: WeComApiClient;\n  private wsManager: WsConnectionManager;\n  private messageHandler: MessageHandler;\n  private logger: Logger;\n  private started: boolean = false;\n\n  constructor(options: WSClientOptions) {\n    super();\n\n    // 合并默认选项\n    this.options = {\n      reconnectInterval: 1000,\n      maxReconnectAttempts: 10,\n      maxAuthFailureAttempts: 5,\n      heartbeatInterval: 30000,\n      requestTimeout: 10000,\n      wsUrl: '',\n      wsOptions: {},\n      maxReplyQueueSize: 500,\n      logger: new DefaultLogger(),\n      ...options,\n    } as Required<WSClientOptions>;\n\n    this.logger = this.options.logger;\n\n    // 初始化 API 客户端（仅用于文件下载）\n    this.apiClient = new WeComApiClient(\n      this.logger,\n      this.options.requestTimeout,\n    );\n\n    // 初始化 WebSocket 管理器\n    this.wsManager = new WsConnectionManager(\n      this.logger,\n      this.options.heartbeatInterval,\n      this.options.reconnectInterval,\n      this.options.maxReconnectAttempts,\n      this.options.wsUrl || undefined,\n      this.options.wsOptions,\n      this.options.maxReplyQueueSize,\n      this.options.maxAuthFailureAttempts,\n    );\n\n    // 设置认证凭证\n    this.wsManager.setCredentials(this.options.botId, this.options.secret, {\n      ...(this.options.scene !== undefined && { scene: this.options.scene }),\n      ...(this.options.plug_version !== undefined && { plug_version: this.options.plug_version }),\n    });\n\n    // 初始化消息处理器\n    this.messageHandler = new MessageHandler(this.logger);\n\n    // 绑定 WebSocket 事件\n    this.setupWsEvents();\n  }\n\n  /**\n   * 设置 WebSocket 事件处理\n   */\n  private setupWsEvents(): void {\n    this.wsManager.onConnected = () => {\n      this.emit('connected');\n    };\n\n    // 认证成功\n    this.wsManager.onAuthenticated = () => {\n      this.logger.info('Authenticated');\n      this.emit('authenticated');\n    };\n\n    this.wsManager.onDisconnected = (reason: string) => {\n      this.emit('disconnected', reason);\n    };\n\n    // 服务端因新连接建立而主动断开旧连接\n    this.wsManager.onServerDisconnect = (reason: string) => {\n      this.logger.warn(`Server disconnected this connection: ${reason}`);\n      this.started = false;\n      this.emit('disconnected', reason);\n    };\n\n    this.wsManager.onReconnecting = (attempt: number) => {\n      this.emit('reconnecting', attempt);\n    };\n\n    this.wsManager.onError = (error: Error) => {\n      this.emit('error', error);\n    };\n\n    this.wsManager.onMessage = (frame: WsFrame) => {\n      this.messageHandler.handleFrame(frame, this);\n    };\n  }\n\n  /**\n   * 建立 WebSocket 长连接\n   * SDK 使用内置默认地址建立连接，连接成功后自动发送认证帧（botId + secret）。\n   * 支持链式调用：wsClient.connect().on('message', handler)\n   *\n   * @returns 返回 this，支持链式调用\n   */\n  connect(): this {\n    if (this.started) {\n      this.logger.warn('Client already connected');\n      return this;\n    }\n\n    this.logger.info('Establishing WebSocket connection...');\n    this.started = true;\n\n    // 直接使用内置默认地址建立连接，连接成功后自动认证\n    this.wsManager.connect();\n\n    return this;\n  }\n\n  /**\n   * 断开 WebSocket 连接\n   */\n  disconnect(): void {\n    if (!this.started) {\n      this.logger.warn('Client not connected');\n      return;\n    }\n\n    this.logger.info('Disconnecting...');\n    this.started = false;\n    this.wsManager.disconnect();\n    this.logger.info('Disconnected');\n  }\n\n  /**\n   * 通过 WebSocket 通道发送回复消息（通用方法）\n   *\n   * @param frame - 收到的原始 WebSocket 帧，透传 headers.req_id\n   * @param body - 回复消息体\n   * @param cmd\n   */\n  reply(frame: WsFrameHeaders, body: StreamReplyBody | Record<string, any>, cmd?: string): Promise<WsFrame> {\n    const reqId = frame.headers?.req_id || '';\n    return this.wsManager.sendReply(reqId, body, cmd);\n  }\n\n  /**\n   * 发送流式文本回复（便捷方法）\n   *\n   * @param frame - 收到的原始 WebSocket 帧，透传 headers.req_id\n   * @param streamId - 流式消息 ID\n   * @param content - 回复内容（支持 Markdown）\n   * @param finish - 是否结束流式消息，默认 false\n   * @param msgItem - 图文混排项（仅在 finish=true 时有效），用于在结束时附带图片内容\n   * @param feedback - 反馈信息（仅在首次回复时设置）\n   */\n  replyStream(frame: WsFrameHeaders, streamId: string, content: string, finish: boolean = false, msgItem?: ReplyMsgItem[], feedback?: ReplyFeedback): Promise<WsFrame> {\n    const stream: StreamReplyBody['stream'] = {\n      id: streamId,\n      finish,\n      content,\n    };\n\n    // msg_item 仅在 finish=true 时支持\n    if (finish && msgItem && msgItem.length > 0) {\n      stream.msg_item = msgItem;\n    }\n\n    // feedback 仅在首次回复时设置\n    if (feedback) {\n      stream.feedback = feedback;\n    }\n\n    return this.reply(frame, {\n      msgtype: 'stream',\n      stream,\n    });\n  }\n\n  /**\n   * 发送欢迎语回复\n   *\n   * 注意：此方法需要使用对应事件（如 enter_chat）的 req_id 才能调用，\n   * 即 frame 参数应来自触发欢迎语的事件帧。\n   * 收到事件回调后需在 5 秒内发送回复，超时将无法发送欢迎语。\n   *\n   * @param frame - 对应事件的 WebSocket 帧（需包含该事件的 req_id）\n   * @param body - 欢迎语消息体（支持文本或模板卡片格式）\n   */\n  replyWelcome(frame: WsFrameHeaders, body: WelcomeTextReplyBody | WelcomeTemplateCardReplyBody): Promise<WsFrame> {\n    return this.reply(frame, body, WsCmd.RESPONSE_WELCOME);\n  }\n\n  /**\n   * 回复模板卡片消息\n   *\n   * 收到消息回调或进入会话事件后，可使用此方法回复模板卡片消息。\n   *\n   * @param frame - 收到的原始 WebSocket 帧，透传 headers.req_id\n   * @param templateCard - 模板卡片内容\n   * @param feedback - 反馈信息\n   */\n  replyTemplateCard(frame: WsFrameHeaders, templateCard: TemplateCard, feedback?: ReplyFeedback): Promise<WsFrame> {\n    const card = feedback ? { ...templateCard, feedback } : templateCard;\n    const body: TemplateCardReplyBody = {\n      msgtype: 'template_card',\n      template_card: card,\n    };\n    return this.reply(frame, body);\n  }\n\n  /**\n   * 发送流式消息 + 模板卡片组合回复\n   *\n   * 首次回复时必须返回 stream 的 id。\n   * template_card 可首次回复，也可在后续回复中发送，但同一个消息只能回复一次。\n   *\n   * @param frame - 收到的原始 WebSocket 帧，透传 headers.req_id\n   * @param streamId - 流式消息 ID\n   * @param content - 回复内容（支持 Markdown）\n   * @param finish - 是否结束流式消息，默认 false\n   * @param options - 可选项\n   * @param options.msgItem - 图文混排项（仅在 finish=true 时有效）\n   * @param options.streamFeedback - 流式消息反馈信息（首次回复时设置）\n   * @param options.templateCard - 模板卡片内容（同一消息只能回复一次）\n   * @param options.cardFeedback - 模板卡片反馈信息\n   */\n  replyStreamWithCard(\n    frame: WsFrameHeaders,\n    streamId: string,\n    content: string,\n    finish: boolean = false,\n    options?: {\n      msgItem?: ReplyMsgItem[];\n      streamFeedback?: ReplyFeedback;\n      templateCard?: TemplateCard;\n      cardFeedback?: ReplyFeedback;\n    },\n  ): Promise<WsFrame> {\n    const stream: StreamReplyBody['stream'] = {\n      id: streamId,\n      finish,\n      content,\n    };\n\n    if (finish && options?.msgItem && options.msgItem.length > 0) {\n      stream.msg_item = options.msgItem;\n    }\n\n    if (options?.streamFeedback) {\n      stream.feedback = options.streamFeedback;\n    }\n\n    const body: StreamWithTemplateCardReplyBody = {\n      msgtype: 'stream_with_template_card',\n      stream,\n    };\n\n    if (options?.templateCard) {\n      body.template_card = options.cardFeedback\n        ? { ...options.templateCard, feedback: options.cardFeedback }\n        : options.templateCard;\n    }\n\n    return this.reply(frame, body);\n  }\n\n  /**\n   * 更新模板卡片\n   *\n   * 注意：此方法需要使用对应事件（template_card_event）的 req_id 才能调用，\n   * 即 frame 参数应来自触发更新的事件帧。\n   * 收到事件回调后需在 5 秒内发送回复，超时将无法更新卡片。\n   *\n   * @param frame - 对应事件的 WebSocket 帧（需包含该事件的 req_id）\n   * @param templateCard - 模板卡片内容（task_id 需跟回调收到的 task_id 一致）\n   * @param userids - 要替换模版卡片消息的 userid 列表，若不填则替换所有用户\n   */\n  updateTemplateCard(frame: WsFrameHeaders, templateCard: TemplateCard, userids?: string[]): Promise<WsFrame> {\n    const body: UpdateTemplateCardBody = {\n      response_type: 'update_template_card',\n      template_card: templateCard,\n    };\n    if (userids && userids.length > 0) {\n      body.userids = userids;\n    }\n    return this.reply(frame, body, WsCmd.RESPONSE_UPDATE);\n  }\n\n  /**\n   * 主动发送消息\n   *\n   * 向指定会话（单聊或群聊）主动推送消息，无需依赖收到的回调帧。\n   *\n   * @param chatid - 会话 ID，单聊填用户的 userid，群聊填对应群聊的 chatid\n   * @param body - 消息体（支持 markdown 或 template_card 格式）\n   * @returns Promise，收到回执时 resolve(回执帧)\n   *\n   * @example\n   * ```ts\n   * // 发送 markdown 消息\n   * await wsClient.sendMessage('CHATID', {\n   *   msgtype: 'markdown',\n   *   markdown: { content: '这是一条**主动推送**的消息' },\n   * });\n   *\n   * // 发送模板卡片消息\n   * await wsClient.sendMessage('CHATID', {\n   *   msgtype: 'template_card',\n   *   template_card: { card_type: 'text_notice', ... },\n   * });\n   * ```\n   */\n  sendMessage(chatid: string, body: SendMsgBody): Promise<WsFrame> {\n    const reqId = generateReqId(WsCmd.SEND_MSG);\n    const fullBody = {\n      chatid,\n      ...body,\n    };\n    return this.wsManager.sendReply(reqId, fullBody, WsCmd.SEND_MSG);\n  }\n\n  /**\n   * 上传临时素材（三步分片上传）\n   *\n   * 通过 WebSocket 长连接执行分片上传：init → chunk × N → finish\n   * 单个分片不超过 512KB（Base64 编码前），最多 100 个分片。\n   *\n   * @param fileBuffer - 文件 Buffer\n   * @param options - 上传选项（类型、文件名）\n   * @returns 上传结果，包含 media_id\n   */\n  async uploadMedia(fileBuffer: Buffer, options: UploadMediaOptions): Promise<UploadMediaFinishResult> {\n    const { type, filename } = options;\n    const totalSize = fileBuffer.length;\n\n    // 分片大小：512KB（Base64 编码前）\n    const CHUNK_SIZE = 512 * 1024;\n    const totalChunks = Math.ceil(totalSize / CHUNK_SIZE);\n\n    if (totalChunks > 100) {\n      throw new Error(`File too large: ${totalChunks} chunks exceeds maximum of 100 chunks (max ~50MB)`);\n    }\n\n    // 计算文件 MD5\n    const md5 = createHash('md5').update(fileBuffer).digest('hex');\n\n    this.logger.info(`Uploading media: type=${type}, filename=${filename}, size=${totalSize}, chunks=${totalChunks}`);\n\n    // Step 1: 初始化上传\n    const initReqId = generateReqId(WsCmd.UPLOAD_MEDIA_INIT);\n    const initResult = await this.wsManager.sendReply(\n      initReqId,\n      { type, filename, total_size: totalSize, total_chunks: totalChunks, md5 },\n      WsCmd.UPLOAD_MEDIA_INIT,\n    );\n\n    const uploadId = initResult.body?.upload_id;\n    if (!uploadId) {\n      throw new Error(`Upload init failed: no upload_id returned. Response: ${JSON.stringify(initResult)}`);\n    }\n\n    this.logger.info(`Upload init success: upload_id=${uploadId}`);\n\n    // Step 2: 分片上传（带重试，根据分片数动态调整并发）\n    /** 单分片最大重试次数 */\n    const MAX_CHUNK_RETRIES = 2;\n    /**\n     * 动态计算并发数：\n     * - 1~4 分片（≤2MB）：全部并发\n     * - 5~10 分片（2~5MB）：并发 3\n     * - >10 分片（>5MB）：并发 2（企微后端对大量并发 chunk 会返回 system error）\n     */\n    const MAX_CONCURRENCY = totalChunks <= 4 ? totalChunks : totalChunks <= 10 ? 3 : 2;\n\n    const uploadChunk = async (chunkIndex: number): Promise<void> => {\n      const start = chunkIndex * CHUNK_SIZE;\n      const end = Math.min(start + CHUNK_SIZE, totalSize);\n      const chunk = fileBuffer.subarray(start, end);\n      const base64Data = chunk.toString('base64');\n\n      let lastError: unknown;\n      for (let attempt = 0; attempt <= MAX_CHUNK_RETRIES; attempt++) {\n        try {\n          const chunkReqId = generateReqId(WsCmd.UPLOAD_MEDIA_CHUNK);\n          await this.wsManager.sendReply(\n            chunkReqId,\n            { upload_id: uploadId, chunk_index: chunkIndex, base64_data: base64Data },\n            WsCmd.UPLOAD_MEDIA_CHUNK,\n          );\n          this.logger.debug(`Uploaded chunk ${chunkIndex + 1}/${totalChunks} (${chunk.length} bytes)`);\n          return;\n        } catch (err) {\n          lastError = err;\n          if (attempt < MAX_CHUNK_RETRIES) {\n            const delay = 500 * (attempt + 1);\n            this.logger.warn(\n              `Chunk ${chunkIndex} upload failed (attempt ${attempt + 1}/${MAX_CHUNK_RETRIES + 1}), ` +\n              `retrying in ${delay}ms... error: ${err instanceof Error ? err.message : JSON.stringify(err)}`,\n            );\n            await new Promise(r => setTimeout(r, delay));\n          }\n        }\n      }\n      // 所有重试都失败\n      const errMsg = lastError instanceof Error\n        ? lastError.message\n        : JSON.stringify(lastError);\n      throw new Error(`Chunk ${chunkIndex} upload failed after ${MAX_CHUNK_RETRIES + 1} attempts: ${errMsg}`);\n    };\n\n    this.logger.debug(`Upload concurrency: ${MAX_CONCURRENCY} workers for ${totalChunks} chunks`);\n\n    if (totalChunks <= 1) {\n      // 单分片直接上传\n      await uploadChunk(0);\n    } else {\n      // 多分片并发上传：动态并发数\n      let nextIndex = 0;\n      const errors: Error[] = [];\n\n      const runWorker = async (): Promise<void> => {\n        while (nextIndex < totalChunks) {\n          const idx = nextIndex++;\n          try {\n            await uploadChunk(idx);\n          } catch (err) {\n            errors.push(err instanceof Error ? err : new Error(String(err)));\n          }\n        }\n      };\n\n      const workerCount = Math.min(MAX_CONCURRENCY, totalChunks);\n      await Promise.all(Array.from({ length: workerCount }, () => runWorker()));\n\n      if (errors.length > 0) {\n        throw new Error(`Upload failed: ${errors.length} chunk(s) failed. First error: ${errors[0].message}`);\n      }\n    }\n\n    this.logger.info(`All ${totalChunks} chunks uploaded, finishing...`);\n\n    // Step 3: 完成上传\n    const finishReqId = generateReqId(WsCmd.UPLOAD_MEDIA_FINISH);\n    const finishResult = await this.wsManager.sendReply(\n      finishReqId,\n      { upload_id: uploadId },\n      WsCmd.UPLOAD_MEDIA_FINISH,\n    );\n\n    const mediaId = finishResult.body?.media_id;\n    if (!mediaId) {\n      throw new Error(`Upload finish failed: no media_id returned. Response: ${JSON.stringify(finishResult)}`);\n    }\n\n    this.logger.info(`Upload complete: media_id=${mediaId}, type=${finishResult.body?.type}`);\n\n    return {\n      type: finishResult.body?.type ?? type,\n      media_id: mediaId,\n      created_at: finishResult.body?.created_at ?? new Date().toISOString(),\n    };\n  }\n\n  /**\n   * 被动回复媒体消息（便捷方法）\n   *\n   * 通过 aibot_respond_msg 被动回复通道发送媒体消息（file/image/voice/video）\n   *\n   * @param frame - 收到的原始 WebSocket 帧，透传 headers.req_id\n   * @param mediaType - 媒体类型\n   * @param mediaId - 临时素材 media_id\n   * @param videoOptions - 视频消息可选参数（仅 mediaType='video' 时生效）\n   */\n  replyMedia(frame: WsFrameHeaders, mediaType: WeComMediaType, mediaId: string, videoOptions?: { title?: string; description?: string }): Promise<WsFrame> {\n    const mediaContent: Record<string, any> = { media_id: mediaId };\n    if (mediaType === 'video' && videoOptions) {\n      if (videoOptions.title) mediaContent.title = videoOptions.title;\n      if (videoOptions.description) mediaContent.description = videoOptions.description;\n    }\n    const body: SendMediaMsgBody = {\n      msgtype: mediaType,\n      [mediaType]: mediaContent,\n    };\n    return this.reply(frame, body);\n  }\n\n  /**\n   * 主动发送媒体消息（便捷方法）\n   *\n   * 通过 aibot_send_msg 主动推送通道发送媒体消息\n   *\n   * @param chatid - 会话 ID\n   * @param mediaType - 媒体类型\n   * @param mediaId - 临时素材 media_id\n   * @param videoOptions - 视频消息可选参数（仅 mediaType='video' 时生效）\n   */\n  sendMediaMessage(chatid: string, mediaType: WeComMediaType, mediaId: string, videoOptions?: { title?: string; description?: string }): Promise<WsFrame> {\n    const mediaContent: Record<string, any> = { media_id: mediaId };\n    if (mediaType === 'video' && videoOptions) {\n      if (videoOptions.title) mediaContent.title = videoOptions.title;\n      if (videoOptions.description) mediaContent.description = videoOptions.description;\n    }\n    const body: SendMediaMsgBody = {\n      msgtype: mediaType,\n      [mediaType]: mediaContent,\n    };\n    return this.sendMessage(chatid, body);\n  }\n\n  /**\n   * 下载文件并使用 AES 密钥解密\n   *\n   * @param url - 文件下载地址\n   * @param aesKey - AES 解密密钥（Base64 编码），取自消息中 image.aeskey 或 file.aeskey 字段\n   * @returns 解密后的文件 Buffer 及文件名\n   *\n   * @example\n   * ```ts\n   * // aesKey 来自消息体中的 image.aeskey 或 file.aeskey\n   * const { buffer, filename } = await wsClient.downloadFile(imageUrl, body.image?.aeskey);\n   * ```\n   */\n  async downloadFile(url: string, aesKey?: string): Promise<{ buffer: Buffer; filename?: string }> {\n    this.logger.debug(`[plugin] downloadFile: url=${url}, hasAesKey=${!!aesKey}`);\n    this.logger.info('Downloading and decrypting file...');\n\n    try {\n      // 下载加密的文件数据\n      const { buffer: encryptedBuffer, filename } = await this.apiClient.downloadFileRaw(url);\n\n      // 如果没有提供 aesKey，直接返回原始数据\n      if (!aesKey) {\n        this.logger.warn('No aesKey provided, returning raw file data');\n        return { buffer: encryptedBuffer, filename };\n      }\n\n      // 使用独立的解密模块进行 AES-256-CBC 解密\n      const decryptedBuffer = decryptFile(encryptedBuffer, aesKey);\n\n      this.logger.info('File downloaded and decrypted successfully');\n      return { buffer: decryptedBuffer, filename };\n    } catch (error: any) {\n      this.logger.error('File download/decrypt failed:', error.message);\n      throw error;\n    }\n  }\n\n  /**\n   * 检查指定消息帧是否有未完成的 ack（即上一条消息还未收到回执）\n   *\n   * 用于流式场景：调用方可据此决定是否跳过当前中间帧，避免排队积压。\n   *\n   * @param frame - 收到的原始 WebSocket 帧\n   * @returns true 表示有消息正在等待 ack\n   */\n  hasPendingReplyAck(frame: WsFrameHeaders): boolean {\n    const reqId = frame.headers?.req_id || '';\n    return this.wsManager.hasPendingAck(reqId);\n  }\n\n  /**\n   * 非阻塞流式文本回复\n   *\n   * 如果上一条同 reqId 的消息尚未收到 ack，则跳过本次发送（返回 'skipped'），\n   * 避免流式中间帧排队积压导致延迟。\n   *\n   * 注意：finish=true 的最终帧不受此限制，始终保证发送（走正常队列）。\n   *\n   * @param frame - 收到的原始 WebSocket 帧\n   * @param streamId - 流式消息 ID\n   * @param content - 回复内容\n   * @param finish - 是否结束流式消息\n   * @param msgItem - 图文混排项（仅在 finish=true 时有效），用于在结束时附带图片内容\n   * @param feedback - 反馈信息（仅在首次回复时设置）\n   * @returns Promise<WsFrame> 正常发送时返回回执帧，跳过时返回 'skipped'\n   */\n  replyStreamNonBlocking(frame: WsFrameHeaders, streamId: string, content: string, finish: boolean = false, msgItem?: ReplyMsgItem[], feedback?: ReplyFeedback): Promise<WsFrame | 'skipped'> {\n    // finish=true 的最终帧必须发送，不做跳过判断\n    if (!finish && this.hasPendingReplyAck(frame)) {\n      return Promise.resolve('skipped');\n    }\n    return this.replyStream(frame, streamId, content, finish, msgItem, feedback);\n  }\n\n  /**\n   * 获取当前连接状态\n   */\n  get isConnected(): boolean {\n    return this.wsManager.isConnected;\n  }\n\n  /**\n   * 获取 API 客户端实例（供高级用途使用，如文件下载）\n   */\n  get api(): WeComApiClient {\n    return this.apiClient;\n  }\n}\n","/**\n * WeCom 加解密通用核心\n * 独立于 Webhook、WebSocket、Agent 的具体协议形态，统一提供基于 AES-256-CBC \n * 的加解密与 SHA1 签名计算能力。\n */\n\nimport crypto from \"node:crypto\";\n\nconst CRYPTO_CONSTANTS = {\n    /** PKCS#7 块大小 */\n    PKCS7_BLOCK_SIZE: 32,\n    /** AES Key 长度 */\n    AES_KEY_LENGTH: 32,\n} as const;\n\n/**\n * 解码企业微信提供的 Base64 encodingAESKey\n */\nexport function decodeEncodingAESKey(encodingAESKey: string): Buffer {\n    const trimmed = encodingAESKey.trim();\n    if (!trimmed) throw new Error(\"encodingAESKey missing\");\n    const withPadding = trimmed.endsWith(\"=\") ? trimmed : `${trimmed}=`;\n    const key = Buffer.from(withPadding, \"base64\");\n    if (key.length !== CRYPTO_CONSTANTS.AES_KEY_LENGTH) {\n        throw new Error(`invalid encodingAESKey (expected ${CRYPTO_CONSTANTS.AES_KEY_LENGTH} bytes, got ${key.length})`);\n    }\n    return key;\n}\n\n/**\n * PKCS#7 填充\n */\nexport function pkcs7Pad(buf: Buffer, blockSize: number): Buffer {\n    const mod = buf.length % blockSize;\n    const pad = mod === 0 ? blockSize : blockSize - mod;\n    const padByte = Buffer.alloc(1, pad);\n    return Buffer.concat([buf, Buffer.alloc(pad, padByte[0])]);\n}\n\n/**\n * PKCS#7 解除填充\n */\nexport function pkcs7Unpad(buf: Buffer, blockSize: number): Buffer {\n    if (buf.length === 0) throw new Error(\"invalid pkcs7 payload\");\n    const pad = buf[buf.length - 1];\n    if (pad < 1 || pad > blockSize) {\n        throw new Error(\"invalid pkcs7 padding value\");\n    }\n    if (pad > buf.length) {\n        throw new Error(\"invalid pkcs7 payload length\");\n    }\n    for (let i = 0; i < pad; i += 1) {\n        if (buf[buf.length - 1 - i] !== pad) {\n            throw new Error(\"invalid pkcs7 padding byte\");\n        }\n    }\n    return buf.subarray(0, buf.length - pad);\n}\n\n/**\n * 计算 SHA1 哈希\n */\nfunction sha1Hex(input: string): string {\n    return crypto.createHash(\"sha1\").update(input).digest(\"hex\");\n}\n\nexport class WecomCrypto {\n    private aesKey: Buffer;\n    private iv: Buffer;\n\n    constructor(\n        private token: string,\n        private encodingAESKey: string,\n        private receiveId?: string // 对应企业微信的 corpId 或 botId (用于校验与追加)\n    ) {\n        if (!token) throw new Error(\"token is required\");\n        this.aesKey = decodeEncodingAESKey(encodingAESKey);\n        this.iv = this.aesKey.subarray(0, 16);\n    }\n\n    /**\n     * 计算 WeCom 消息签名\n     */\n    public computeSignature(timestamp: string, nonce: string, encrypt: string): string {\n        const parts = [this.token, timestamp, nonce, encrypt]\n            .map((v) => String(v ?? \"\"))\n            .sort();\n        return sha1Hex(parts.join(\"\"));\n    }\n\n    /**\n     * 验证 WeCom 消息签名\n     */\n    public verifySignature(signature: string, timestamp: string, nonce: string, encrypt: string): boolean {\n        const expected = this.computeSignature(timestamp, nonce, encrypt);\n        return expected === signature;\n    }\n\n    /**\n     * 消息解密\n     * 返回纯文本字符串（XML 或 JSON 根据上层业务而定）\n     */\n    public decrypt(encryptText: string): string {\n        const decipher = crypto.createDecipheriv(\"aes-256-cbc\", this.aesKey, this.iv);\n        decipher.setAutoPadding(false);\n        const decryptedPadded = Buffer.concat([\n            decipher.update(Buffer.from(encryptText, \"base64\")),\n            decipher.final(),\n        ]);\n        const decrypted = pkcs7Unpad(decryptedPadded, CRYPTO_CONSTANTS.PKCS7_BLOCK_SIZE);\n\n        if (decrypted.length < 20) {\n            throw new Error(`invalid payload (expected >=20 bytes, got ${decrypted.length})`);\n        }\n\n        // 16 bytes random + 4 bytes length + msg + receiveId\n        const msgLen = decrypted.readUInt32BE(16);\n        const msgStart = 20;\n        const msgEnd = msgStart + msgLen;\n        if (msgEnd > decrypted.length) {\n            throw new Error(`invalid msg length (msgEnd=${msgEnd}, total=${decrypted.length})`);\n        }\n        const msg = decrypted.subarray(msgStart, msgEnd).toString(\"utf8\");\n\n        const receiveId = this.receiveId ?? \"\";\n        if (receiveId) {\n            const trailing = decrypted.subarray(msgEnd).toString(\"utf8\");\n            if (trailing !== receiveId) {\n                throw new Error(`receiveId mismatch (expected \"${receiveId}\", got \"${trailing}\")`);\n            }\n        }\n\n        return msg;\n    }\n\n    /**\n     * 消息加密\n     * 加密明文并返回 base64 格式密文与对应的新签名\n     */\n    public encrypt(plainText: string, timestamp: string, nonce: string): { encrypt: string; signature: string } {\n        const random16 = crypto.randomBytes(16);\n        const msgBuf = Buffer.from(plainText ?? \"\", \"utf8\");\n        const msgLen = Buffer.alloc(4);\n        msgLen.writeUInt32BE(msgBuf.length, 0);\n        const receiveIdBuf = Buffer.from(this.receiveId ?? \"\", \"utf8\");\n\n        const raw = Buffer.concat([random16, msgLen, msgBuf, receiveIdBuf]);\n        const padded = pkcs7Pad(raw, CRYPTO_CONSTANTS.PKCS7_BLOCK_SIZE);\n        \n        const cipher = crypto.createCipheriv(\"aes-256-cbc\", this.aesKey, this.iv);\n        cipher.setAutoPadding(false);\n        const encryptedBuf = Buffer.concat([cipher.update(padded), cipher.final()]);\n        const encryptBase64 = encryptedBuf.toString(\"base64\");\n\n        const signature = this.computeSignature(timestamp, nonce, encryptBase64);\n\n        return { encrypt: encryptBase64, signature };\n    }\n}\n","import { WSClient } from './client';\n\n/** 默认导出 AiBot 命名空间 */\nconst AiBot = {\n  WSClient,\n};\n\nexport default AiBot;\n\n// 同时支持具名导出\nexport { WSClient } from './client';\nexport { WeComApiClient } from './api';\nexport { WsConnectionManager } from './ws';\nexport { MessageHandler } from './message-handler';\nexport { WecomCrypto, decodeEncodingAESKey, pkcs7Pad, pkcs7Unpad } from './wecom-crypto';\nexport { decryptFile } from './crypto';\nexport { DefaultLogger } from './logger';\nexport { generateReqId, generateRandomString } from './utils';\nexport {\n  MessageType,\n  EventType,\n  TemplateCardType,\n  WsCmd,\n  type WSClientOptions,\n  type WSClientEventMap,\n  type BaseMessage,\n  type TextMessage,\n  type ImageMessage,\n  type MixedMessage,\n  type VoiceMessage,\n  type VideoMessage,\n  type FileMessage,\n  type MessageFrom,\n  type TextContent,\n  type ImageContent,\n  type MixedContent,\n  type MixedMsgItem,\n  type VoiceContent,\n  type VideoContent,\n  type FileContent,\n  type QuoteContent,\n  type ReplyOptions,\n  type SendTextParams,\n  type SendMarkdownParams,\n  type WsFrame,\n  type WsFrameHeaders,\n  type StreamReplyBody,\n  type ReplyMsgItem,\n  type ReplyFeedback,\n  type WelcomeTextReplyBody,\n  type WelcomeTemplateCardReplyBody,\n  type WelcomeReplyBody,\n  type TemplateCardMainTitle,\n  type TemplateCardButton,\n  type TemplateCardSource,\n  type TemplateCardActionMenu,\n  type TemplateCardEmphasisContent,\n  type TemplateCardQuoteArea,\n  type TemplateCardHorizontalContent,\n  type TemplateCardJumpAction,\n  type TemplateCardAction,\n  type TemplateCardVerticalContent,\n  type TemplateCardImage,\n  type TemplateCardImageTextArea,\n  type TemplateCardSubmitButton,\n  type TemplateCardSelectionItem,\n  type TemplateCardCheckbox,\n  type TemplateCard,\n  type TemplateCardReplyBody,\n  type StreamWithTemplateCardReplyBody,\n  type UpdateTemplateCardBody,\n  type SendMarkdownMsgBody,\n  type SendTemplateCardMsgBody,\n  type SendMsgBody,\n  type SendMediaMsgBody,\n  type WeComMediaType,\n  type UploadMediaOptions,\n  type UploadMediaInitBody,\n  type UploadMediaInitResult,\n  type UploadMediaChunkBody,\n  type UploadMediaFinishBody,\n  type UploadMediaFinishResult,\n  type EventFrom,\n  type EnterChatEvent,\n  type TemplateCardEventData,\n  type FeedbackEventData,\n  type EventContent,\n  type EventMessage,\n  type EventMessageWith,\n  type Logger,\n  WSAuthFailureError,\n  WSReconnectExhaustedError,\n} from './types';\n"],"names":["crypto"],"mappings":"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"}