@gloablehive/celphone-wechat-plugin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/INSTALL.md +231 -0
  2. package/README.md +259 -0
  3. package/dist/index-simple.js +9 -0
  4. package/dist/index.d.ts +16 -0
  5. package/dist/index.js +77 -0
  6. package/dist/mock-server.d.ts +6 -0
  7. package/dist/mock-server.js +203 -0
  8. package/dist/openclaw.plugin.json +96 -0
  9. package/dist/setup-entry.d.ts +9 -0
  10. package/dist/setup-entry.js +8 -0
  11. package/dist/src/cache/compactor.d.ts +36 -0
  12. package/dist/src/cache/compactor.js +154 -0
  13. package/dist/src/cache/extractor.d.ts +48 -0
  14. package/dist/src/cache/extractor.js +120 -0
  15. package/dist/src/cache/index.d.ts +15 -0
  16. package/dist/src/cache/index.js +16 -0
  17. package/dist/src/cache/indexer.d.ts +41 -0
  18. package/dist/src/cache/indexer.js +262 -0
  19. package/dist/src/cache/manager.d.ts +113 -0
  20. package/dist/src/cache/manager.js +271 -0
  21. package/dist/src/cache/message-queue.d.ts +59 -0
  22. package/dist/src/cache/message-queue.js +147 -0
  23. package/dist/src/cache/saas-connector.d.ts +94 -0
  24. package/dist/src/cache/saas-connector.js +289 -0
  25. package/dist/src/cache/syncer.d.ts +60 -0
  26. package/dist/src/cache/syncer.js +177 -0
  27. package/dist/src/cache/types.d.ts +198 -0
  28. package/dist/src/cache/types.js +43 -0
  29. package/dist/src/cache/writer.d.ts +81 -0
  30. package/dist/src/cache/writer.js +461 -0
  31. package/dist/src/channel.d.ts +65 -0
  32. package/dist/src/channel.js +334 -0
  33. package/dist/src/client.d.ts +280 -0
  34. package/dist/src/client.js +248 -0
  35. package/index-simple.ts +11 -0
  36. package/index.ts +89 -0
  37. package/mock-server.ts +237 -0
  38. package/openclaw.plugin.json +98 -0
  39. package/package.json +37 -0
  40. package/setup-entry.ts +10 -0
  41. package/src/channel.ts +398 -0
  42. package/src/client.ts +412 -0
  43. package/test-cache.ts +260 -0
  44. package/test-integration.ts +319 -0
  45. package/tsconfig.json +22 -0
