@xpert-ai/plugin-community-wechat 0.1.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.
- package/README.md +353 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +139 -0
- package/dist/lib/constants.d.ts +23 -0
- package/dist/lib/constants.js +23 -0
- package/dist/lib/conversation-user-key.d.ts +13 -0
- package/dist/lib/conversation-user-key.js +28 -0
- package/dist/lib/conversation.service.d.ts +215 -0
- package/dist/lib/conversation.service.js +1179 -0
- package/dist/lib/decorators.d.ts +2 -0
- package/dist/lib/decorators.js +3 -0
- package/dist/lib/entities/index.d.ts +4 -0
- package/dist/lib/entities/index.js +4 -0
- package/dist/lib/entities/wechat-personal-account.entity.d.ts +19 -0
- package/dist/lib/entities/wechat-personal-account.entity.js +83 -0
- package/dist/lib/entities/wechat-personal-conversation-binding.entity.d.ts +14 -0
- package/dist/lib/entities/wechat-personal-conversation-binding.entity.js +65 -0
- package/dist/lib/entities/wechat-personal-message-log.entity.d.ts +27 -0
- package/dist/lib/entities/wechat-personal-message-log.entity.js +108 -0
- package/dist/lib/entities/wechat-personal-trigger-binding.entity.d.ts +17 -0
- package/dist/lib/entities/wechat-personal-trigger-binding.entity.js +71 -0
- package/dist/lib/handoff/index.d.ts +4 -0
- package/dist/lib/handoff/index.js +4 -0
- package/dist/lib/handoff/wechat-personal-chat-callback.processor.d.ts +26 -0
- package/dist/lib/handoff/wechat-personal-chat-callback.processor.js +312 -0
- package/dist/lib/handoff/wechat-personal-chat-dispatch.service.d.ts +26 -0
- package/dist/lib/handoff/wechat-personal-chat-dispatch.service.js +187 -0
- package/dist/lib/handoff/wechat-personal-chat-run-state.service.d.ts +21 -0
- package/dist/lib/handoff/wechat-personal-chat-run-state.service.js +39 -0
- package/dist/lib/handoff/wechat-personal-chat.types.d.ts +69 -0
- package/dist/lib/handoff/wechat-personal-chat.types.js +2 -0
- package/dist/lib/message.d.ts +49 -0
- package/dist/lib/message.js +64 -0
- package/dist/lib/remote-components/wechat-personal-workbench/app.js +1831 -0
- package/dist/lib/tokens.d.ts +1 -0
- package/dist/lib/tokens.js +1 -0
- package/dist/lib/types.d.ts +48 -0
- package/dist/lib/types.js +365 -0
- package/dist/lib/views/wechat-personal-view.provider.d.ts +17 -0
- package/dist/lib/views/wechat-personal-view.provider.js +441 -0
- package/dist/lib/wechat-personal-channel.strategy.d.ts +33 -0
- package/dist/lib/wechat-personal-channel.strategy.js +197 -0
- package/dist/lib/wechat-personal-integration.strategy.d.ts +56 -0
- package/dist/lib/wechat-personal-integration.strategy.js +217 -0
- package/dist/lib/wechat-personal.client.d.ts +29 -0
- package/dist/lib/wechat-personal.client.js +146 -0
- package/dist/lib/wechat-personal.controller.d.ts +50 -0
- package/dist/lib/wechat-personal.controller.js +270 -0
- package/dist/lib/wechat-personal.middleware.d.ts +20 -0
- package/dist/lib/wechat-personal.middleware.js +267 -0
- package/dist/lib/wechat-personal.plugin.d.ts +2 -0
- package/dist/lib/wechat-personal.plugin.js +58 -0
- package/dist/lib/wechat-personal.templates.d.ts +2 -0
- package/dist/lib/wechat-personal.templates.js +100 -0
- package/dist/lib/workflow/index.d.ts +5 -0
- package/dist/lib/workflow/index.js +5 -0
- package/dist/lib/workflow/wechat-personal-trigger-aggregation.service.d.ts +10 -0
- package/dist/lib/workflow/wechat-personal-trigger-aggregation.service.js +39 -0
- package/dist/lib/workflow/wechat-personal-trigger-aggregation.types.d.ts +30 -0
- package/dist/lib/workflow/wechat-personal-trigger-aggregation.types.js +2 -0
- package/dist/lib/workflow/wechat-personal-trigger-flush.processor.d.ts +8 -0
- package/dist/lib/workflow/wechat-personal-trigger-flush.processor.js +39 -0
- package/dist/lib/workflow/wechat-personal-trigger.strategy.d.ts +65 -0
- package/dist/lib/workflow/wechat-personal-trigger.strategy.js +511 -0
- package/dist/lib/workflow/wechat-personal-trigger.types.d.ts +10 -0
- package/dist/lib/workflow/wechat-personal-trigger.types.js +2 -0
- package/dist/xpert-wechat-personal-admin-assistant.yaml +103 -0
- package/dist/xpert-wechat-personal-user-assistant.yaml +127 -0
- package/package.json +79 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WECHAT_PERSONAL_PLUGIN_CONTEXT: unique symbol;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const WECHAT_PERSONAL_PLUGIN_CONTEXT = Symbol('WECHAT_PERSONAL_PLUGIN_CONTEXT');
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type WechatPersonalGroupTriggerMode = 'mention_or_keywords' | 'all' | 'mentions' | 'keywords' | 'off';
|
|
2
|
+
export interface TIntegrationWechatPersonalOptions {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
apiVersion?: string;
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
apiToken?: string;
|
|
7
|
+
preferLanguage?: 'en' | 'zh-Hans';
|
|
8
|
+
callbackSecret?: string;
|
|
9
|
+
groupTriggerMode?: WechatPersonalGroupTriggerMode;
|
|
10
|
+
groupKeywords?: string[];
|
|
11
|
+
ignoreSelfMessages?: boolean;
|
|
12
|
+
fallbackToLegacySendText?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface WechatPersonalInboundEvent {
|
|
15
|
+
source: 'legacy_callback' | 'message_webhook';
|
|
16
|
+
uuid: string;
|
|
17
|
+
ownerWxid?: string;
|
|
18
|
+
ownerName?: string;
|
|
19
|
+
contactId: string;
|
|
20
|
+
contactName?: string;
|
|
21
|
+
senderId: string;
|
|
22
|
+
senderName?: string;
|
|
23
|
+
chatId: string;
|
|
24
|
+
chatType: 'private' | 'group';
|
|
25
|
+
messageId: string;
|
|
26
|
+
msgType?: number;
|
|
27
|
+
content: string;
|
|
28
|
+
displayText?: string;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
isSelf: boolean;
|
|
31
|
+
raw: Record<string, unknown>;
|
|
32
|
+
rawPayload: unknown;
|
|
33
|
+
}
|
|
34
|
+
export interface WechatPersonalDispatchableMessage extends WechatPersonalInboundEvent {
|
|
35
|
+
input: string;
|
|
36
|
+
triggerReason: 'private' | 'group_all' | 'mention' | 'keyword';
|
|
37
|
+
}
|
|
38
|
+
export declare function isWechatPersonalProviderValue(value: unknown): boolean;
|
|
39
|
+
export declare function normalizeApiVersion(value: unknown): string;
|
|
40
|
+
export declare function normalizeBaseUrl(value: unknown): string;
|
|
41
|
+
export declare function normalizeTimeoutMs(value: unknown, defaultValue?: number): number;
|
|
42
|
+
export declare function normalizeString(value: unknown): string;
|
|
43
|
+
export declare function normalizeBoolean(value: unknown): boolean;
|
|
44
|
+
export declare function normalizeGroupTriggerMode(value: unknown): WechatPersonalGroupTriggerMode;
|
|
45
|
+
export declare function normalizeKeywords(value: unknown): string[];
|
|
46
|
+
export declare function normalizeWechatPersonalInboundPayload(payload: unknown): WechatPersonalInboundEvent | null;
|
|
47
|
+
export declare function shouldDispatchWechatPersonalMessage(event: WechatPersonalInboundEvent, options?: Pick<TIntegrationWechatPersonalOptions, 'ignoreSelfMessages' | 'groupTriggerMode' | 'groupKeywords'>): WechatPersonalDispatchableMessage | null;
|
|
48
|
+
export declare function summarizePayload(payload: unknown, maxLength?: number): string;
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { WECHAT_PERSONAL_PROVIDER_KEY } from './constants.js';
|
|
2
|
+
export function isWechatPersonalProviderValue(value) {
|
|
3
|
+
return value === WECHAT_PERSONAL_PROVIDER_KEY;
|
|
4
|
+
}
|
|
5
|
+
export function normalizeApiVersion(value) {
|
|
6
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
7
|
+
return '/v1/';
|
|
8
|
+
}
|
|
9
|
+
let text = value.trim();
|
|
10
|
+
if (!text.startsWith('/')) {
|
|
11
|
+
text = `/${text}`;
|
|
12
|
+
}
|
|
13
|
+
if (!text.endsWith('/')) {
|
|
14
|
+
text = `${text}/`;
|
|
15
|
+
}
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
export function normalizeBaseUrl(value) {
|
|
19
|
+
if (typeof value !== 'string') {
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
return value.trim().replace(/\/+$/, '');
|
|
23
|
+
}
|
|
24
|
+
export function normalizeTimeoutMs(value, defaultValue = 10000) {
|
|
25
|
+
if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
|
|
26
|
+
return Math.floor(value);
|
|
27
|
+
}
|
|
28
|
+
return defaultValue;
|
|
29
|
+
}
|
|
30
|
+
export function normalizeString(value) {
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
return value.trim();
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
35
|
+
return String(value);
|
|
36
|
+
}
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
export function normalizeBoolean(value) {
|
|
40
|
+
if (typeof value === 'boolean') {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === 'string') {
|
|
44
|
+
return ['true', '1', 'yes'].includes(value.trim().toLowerCase());
|
|
45
|
+
}
|
|
46
|
+
if (typeof value === 'number') {
|
|
47
|
+
return value !== 0;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
export function normalizeGroupTriggerMode(value) {
|
|
52
|
+
if (value === 'mention_or_keywords' ||
|
|
53
|
+
value === 'all' ||
|
|
54
|
+
value === 'mentions' ||
|
|
55
|
+
value === 'keywords' ||
|
|
56
|
+
value === 'off') {
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
return 'mention_or_keywords';
|
|
60
|
+
}
|
|
61
|
+
export function normalizeKeywords(value) {
|
|
62
|
+
if (Array.isArray(value)) {
|
|
63
|
+
return value.map((item) => normalizeString(item)).filter(Boolean);
|
|
64
|
+
}
|
|
65
|
+
if (typeof value === 'string') {
|
|
66
|
+
return value
|
|
67
|
+
.split(/[,\n,]/)
|
|
68
|
+
.map((item) => item.trim())
|
|
69
|
+
.filter(Boolean);
|
|
70
|
+
}
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
export function normalizeWechatPersonalInboundPayload(payload) {
|
|
74
|
+
const record = asRecord(payload);
|
|
75
|
+
if (!record) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (asRecord(record.message)) {
|
|
79
|
+
return normalizeLegacyCallback(record, payload);
|
|
80
|
+
}
|
|
81
|
+
if (normalizeString(record.uuid || record.UUID) && normalizeString(record.contactid || record.Contactid)) {
|
|
82
|
+
return normalizeMessageWebhook(record, payload);
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
export function shouldDispatchWechatPersonalMessage(event, options) {
|
|
87
|
+
if ((options?.ignoreSelfMessages ?? true) && event.isSelf) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (!isTextLikeMessage(event.msgType)) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const input = normalizeAgentInput(event);
|
|
94
|
+
if (!input) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
if (event.chatType !== 'group') {
|
|
98
|
+
return {
|
|
99
|
+
...event,
|
|
100
|
+
input,
|
|
101
|
+
triggerReason: 'private'
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const mode = normalizeGroupTriggerMode(options?.groupTriggerMode);
|
|
105
|
+
if (mode === 'off') {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
if (mode === 'all') {
|
|
109
|
+
return {
|
|
110
|
+
...event,
|
|
111
|
+
input,
|
|
112
|
+
triggerReason: 'group_all'
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const mentioned = isMentioned(event);
|
|
116
|
+
const keyword = matchKeyword(input, normalizeKeywords(options?.groupKeywords));
|
|
117
|
+
if ((mode === 'mentions' || mode === 'mention_or_keywords') && mentioned) {
|
|
118
|
+
return {
|
|
119
|
+
...event,
|
|
120
|
+
input: stripLeadingMention(input),
|
|
121
|
+
triggerReason: 'mention'
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if ((mode === 'keywords' || mode === 'mention_or_keywords') && keyword) {
|
|
125
|
+
return {
|
|
126
|
+
...event,
|
|
127
|
+
input,
|
|
128
|
+
triggerReason: 'keyword'
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
export function summarizePayload(payload, maxLength = 4000) {
|
|
134
|
+
try {
|
|
135
|
+
const text = JSON.stringify(payload);
|
|
136
|
+
return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return '[unserializable payload]';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function normalizeLegacyCallback(wrapper, rawPayload) {
|
|
143
|
+
const message = asRecord(wrapper.message);
|
|
144
|
+
if (!message) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const uuid = normalizeString(wrapper.key || wrapper.uuid || wrapper.UUID);
|
|
148
|
+
const fromUser = builtinString(message.from_user_name || message.fromUserName || message.FromUserName);
|
|
149
|
+
const toUser = builtinString(message.to_user_name || message.toUserName || message.ToUserName);
|
|
150
|
+
const content = builtinString(message.content || message.Content);
|
|
151
|
+
const pushContent = normalizeString(message.push_content || message.pushContent || message.PushContent);
|
|
152
|
+
const msgType = normalizeNumber(message.msg_type || message.msgType || message.MsgType);
|
|
153
|
+
const msgId = normalizeString(message.new_msg_id || message.newMsgId || message.NewMsgId) ||
|
|
154
|
+
normalizeString(message.msg_id || message.msgId || message.MsgId);
|
|
155
|
+
const timestamp = normalizeTimestamp(message.create_time || message.createTime || message.CreateTime);
|
|
156
|
+
const isGroup = isGroupContact(fromUser) || isGroupContact(toUser);
|
|
157
|
+
const ownerWxid = resolveLegacyOwnerWxid(fromUser, toUser, content, isGroup);
|
|
158
|
+
const contactId = resolveContactId(fromUser, toUser, ownerWxid);
|
|
159
|
+
const parsed = parseGroupSender(content, isGroup, ownerWxid);
|
|
160
|
+
const senderId = parsed.senderId || (!isGroup && fromUser ? fromUser : ownerWxid) || contactId;
|
|
161
|
+
const body = parsed.body || content;
|
|
162
|
+
const isSelf = isGroup ? senderId === ownerWxid : fromUser === ownerWxid;
|
|
163
|
+
if (!uuid || !contactId || !senderId || !msgId) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
source: 'legacy_callback',
|
|
168
|
+
uuid,
|
|
169
|
+
ownerWxid,
|
|
170
|
+
contactId,
|
|
171
|
+
senderId,
|
|
172
|
+
chatId: contactId,
|
|
173
|
+
chatType: isGroup ? 'group' : 'private',
|
|
174
|
+
messageId: msgId,
|
|
175
|
+
msgType,
|
|
176
|
+
content: body,
|
|
177
|
+
displayText: pushContent || body,
|
|
178
|
+
timestamp,
|
|
179
|
+
isSelf,
|
|
180
|
+
raw: message,
|
|
181
|
+
rawPayload
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function normalizeMessageWebhook(payload, rawPayload) {
|
|
185
|
+
const uuid = normalizeString(payload.uuid || payload.UUID);
|
|
186
|
+
const ownerWxid = normalizeString(payload.ownerwxid || payload.ownerWxid || payload.Ownerwxid);
|
|
187
|
+
const ownerInfo = asRecord(payload.ownerinfo || payload.ownerInfo || payload.Ownerinfo);
|
|
188
|
+
const contactId = normalizeString(payload.contactid || payload.contactId || payload.Contactid);
|
|
189
|
+
const contactInfo = asRecord(payload.contactinfo || payload.contactInfo || payload.Contactinfo);
|
|
190
|
+
const senderId = normalizeString(payload.sendusername || payload.sendUserName || payload.senderId || payload.Sendusername) ||
|
|
191
|
+
normalizeString(payload.fromusername || payload.fromUserName || payload.Fromusername) ||
|
|
192
|
+
contactId;
|
|
193
|
+
const senderInfo = asRecord(payload.sendcontactinfo || payload.sendContactInfo || payload.Sendcontactinfo);
|
|
194
|
+
const msgType = normalizeNumber(payload.msgtype || payload.msgType || payload.Msgtype);
|
|
195
|
+
const rawContent = normalizeString(payload.content || payload.Content);
|
|
196
|
+
const pushContent = normalizeString(payload.pushcontent || payload.pushContent || payload.Pushcontent);
|
|
197
|
+
const isGroup = normalizeChatType(payload.chattype || payload.chatType || payload.Chattype, contactId) === 'group';
|
|
198
|
+
const content = stripGroupSenderPrefix(rawContent || pushContent, isGroup).body;
|
|
199
|
+
const messageId = normalizeString(payload.newmsgid || payload.newMsgId || payload.Newmsgid) ||
|
|
200
|
+
normalizeString(payload.msgid || payload.msgId || payload.Msgid);
|
|
201
|
+
const timestamp = normalizeTimestamp(payload.createtime || payload.createTime || payload.Createtime);
|
|
202
|
+
if (!uuid || !contactId || !senderId || !messageId) {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
source: 'message_webhook',
|
|
207
|
+
uuid,
|
|
208
|
+
ownerWxid,
|
|
209
|
+
ownerName: normalizeContactName(ownerInfo),
|
|
210
|
+
contactId,
|
|
211
|
+
contactName: normalizeContactName(contactInfo),
|
|
212
|
+
senderId,
|
|
213
|
+
senderName: normalizeContactName(senderInfo),
|
|
214
|
+
chatId: contactId,
|
|
215
|
+
chatType: isGroup ? 'group' : 'private',
|
|
216
|
+
messageId,
|
|
217
|
+
msgType,
|
|
218
|
+
content,
|
|
219
|
+
displayText: pushContent || content,
|
|
220
|
+
timestamp,
|
|
221
|
+
isSelf: normalizeBoolean(payload.isself || payload.isSelf || payload.Isself),
|
|
222
|
+
raw: payload,
|
|
223
|
+
rawPayload
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function normalizeAgentInput(event) {
|
|
227
|
+
const text = normalizeString(event.content || event.displayText);
|
|
228
|
+
if (!text) {
|
|
229
|
+
return '';
|
|
230
|
+
}
|
|
231
|
+
if (/^\[[^\]]+\]$/.test(text)) {
|
|
232
|
+
return '';
|
|
233
|
+
}
|
|
234
|
+
return text;
|
|
235
|
+
}
|
|
236
|
+
function isTextLikeMessage(msgType) {
|
|
237
|
+
return msgType === undefined || msgType === 0 || msgType === 1;
|
|
238
|
+
}
|
|
239
|
+
function matchKeyword(input, keywords) {
|
|
240
|
+
const lowered = input.toLowerCase();
|
|
241
|
+
return keywords.find((keyword) => lowered.includes(keyword.toLowerCase())) || null;
|
|
242
|
+
}
|
|
243
|
+
function isMentioned(event) {
|
|
244
|
+
const rawText = summarizePayload(event.raw, 2000);
|
|
245
|
+
const ownerWxid = normalizeString(event.ownerWxid);
|
|
246
|
+
if (ownerWxid && rawText.includes(ownerWxid) && /atuserlist|atuser|@/i.test(rawText)) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
const content = `${event.content}\n${event.displayText || ''}`;
|
|
250
|
+
if (ownerWxid && content.includes(`@${ownerWxid}`)) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
return /(^|\s)@[^\s]{1,32}/.test(content);
|
|
254
|
+
}
|
|
255
|
+
function stripLeadingMention(input) {
|
|
256
|
+
return input.replace(/^@[^\s]+\s*/, '').trim() || input;
|
|
257
|
+
}
|
|
258
|
+
function normalizeContactName(record) {
|
|
259
|
+
if (!record) {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
return (normalizeString(record.displayname || record.displayName || record.Displayname) ||
|
|
263
|
+
normalizeString(record.nickname || record.nickName || record.Nickname) ||
|
|
264
|
+
undefined);
|
|
265
|
+
}
|
|
266
|
+
function parseGroupSender(content, isGroup, ownerWxid) {
|
|
267
|
+
if (!isGroup) {
|
|
268
|
+
return { body: content };
|
|
269
|
+
}
|
|
270
|
+
const parsed = stripGroupSenderPrefix(content, true);
|
|
271
|
+
const senderId = parsed.senderId || ownerWxid;
|
|
272
|
+
return {
|
|
273
|
+
senderId,
|
|
274
|
+
body: parsed.body
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
function stripGroupSenderPrefix(content, isGroup) {
|
|
278
|
+
if (!isGroup) {
|
|
279
|
+
return { body: content };
|
|
280
|
+
}
|
|
281
|
+
const match = content.match(/^([^:\n]{2,128}):\n?([\s\S]*)$/);
|
|
282
|
+
if (!match) {
|
|
283
|
+
return { body: content };
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
senderId: match[1].trim(),
|
|
287
|
+
body: match[2].trim()
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function resolveLegacyOwnerWxid(fromUser, toUser, content, isGroup) {
|
|
291
|
+
if (isGroup) {
|
|
292
|
+
if (isGroupContact(fromUser)) {
|
|
293
|
+
return toUser;
|
|
294
|
+
}
|
|
295
|
+
if (isGroupContact(toUser)) {
|
|
296
|
+
return fromUser;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (toUser && !isGroupContact(toUser)) {
|
|
300
|
+
return toUser;
|
|
301
|
+
}
|
|
302
|
+
const sender = stripGroupSenderPrefix(content, isGroup).senderId;
|
|
303
|
+
if (sender && fromUser && sender === fromUser) {
|
|
304
|
+
return toUser;
|
|
305
|
+
}
|
|
306
|
+
return toUser || fromUser;
|
|
307
|
+
}
|
|
308
|
+
function resolveContactId(fromUser, toUser, ownerWxid) {
|
|
309
|
+
if (isGroupContact(fromUser)) {
|
|
310
|
+
return fromUser;
|
|
311
|
+
}
|
|
312
|
+
if (isGroupContact(toUser)) {
|
|
313
|
+
return toUser;
|
|
314
|
+
}
|
|
315
|
+
if (fromUser === ownerWxid) {
|
|
316
|
+
return toUser;
|
|
317
|
+
}
|
|
318
|
+
if (toUser === ownerWxid) {
|
|
319
|
+
return fromUser;
|
|
320
|
+
}
|
|
321
|
+
return fromUser || toUser;
|
|
322
|
+
}
|
|
323
|
+
function normalizeChatType(value, contactId) {
|
|
324
|
+
const text = normalizeString(value).toLowerCase();
|
|
325
|
+
if (text === 'room' || text === 'group') {
|
|
326
|
+
return 'group';
|
|
327
|
+
}
|
|
328
|
+
return isGroupContact(contactId) ? 'group' : 'private';
|
|
329
|
+
}
|
|
330
|
+
function isGroupContact(value) {
|
|
331
|
+
return value.endsWith('@chatroom');
|
|
332
|
+
}
|
|
333
|
+
function normalizeTimestamp(value) {
|
|
334
|
+
const number = normalizeNumber(value);
|
|
335
|
+
if (!number) {
|
|
336
|
+
return Date.now();
|
|
337
|
+
}
|
|
338
|
+
return number > 10_000_000_000 ? number : number * 1000;
|
|
339
|
+
}
|
|
340
|
+
function normalizeNumber(value) {
|
|
341
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
342
|
+
return value;
|
|
343
|
+
}
|
|
344
|
+
if (typeof value === 'string' && value.trim()) {
|
|
345
|
+
const parsed = Number(value);
|
|
346
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
347
|
+
}
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
function builtinString(value) {
|
|
351
|
+
if (typeof value === 'string') {
|
|
352
|
+
return value.trim();
|
|
353
|
+
}
|
|
354
|
+
const record = asRecord(value);
|
|
355
|
+
if (!record) {
|
|
356
|
+
return '';
|
|
357
|
+
}
|
|
358
|
+
return normalizeString(record.str || record.Str || record.string || record.String);
|
|
359
|
+
}
|
|
360
|
+
function asRecord(value) {
|
|
361
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
return value;
|
|
365
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { XpertRemoteComponentEntry, XpertRemoteComponentViewSchema, XpertResolvedViewHostContext, XpertViewActionRequest, XpertViewActionResult, XpertViewDataResult, XpertViewQuery } from '@xpert-ai/contracts';
|
|
2
|
+
import { IXpertViewExtensionProvider } from '@xpert-ai/plugin-sdk';
|
|
3
|
+
import { WechatPersonalConversationService } from '../conversation.service.js';
|
|
4
|
+
import { WechatPersonalChannelStrategy } from '../wechat-personal-channel.strategy.js';
|
|
5
|
+
type SdkViewManifestsResult = ReturnType<IXpertViewExtensionProvider['getViewManifests']>;
|
|
6
|
+
export declare class WechatPersonalViewProvider implements IXpertViewExtensionProvider {
|
|
7
|
+
private readonly conversationService;
|
|
8
|
+
private readonly wechatChannel;
|
|
9
|
+
constructor(conversationService: WechatPersonalConversationService, wechatChannel: WechatPersonalChannelStrategy);
|
|
10
|
+
supports(context: XpertResolvedViewHostContext): boolean;
|
|
11
|
+
getViewManifests(context: XpertResolvedViewHostContext, slot: string): SdkViewManifestsResult;
|
|
12
|
+
getRemoteComponentEntry(_context: XpertResolvedViewHostContext, viewKey: string, component: XpertRemoteComponentViewSchema['component']): Promise<XpertRemoteComponentEntry>;
|
|
13
|
+
getViewData(context: XpertResolvedViewHostContext, viewKey: string, query: XpertViewQuery): Promise<XpertViewDataResult>;
|
|
14
|
+
executeViewAction(context: XpertResolvedViewHostContext, viewKey: string, actionKey: string, request: XpertViewActionRequest): Promise<XpertViewActionResult>;
|
|
15
|
+
private resolveIntegrationId;
|
|
16
|
+
}
|
|
17
|
+
export {};
|