@@ -0,0 +1,334 @@
1
+ /**
2
+ * WorkPhone WeChat Channel Plugin for OpenClaw
3
+ *
4
+ * This channel plugin connects OpenClaw to WorkPhone's WeChat API,
5
+ * enabling sending and receiving WeChat messages through the WorkPhone platform.
6
+ *
7
+ * IMPORTANT - Human Account Model:
8
+ * Unlike Telegram/WhatsApp bots, this connects to a real human WeChat account.
9
+ * The agent communicates with ALL friends and groups under that WeChat account,
10
+ * not just one DM context. This is "human mode" vs "bot mode".
11
+ *
12
+ * Includes Local Cache:
13
+ * - Per-account, per-user/conversation MD files
14
+ * - YAML frontmatter (aligned with Claude Code)
15
+ * - MEMORY.md indexing
16
+ * - 4-layer compression
17
+ * - AI summary extraction
18
+ * - SAAS connectivity + offline fallback
19
+ * - Cloud sync
20
+ */
21
+ import { createChatChannelPlugin, createChannelPluginBase, } from "openclaw/plugin-sdk/core";
22
+ import { createWorkPhoneClient } from "./client.js";
23
+ // Import cache modules
24
+ import { createCacheManager, } from "./cache/index.js";
25
+ // Cache manager instance (lazy initialized)
26
+ let cacheManager = null;
27
+ /**
28
+ * Get or create cache manager
29
+ */
30
+ function getCacheManager(cfg) {
31
+ if (cacheManager)
32
+ return cacheManager;
33
+ const section = cfg.channels?.["celphone-wechat"];
34
+ const accounts = (section?.accounts || []);
35
+ // If no accounts configured, create default from main config
36
+ if (accounts.length === 0 && section?.wechatAccountId) {
37
+ accounts.push({
38
+ accountId: section.accountId || 'default',
39
+ wechatAccountId: section.wechatAccountId,
40
+ wechatId: section.wechatId || section.wechatAccountId,
41
+ nickName: section.nickName || 'WeChat User',
42
+ enabled: true,
43
+ });
44
+ }
45
+ const basePath = globalThis?.process?.env?.OPENCLAW_CACHE_PATH
46
+ || '~/.openclaw/channels/celphone-wechat';
47
+ cacheManager = createCacheManager({
48
+ basePath,
49
+ accounts,
50
+ saasConfig: section?.saas ? {
51
+ apiBaseUrl: section.saas.apiBaseUrl,
52
+ apiKey: section.saas.apiKey,
53
+ timeout: section.saas.timeout || 5000,
54
+ } : undefined,
55
+ syncConfig: section?.sync ? {
56
+ databaseUrl: section.sync.databaseUrl,
57
+ syncMode: section.sync.syncMode || 'interval',
58
+ syncIntervalMs: section.sync.syncIntervalMs || 5 * 60 * 1000,
59
+ } : undefined,
60
+ });
61
+ // Initialize cache manager
62
+ cacheManager.init().catch(err => {
63
+ console.error('[CelPhoneWeChat] Cache manager init failed:', err);
64
+ });
65
+ return cacheManager;
66
+ }
67
+ /**
68
+ * Resolve account from OpenClaw config
69
+ *
70
+ * Note: This is a "human account" model - the WeChat account represents
71
+ * a real person with all their friends and groups, not a bot.
72
+ */
73
+ function resolveAccount(cfg, accountId) {
74
+ const section = cfg.channels?.["celphone-wechat"];
75
+ const apiKey = section?.apiKey;
76
+ const baseUrl = section?.baseUrl || "https://api.workphone.example.com";
77
+ const wechatAccountId = section?.wechatAccountId;
78
+ if (!apiKey) {
79
+ throw new Error("celphone-wechat: apiKey is required");
80
+ }
81
+ if (!wechatAccountId) {
82
+ throw new Error("celphone-wechat: wechatAccountId is required (the WeChat account to use)");
83
+ }
84
+ return {
85
+ accountId: accountId ?? null,
86
+ apiKey,
87
+ baseUrl,
88
+ wechatAccountId,
89
+ wechatId: section?.wechatId || wechatAccountId, // Actual WeChat ID (wxid_xxx)
90
+ nickName: section?.nickName || "WeChat User", // Display name
91
+ allowFrom: section?.allowFrom ?? [],
92
+ dmPolicy: section?.dmSecurity,
93
+ };
94
+ }
95
+ /**
96
+ * Create the channel plugin
97
+ */
98
+ export const celPhoneWeChatPlugin = createChatChannelPlugin({
99
+ base: createChannelPluginBase({
100
+ id: "celphone-wechat",
101
+ setup: {
102
+ resolveAccount,
103
+ inspectAccount(cfg, accountId) {
104
+ const section = cfg.channels?.["celphone-wechat"];
105
+ const hasApiKey = Boolean(section?.apiKey);
106
+ return {
107
+ enabled: hasApiKey,
108
+ configured: hasApiKey,
109
+ tokenStatus: hasApiKey ? "available" : "missing",
110
+ };
111
+ },
112
+ },
113
+ }),
114
+ // DM security: who can message the bot
115
+ security: {
116
+ dm: {
117
+ channelKey: "celphone-wechat",
118
+ resolvePolicy: (account) => account.dmPolicy,
119
+ resolveAllowFrom: (account) => account.allowFrom,
120
+ defaultPolicy: "allowlist", // Default to allowlist for security
121
+ },
122
+ },
123
+ // Pairing: not currently supported for this channel
124
+ // WorkPhone WeChat doesn't have a standard pairing flow
125
+ // pairing: { ... },
126
+ // Threading: how replies are delivered
127
+ // For WeChat, replies go back to the same chat (friend or chatroom)
128
+ threading: {
129
+ topLevelReplyToMode: "reply", // Reply to the last message in the thread
130
+ },
131
+ // Outbound: send messages to WeChat via WorkPhone API
132
+ //
133
+ // HUMAN ACCOUNT MODEL IMPORTANT:
134
+ // This channel connects to a real person's WeChat account.
135
+ // The agent needs to communicate with ALL their friends and groups,
136
+ // not just one conversation. We distinguish by conversation type:
137
+ // - DM (direct): friendWechatId in params.to
138
+ // - Group chat: chatroomId in params.to (detect by format or metadata)
139
+ outbound: {
140
+ attachedResults: {
141
+ // Send text - detect if DM or group based on conversation metadata
142
+ sendText: async (params) => {
143
+ const client = createWorkPhoneClient({
144
+ baseUrl: params.account.baseUrl,
145
+ apiKey: params.account.apiKey,
146
+ accountId: params.account.accountId || undefined,
147
+ wechatAccountId: params.account.wechatAccountId,
148
+ });
149
+ // Check if this is a group message (chatroom)
150
+ // Chatroom IDs typically start with certain prefix or have specific format
151
+ const isChatroom = params.metadata?.conversationType === 'group' ||
152
+ (params.to && params.to.includes('@chatroom'));
153
+ let result;
154
+ if (isChatroom) {
155
+ // Send to chatroom (group)
156
+ result = await client.sendChatroomMessage({
157
+ wechatAccountId: params.account.wechatAccountId,
158
+ chatroomId: params.to,
159
+ content: params.text,
160
+ type: 'text',
161
+ });
162
+ }
163
+ else {
164
+ // Send to friend (DM)
165
+ result = await client.sendFriendMessage({
166
+ wechatAccountId: params.account.wechatAccountId,
167
+ friendWechatId: params.to,
168
+ content: params.text,
169
+ type: 'text',
170
+ });
171
+ }
172
+ return { messageId: result.messageId };
173
+ },
174
+ // Send media - also support both DM and group
175
+ sendMedia: async (params) => {
176
+ const client = createWorkPhoneClient({
177
+ baseUrl: params.account.baseUrl,
178
+ apiKey: params.account.apiKey,
179
+ accountId: params.account.accountId || undefined,
180
+ wechatAccountId: params.account.wechatAccountId,
181
+ });
182
+ const isChatroom = params.metadata?.conversationType === 'group' ||
183
+ (params.to && params.to.includes('@chatroom'));
184
+ let result;
185
+ if (isChatroom) {
186
+ result = await client.sendChatroomMessage({
187
+ wechatAccountId: params.account.wechatAccountId,
188
+ chatroomId: params.to,
189
+ content: params.filePath || '',
190
+ type: 'file',
191
+ });
192
+ }
193
+ else {
194
+ result = await client.sendFriendMessage({
195
+ wechatAccountId: params.account.wechatAccountId,
196
+ friendWechatId: params.to,
197
+ content: params.filePath || '',
198
+ type: 'file',
199
+ });
200
+ }
201
+ return { messageId: result.messageId };
202
+ },
203
+ },
204
+ // Additional outbound handlers can be added here for:
205
+ // - sendLink: Send link cards
206
+ // - sendLocation: Send location
207
+ // - sendContact: Send contact card
208
+ },
209
+ // Additional capabilities
210
+ // - Describe the channel's message types and features
211
+ capabilities: {
212
+ supportedMessageTypes: [
213
+ "text",
214
+ "image",
215
+ "video",
216
+ "file",
217
+ "link",
218
+ "location",
219
+ "contact",
220
+ ],
221
+ maxAttachmentSize: 25 * 1024 * 1024, // 25MB
222
+ supportsMarkdown: false, // WeChat uses a limited markup
223
+ supportsHtml: false,
224
+ supportsEmoji: true,
225
+ supportsReactions: false, // WeChat doesn't support reactions
226
+ supportsThreads: true, // Can reply in chat
227
+ supportsEditing: false, // Cannot edit sent messages
228
+ supportsDeleting: false, // Cannot delete sent messages
229
+ },
230
+ });
231
+ /**
232
+ * Helper function to handle inbound webhook messages
233
+ * This should be called from your HTTP route handler
234
+ *
235
+ * Integrates with Cache Manager for:
236
+ * - Local MD file caching
237
+ * - User profile storage
238
+ * - Session memory
239
+ * - Cloud sync
240
+ * - Offline fallback
241
+ */
242
+ export async function handleInboundMessage(api, payload, cfg) {
243
+ const { event, accountId, wechatAccountId, message, friendRequest } = payload;
244
+ if (event === 'message' && message) {
245
+ // Determine conversation type
246
+ const isChatroom = !!message.chatroomId;
247
+ const conversationId = isChatroom
248
+ ? message.chatroomId
249
+ : message.fromUser || message.toUser || '';
250
+ // Convert to cache format and store locally
251
+ if (cacheManager && accountId) {
252
+ try {
253
+ await cacheManager.onMessage({
254
+ messageId: message.messageId,
255
+ msgSvrId: message.msgSvrId,
256
+ accountId: accountId,
257
+ conversationType: isChatroom ? 'chatroom' : 'friend',
258
+ conversationId,
259
+ senderId: message.fromUser || '',
260
+ content: message.content,
261
+ messageType: message.type || 1,
262
+ timestamp: message.timestamp || Date.now(),
263
+ isSelf: message.isSelf || false,
264
+ direction: message.isSelf ? 'outbound' : 'inbound',
265
+ });
266
+ }
267
+ catch (err) {
268
+ console.error('[CelPhoneWeChat] Cache write failed:', err);
269
+ }
270
+ }
271
+ // Convert WorkPhone message format to OpenClaw format
272
+ const openclawMessage = {
273
+ id: message.messageId,
274
+ rawId: message.msgSvrId || message.messageId,
275
+ conversation: {
276
+ type: isChatroom ? 'group' : 'dm',
277
+ id: conversationId,
278
+ chatroomId: isChatroom ? conversationId : undefined,
279
+ },
280
+ sender: {
281
+ id: message.fromUser || '',
282
+ platformId: message.wechatId,
283
+ },
284
+ content: {
285
+ type: message.type === 1 ? 'text' : 'media',
286
+ text: message.content,
287
+ },
288
+ timestamp: new Date(message.timestamp || Date.now()),
289
+ isSelf: message.isSelf || false,
290
+ };
291
+ // Dispatch to OpenClaw
292
+ await api.inbound.dispatchMessage(openclawMessage);
293
+ }
294
+ else if (event === 'friend_request' && friendRequest) {
295
+ // Handle friend request
296
+ await api.inbound.dispatchFriendRequest({
297
+ id: friendRequest.v1,
298
+ platformId: friendRequest.fromUser,
299
+ scene: friendRequest.scene,
300
+ ticket: friendRequest.ticket,
301
+ accountId,
302
+ wechatAccountId,
303
+ });
304
+ }
305
+ }
306
+ /**
307
+ * Get user profile from cache (for agent use)
308
+ */
309
+ export async function getUserProfile(accountId, wechatId) {
310
+ if (!cacheManager)
311
+ return null;
312
+ return await cacheManager.getProfile(accountId, wechatId);
313
+ }
314
+ /**
315
+ * Update user profile in cache
316
+ */
317
+ export async function updateUserProfile(accountId, wechatId, updates) {
318
+ if (!cacheManager)
319
+ return;
320
+ await cacheManager.updateProfile(accountId, wechatId, updates);
321
+ }
322
+ /**
323
+ * Get SAAS connection status
324
+ */
325
+ export function getConnectionStatus() {
326
+ return cacheManager?.getConnectionStatus();
327
+ }
328
+ /**
329
+ * Check if system is online (SAAS connected)
330
+ */
331
+ export function isOnline() {
332
+ return cacheManager?.isSAASOnline() ?? false;
333
+ }
334
+ export default celPhoneWeChatPlugin;
@@ -0,0 +1,280 @@
1
+ /**
2
+ * WorkPhone WeChat API Client
3
+ *
4
+ * Interfaces with the WorkPhone API for sending/receiving WeChat messages
5
+ * Based on the Apifox API manual: data/apifox-workphone-3/
6
+ */
7
+ export interface WorkPhoneConfig {
8
+ baseUrl: string;
9
+ apiKey: string;
10
+ accountId?: string;
11
+ wechatAccountId?: string;
12
+ }
13
+ export interface WeChatFriend {
14
+ wechatFriendId: string;
15
+ wechatId: string;
16
+ nickName: string;
17
+ remark: string;
18
+ avatar?: string;
19
+ label?: string[];
20
+ phones?: string[];
21
+ }
22
+ export interface WeChatChatroom {
23
+ wechatChatroomId: string;
24
+ chatroomId: string;
25
+ name: string;
26
+ ownerId: string;
27
+ memberCount: number;
28
+ }
29
+ export interface WeChatMessage {
30
+ messageId: string;
31
+ msgSvrId?: string;
32
+ wechatId: string;
33
+ content: string;
34
+ type: number;
35
+ timestamp: number;
36
+ isSelf: boolean;
37
+ fromUser?: string;
38
+ toUser?: string;
39
+ }
40
+ export interface SendMessageParams {
41
+ wechatAccountId: string;
42
+ toUser: string;
43
+ content: string;
44
+ type?: 'text' | 'image' | 'video' | 'file' | 'link' | 'card';
45
+ }
46
+ export interface SendMessageResult {
47
+ messageId: string;
48
+ msgSvrId?: string;
49
+ success: boolean;
50
+ }
51
+ export interface WebhookPayload {
52
+ event: 'message' | 'friend_request' | 'group_invite' | 'system';
53
+ accountId: string;
54
+ wechatAccountId: string;
55
+ message?: WeChatMessage;
56
+ friendRequest?: {
57
+ v1: string;
58
+ scene: number;
59
+ fromUser: string;
60
+ ticket?: string;
61
+ };
62
+ timestamp: number;
63
+ }
64
+ export declare class WorkPhoneWeChatClient {
65
+ private config;
66
+ constructor(config: WorkPhoneConfig);
67
+ private request;
68
+ /**
69
+ * Get all WeChat accounts for an account
70
+ * GET /api/v1/accounts/{accountId}/wechatAccounts
71
+ */
72
+ getWeChatAccounts(accountId: string): Promise<WeChatFriend[]>;
73
+ /**
74
+ * Get WeChat account info by wechatId
75
+ * GET /wp/api/v1/wechatAccounts/{wechatId}/byWechatId
76
+ */
77
+ getWeChatAccountById(wechatId: string): Promise<any>;
78
+ /**
79
+ * Get all friends for a WeChat account
80
+ * GET /wp/api/v1/wechatAccounts/{wechatAccountId}/friends
81
+ */
82
+ getFriends(wechatAccountId: string, options?: {
83
+ page?: number;
84
+ pageSize?: number;
85
+ labelId?: string;
86
+ }): Promise<{
87
+ list: WeChatFriend[];
88
+ total: number;
89
+ }>;
90
+ /**
91
+ * Search friends
92
+ * GET /wp/api/v1/wechatFriends
93
+ */
94
+ searchFriends(params: {
95
+ accountId?: string;
96
+ wechatAccountId?: string;
97
+ keyword?: string;
98
+ }): Promise<WeChatFriend[]>;
99
+ /**
100
+ * Get friend by ID
101
+ * GET /wp/api/v1/wechatFriends/{wechatFriendId}
102
+ */
103
+ getFriend(wechatFriendId: string): Promise<WeChatFriend>;
104
+ /**
105
+ * Add friend (send friend request)
106
+ * POST /wp/api/v1/wechatFriends/addFriend
107
+ */
108
+ addFriend(params: {
109
+ wechatAccountId: string;
110
+ v1: string;
111
+ verifyMessage?: string;
112
+ scene?: number;
113
+ }): Promise<{
114
+ success: boolean;
115
+ taskId?: string;
116
+ }>;
117
+ /**
118
+ * Accept friend request
119
+ * POST /wp/api/v1/wechatFriends/{wechatFriendId}/acceptFriend
120
+ */
121
+ acceptFriend(wechatFriendId: string): Promise<{
122
+ success: boolean;
123
+ }>;
124
+ /**
125
+ * Update friend remark
126
+ * PUT /wp/api/v1/wechatFriends/{wechatFriendId}/remark
127
+ */
128
+ updateFriendRemark(wechatFriendId: string, remark: string): Promise<{
129
+ success: boolean;
130
+ }>;
131
+ /**
132
+ * Update friend labels
133
+ * PUT /wp/api/v1/wechatFriends/{wechatFriendId}/label
134
+ */
135
+ updateFriendLabels(wechatFriendId: string, labelIds: string[]): Promise<{
136
+ success: boolean;
137
+ }>;
138
+ /**
139
+ * Get all chatrooms for a WeChat account
140
+ * GET /wp/api/v1/wechatAccounts/{wechatAccountId}/chatrooms
141
+ */
142
+ getChatrooms(wechatAccountId: string): Promise<WeChatChatroom[]>;
143
+ /**
144
+ * Get chatroom info by chatroomId
145
+ * GET /wp/api/v1/wechatChatrooms/{wechatChatroomId}
146
+ */
147
+ getChatroom(wechatChatroomId: string): Promise<WeChatChatroom>;
148
+ /**
149
+ * Update chatroom name (announcement)
150
+ * PUT /wp/api/v1/wechatChatrooms/{wechatChatroomId}/chatroomName
151
+ */
152
+ updateChatroomName(wechatChatroomId: string, name: string): Promise<{
153
+ success: boolean;
154
+ }>;
155
+ /**
156
+ * Publish chatroom announcement
157
+ * PUT /api/v1/wechat/chatroom/announcement
158
+ */
159
+ publishChatroomAnnouncement(wechatChatroomId: string, content: string): Promise<{
160
+ success: boolean;
161
+ }>;
162
+ /**
163
+ * Get friend messages (1-on-1 chat)
164
+ * GET /wp/api/v1/wechat/friendMessages
165
+ */
166
+ getFriendMessages(params: {
167
+ wechatAccountId: string;
168
+ friendWechatId: string;
169
+ startTime?: number;
170
+ endTime?: number;
171
+ limit?: number;
172
+ offset?: number;
173
+ }): Promise<{
174
+ list: WeChatMessage[];
175
+ total: number;
176
+ }>;
177
+ /**
178
+ * Get chatroom messages (group chat)
179
+ * GET /wp/api/v1/wechat/chatroomMessages
180
+ */
181
+ getChatroomMessages(params: {
182
+ wechatAccountId: string;
183
+ chatroomId: string;
184
+ startTime?: number;
185
+ endTime?: number;
186
+ limit?: number;
187
+ offset?: number;
188
+ }): Promise<{
189
+ list: WeChatMessage[];
190
+ total: number;
191
+ }>;
192
+ /**
193
+ * Send friend message (1-on-1)
194
+ * POST /wp/api/v1/wechat/friendMessages
195
+ */
196
+ sendFriendMessage(params: {
197
+ wechatAccountId: string;
198
+ friendWechatId: string;
199
+ content: string;
200
+ type?: 'text' | 'image' | 'video' | 'file' | 'link';
201
+ }): Promise<SendMessageResult>;
202
+ /**
203
+ * Send chatroom message (group)
204
+ * POST /wp/api/v1/wechat/chatroomMessages
205
+ */
206
+ sendChatroomMessage(params: {
207
+ wechatAccountId: string;
208
+ chatroomId: string;
209
+ content: string;
210
+ type?: 'text' | 'image' | 'video' | 'file' | 'link';
211
+ atUsers?: string[];
212
+ }): Promise<SendMessageResult>;
213
+ /**
214
+ * Get moments
215
+ * GET /wp/api/v1/moments
216
+ */
217
+ getMoments(params: {
218
+ wechatAccountId: string;
219
+ startTime?: number;
220
+ endTime?: number;
221
+ limit?: number;
222
+ }): Promise<{
223
+ list: any[];
224
+ total: number;
225
+ }>;
226
+ /**
227
+ * Publish moment (post to Moments)
228
+ * POST /wp/api/v1/moments
229
+ */
230
+ publishMoment(params: {
231
+ wechatAccountId: string;
232
+ content: string;
233
+ images?: string[];
234
+ videos?: string[];
235
+ location?: {
236
+ lat: number;
237
+ lng: number;
238
+ name: string;
239
+ };
240
+ }): Promise<{
241
+ momentId: string;
242
+ success: boolean;
243
+ }>;
244
+ /**
245
+ * Comment on a moment
246
+ * POST /wp/api/v1/moments/{momentId}/comment
247
+ */
248
+ commentMoment(momentId: string, content: string, replyCommentId?: string): Promise<{
249
+ success: boolean;
250
+ }>;
251
+ /**
252
+ * Like a moment
253
+ * POST /wp/api/v1/moments/{momentId}/like
254
+ */
255
+ likeMoment(momentId: string): Promise<{
256
+ success: boolean;
257
+ }>;
258
+ /**
259
+ * Download friend message file
260
+ */
261
+ downloadFriendFile(messageId: string, wechatTime: number): Promise<Blob>;
262
+ /**
263
+ * Download chatroom message file
264
+ */
265
+ downloadChatroomFile(messageId: string, wechatTime: number): Promise<Blob>;
266
+ /**
267
+ * Parse webhook payload from WorkPhone callback
268
+ * This should be called by your webhook endpoint handler
269
+ */
270
+ parseWebhookPayload(payload: any): WebhookPayload | null;
271
+ }
272
+ /**
273
+ * Factory function to create a WorkPhone client from OpenClaw config
274
+ */
275
+ export declare function createWorkPhoneClient(config: {
276
+ baseUrl: string;
277
+ apiKey: string;
278
+ accountId?: string;
279
+ wechatAccountId?: string;
280
+ }): WorkPhoneWeChatClient;