@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.
Files changed (69) hide show
  1. package/README.md +353 -0
  2. package/dist/index.d.ts +20 -0
  3. package/dist/index.js +139 -0
  4. package/dist/lib/constants.d.ts +23 -0
  5. package/dist/lib/constants.js +23 -0
  6. package/dist/lib/conversation-user-key.d.ts +13 -0
  7. package/dist/lib/conversation-user-key.js +28 -0
  8. package/dist/lib/conversation.service.d.ts +215 -0
  9. package/dist/lib/conversation.service.js +1179 -0
  10. package/dist/lib/decorators.d.ts +2 -0
  11. package/dist/lib/decorators.js +3 -0
  12. package/dist/lib/entities/index.d.ts +4 -0
  13. package/dist/lib/entities/index.js +4 -0
  14. package/dist/lib/entities/wechat-personal-account.entity.d.ts +19 -0
  15. package/dist/lib/entities/wechat-personal-account.entity.js +83 -0
  16. package/dist/lib/entities/wechat-personal-conversation-binding.entity.d.ts +14 -0
  17. package/dist/lib/entities/wechat-personal-conversation-binding.entity.js +65 -0
  18. package/dist/lib/entities/wechat-personal-message-log.entity.d.ts +27 -0
  19. package/dist/lib/entities/wechat-personal-message-log.entity.js +108 -0
  20. package/dist/lib/entities/wechat-personal-trigger-binding.entity.d.ts +17 -0
  21. package/dist/lib/entities/wechat-personal-trigger-binding.entity.js +71 -0
  22. package/dist/lib/handoff/index.d.ts +4 -0
  23. package/dist/lib/handoff/index.js +4 -0
  24. package/dist/lib/handoff/wechat-personal-chat-callback.processor.d.ts +26 -0
  25. package/dist/lib/handoff/wechat-personal-chat-callback.processor.js +312 -0
  26. package/dist/lib/handoff/wechat-personal-chat-dispatch.service.d.ts +26 -0
  27. package/dist/lib/handoff/wechat-personal-chat-dispatch.service.js +187 -0
  28. package/dist/lib/handoff/wechat-personal-chat-run-state.service.d.ts +21 -0
  29. package/dist/lib/handoff/wechat-personal-chat-run-state.service.js +39 -0
  30. package/dist/lib/handoff/wechat-personal-chat.types.d.ts +69 -0
  31. package/dist/lib/handoff/wechat-personal-chat.types.js +2 -0
  32. package/dist/lib/message.d.ts +49 -0
  33. package/dist/lib/message.js +64 -0
  34. package/dist/lib/remote-components/wechat-personal-workbench/app.js +1831 -0
  35. package/dist/lib/tokens.d.ts +1 -0
  36. package/dist/lib/tokens.js +1 -0
  37. package/dist/lib/types.d.ts +48 -0
  38. package/dist/lib/types.js +365 -0
  39. package/dist/lib/views/wechat-personal-view.provider.d.ts +17 -0
  40. package/dist/lib/views/wechat-personal-view.provider.js +441 -0
  41. package/dist/lib/wechat-personal-channel.strategy.d.ts +33 -0
  42. package/dist/lib/wechat-personal-channel.strategy.js +197 -0
  43. package/dist/lib/wechat-personal-integration.strategy.d.ts +56 -0
  44. package/dist/lib/wechat-personal-integration.strategy.js +217 -0
  45. package/dist/lib/wechat-personal.client.d.ts +29 -0
  46. package/dist/lib/wechat-personal.client.js +146 -0
  47. package/dist/lib/wechat-personal.controller.d.ts +50 -0
  48. package/dist/lib/wechat-personal.controller.js +270 -0
  49. package/dist/lib/wechat-personal.middleware.d.ts +20 -0
  50. package/dist/lib/wechat-personal.middleware.js +267 -0
  51. package/dist/lib/wechat-personal.plugin.d.ts +2 -0
  52. package/dist/lib/wechat-personal.plugin.js +58 -0
  53. package/dist/lib/wechat-personal.templates.d.ts +2 -0
  54. package/dist/lib/wechat-personal.templates.js +100 -0
  55. package/dist/lib/workflow/index.d.ts +5 -0
  56. package/dist/lib/workflow/index.js +5 -0
  57. package/dist/lib/workflow/wechat-personal-trigger-aggregation.service.d.ts +10 -0
  58. package/dist/lib/workflow/wechat-personal-trigger-aggregation.service.js +39 -0
  59. package/dist/lib/workflow/wechat-personal-trigger-aggregation.types.d.ts +30 -0
  60. package/dist/lib/workflow/wechat-personal-trigger-aggregation.types.js +2 -0
  61. package/dist/lib/workflow/wechat-personal-trigger-flush.processor.d.ts +8 -0
  62. package/dist/lib/workflow/wechat-personal-trigger-flush.processor.js +39 -0
  63. package/dist/lib/workflow/wechat-personal-trigger.strategy.d.ts +65 -0
  64. package/dist/lib/workflow/wechat-personal-trigger.strategy.js +511 -0
  65. package/dist/lib/workflow/wechat-personal-trigger.types.d.ts +10 -0
  66. package/dist/lib/workflow/wechat-personal-trigger.types.js +2 -0
  67. package/dist/xpert-wechat-personal-admin-assistant.yaml +103 -0
  68. package/dist/xpert-wechat-personal-user-assistant.yaml +127 -0
  69. package/package.json +79 -0
@@ -0,0 +1,511 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ var WechatPersonalTriggerStrategy_1;
14
+ import { Inject, Injectable, Logger } from '@nestjs/common';
15
+ import { InjectRepository } from '@nestjs/typeorm';
16
+ import { HANDOFF_PERMISSION_SERVICE_TOKEN, INTEGRATION_PERMISSION_SERVICE_TOKEN, RequestContext, WorkflowTriggerStrategy } from '@xpert-ai/plugin-sdk';
17
+ import { randomUUID } from 'crypto';
18
+ import { Repository } from 'typeorm';
19
+ import { WECHAT_PERSONAL_ICON, WECHAT_PERSONAL_PROVIDER_KEY } from '../constants.js';
20
+ import { WechatPersonalTriggerBindingEntity } from '../entities/wechat-personal-trigger-binding.entity.js';
21
+ import { WechatPersonalChatDispatchService } from '../handoff/wechat-personal-chat-dispatch.service.js';
22
+ import { WechatPersonalMessage } from '../message.js';
23
+ import { WECHAT_PERSONAL_PLUGIN_CONTEXT } from '../tokens.js';
24
+ import { normalizeGroupTriggerMode, normalizeKeywords } from '../types.js';
25
+ import { WechatPersonalChannelStrategy } from '../wechat-personal-channel.strategy.js';
26
+ import { WECHAT_PERSONAL_TRIGGER_FLUSH_MESSAGE_TYPE } from './wechat-personal-trigger-aggregation.types.js';
27
+ import { WechatPersonalTriggerAggregationService } from './wechat-personal-trigger-aggregation.service.js';
28
+ import { WechatPersonalTrigger } from './wechat-personal-trigger.types.js';
29
+ const DEFAULT_SESSION_TIMEOUT_SECONDS = 3600;
30
+ const DEFAULT_SUMMARY_WINDOW_SECONDS = 0;
31
+ let WechatPersonalTriggerStrategy = WechatPersonalTriggerStrategy_1 = class WechatPersonalTriggerStrategy {
32
+ constructor(dispatchService, aggregationService, wechatChannel, bindingRepository, pluginContext) {
33
+ this.dispatchService = dispatchService;
34
+ this.aggregationService = aggregationService;
35
+ this.wechatChannel = wechatChannel;
36
+ this.bindingRepository = bindingRepository;
37
+ this.pluginContext = pluginContext;
38
+ this.logger = new Logger(WechatPersonalTriggerStrategy_1.name);
39
+ this.callbacks = new Map();
40
+ this.meta = {
41
+ name: WechatPersonalTrigger,
42
+ label: {
43
+ en_US: 'Personal WeChat Trigger',
44
+ zh_Hans: '个人微信触发器'
45
+ },
46
+ icon: {
47
+ type: 'svg',
48
+ value: WECHAT_PERSONAL_ICON
49
+ },
50
+ configSchema: {
51
+ type: 'object',
52
+ properties: {
53
+ enabled: {
54
+ type: 'boolean',
55
+ title: {
56
+ en_US: 'Enabled',
57
+ zh_Hans: '启用'
58
+ },
59
+ default: true
60
+ },
61
+ integrationId: {
62
+ type: 'string',
63
+ title: {
64
+ en_US: 'Personal WeChat Integration',
65
+ zh_Hans: '个人微信集成'
66
+ },
67
+ 'x-ui': {
68
+ component: 'remoteSelect',
69
+ selectUrl: '/api/wechat-personal/integration-select-options'
70
+ }
71
+ },
72
+ sessionTimeoutSeconds: {
73
+ type: 'number',
74
+ title: {
75
+ en_US: 'Session Timeout (seconds)',
76
+ zh_Hans: '会话超时时间(秒)'
77
+ },
78
+ default: DEFAULT_SESSION_TIMEOUT_SECONDS
79
+ },
80
+ summaryWindowSeconds: {
81
+ type: 'number',
82
+ title: {
83
+ en_US: 'Summary Window (seconds)',
84
+ zh_Hans: '汇总时间(秒)'
85
+ },
86
+ description: {
87
+ en_US: 'Messages received in this window are merged before dispatching to the agent.',
88
+ zh_Hans: '窗口内收到的连续文本会合并后再发送给 Agent。'
89
+ },
90
+ default: DEFAULT_SUMMARY_WINDOW_SECONDS
91
+ },
92
+ groupTriggerMode: {
93
+ type: 'string',
94
+ title: {
95
+ en_US: 'Group Trigger Mode',
96
+ zh_Hans: '群聊触发方式'
97
+ },
98
+ enum: ['mention_or_keywords', 'all', 'mentions', 'keywords', 'off'],
99
+ default: 'mention_or_keywords'
100
+ },
101
+ groupKeywords: {
102
+ type: 'array',
103
+ title: {
104
+ en_US: 'Group Keywords',
105
+ zh_Hans: '群聊关键词'
106
+ },
107
+ items: {
108
+ type: 'string'
109
+ }
110
+ }
111
+ },
112
+ required: ['enabled', 'integrationId']
113
+ }
114
+ };
115
+ this.bootstrap = {
116
+ mode: 'replay_publish',
117
+ critical: false
118
+ };
119
+ }
120
+ get integrationPermissionService() {
121
+ if (!this._integrationPermissionService) {
122
+ this._integrationPermissionService = this.pluginContext.resolve(INTEGRATION_PERMISSION_SERVICE_TOKEN);
123
+ }
124
+ return this._integrationPermissionService;
125
+ }
126
+ get handoffPermissionService() {
127
+ if (!this._handoffPermissionService) {
128
+ this._handoffPermissionService = this.pluginContext.resolve(HANDOFF_PERMISSION_SERVICE_TOKEN);
129
+ }
130
+ return this._handoffPermissionService;
131
+ }
132
+ async validate(payload) {
133
+ const { xpertId, node, config } = payload;
134
+ const items = [];
135
+ const nodeKey = node?.key;
136
+ if (!config?.integrationId) {
137
+ items.push({
138
+ node: nodeKey,
139
+ ruleCode: 'TRIGGER_WECHAT_PERSONAL_INTEGRATION_REQUIRED',
140
+ field: 'integrationId',
141
+ value: '',
142
+ message: {
143
+ en_US: 'Personal WeChat integration is required',
144
+ zh_Hans: '需要选择个人微信集成'
145
+ },
146
+ level: 'error'
147
+ });
148
+ return items;
149
+ }
150
+ try {
151
+ const integration = await this.integrationPermissionService.read(config.integrationId);
152
+ if (!integration || integration.provider !== WECHAT_PERSONAL_PROVIDER_KEY) {
153
+ items.push({
154
+ node: nodeKey,
155
+ ruleCode: 'TRIGGER_WECHAT_PERSONAL_INTEGRATION_NOT_FOUND',
156
+ field: 'integrationId',
157
+ value: config.integrationId,
158
+ message: {
159
+ en_US: `Personal WeChat integration "${config.integrationId}" not found`,
160
+ zh_Hans: `个人微信集成 "${config.integrationId}" 不存在`
161
+ },
162
+ level: 'error'
163
+ });
164
+ }
165
+ }
166
+ catch (error) {
167
+ this.logger.warn(`Validate integration "${config.integrationId}" failed: ${error instanceof Error ? error.message : String(error)}`);
168
+ }
169
+ if (!config.enabled) {
170
+ return items;
171
+ }
172
+ const existingXpertId = await this.getBoundXpertId(config.integrationId);
173
+ if (existingXpertId && existingXpertId !== xpertId) {
174
+ items.push({
175
+ node: nodeKey,
176
+ ruleCode: 'TRIGGER_WECHAT_PERSONAL_INTEGRATION_CONFLICT',
177
+ field: 'integrationId',
178
+ value: config.integrationId,
179
+ message: {
180
+ en_US: `Integration "${config.integrationId}" is already bound to another xpert`,
181
+ zh_Hans: `个人微信集成 "${config.integrationId}" 已绑定到其他专家`
182
+ },
183
+ level: 'error'
184
+ });
185
+ }
186
+ return items;
187
+ }
188
+ async publish(payload, callback) {
189
+ const { xpertId, config } = payload;
190
+ if (!config?.enabled || !config.integrationId) {
191
+ return;
192
+ }
193
+ const integrationId = config.integrationId;
194
+ const existingXpertId = await this.getBoundXpertId(integrationId);
195
+ if (existingXpertId && existingXpertId !== xpertId) {
196
+ throw new Error(`Personal WeChat trigger integration "${integrationId}" is already bound to xpert "${existingXpertId}"`);
197
+ }
198
+ const context = await this.resolveBindingContext(integrationId);
199
+ await this.bindingRepository.upsert({
200
+ integrationId,
201
+ xpertId,
202
+ sessionTimeoutSeconds: this.normalizePositiveSeconds(config.sessionTimeoutSeconds, DEFAULT_SESSION_TIMEOUT_SECONDS),
203
+ summaryWindowSeconds: this.normalizeNonNegativeSeconds(config.summaryWindowSeconds, DEFAULT_SUMMARY_WINDOW_SECONDS),
204
+ groupTriggerMode: normalizeGroupTriggerMode(config.groupTriggerMode),
205
+ groupKeywords: normalizeKeywords(config.groupKeywords),
206
+ tenantId: context.tenantId ?? null,
207
+ organizationId: context.organizationId ?? null,
208
+ createdById: context.createdById ?? null,
209
+ updatedById: context.updatedById ?? null
210
+ }, ['integrationId']);
211
+ this.callbacks.set(integrationId, callback);
212
+ }
213
+ async stop(payload) {
214
+ const { xpertId, config } = payload;
215
+ const integrationId = config?.integrationId;
216
+ if (integrationId) {
217
+ this.callbacks.delete(integrationId);
218
+ await this.removeBindingFromStore(integrationId, xpertId);
219
+ return;
220
+ }
221
+ const scope = this.resolveRequestTenantScope();
222
+ const persistedBindings = await this.bindingRepository.find({
223
+ where: this.scopedWhere({ xpertId }, scope)
224
+ });
225
+ for (const binding of persistedBindings) {
226
+ this.callbacks.delete(binding.integrationId);
227
+ }
228
+ await this.removeBindingsByXpertId(xpertId);
229
+ }
230
+ async getBinding(integrationId, scope) {
231
+ if (!integrationId) {
232
+ return null;
233
+ }
234
+ const resolvedScope = scope ?? (await this.resolveQueryTenantScope(integrationId));
235
+ return this.bindingRepository.findOne({
236
+ where: this.scopedWhere({ integrationId }, resolvedScope)
237
+ });
238
+ }
239
+ async getBoundXpertId(integrationId) {
240
+ const binding = await this.getBinding(integrationId);
241
+ return binding?.xpertId ?? null;
242
+ }
243
+ async getBindingByXpertId(xpertId) {
244
+ if (!xpertId) {
245
+ return null;
246
+ }
247
+ const scope = this.resolveRequestTenantScope();
248
+ return this.bindingRepository.findOne({
249
+ where: this.scopedWhere({ xpertId }, scope),
250
+ order: {
251
+ updatedAt: 'DESC'
252
+ }
253
+ });
254
+ }
255
+ async getBoundIntegrationId(xpertId) {
256
+ const binding = await this.getBindingByXpertId(xpertId);
257
+ return binding?.integrationId ?? null;
258
+ }
259
+ async clearBufferedConversation(conversationUserKey) {
260
+ const aggregateKey = this.normalizeAggregateKey(conversationUserKey);
261
+ if (!aggregateKey) {
262
+ return;
263
+ }
264
+ await this.aggregationService.clear(aggregateKey);
265
+ }
266
+ async handleInboundMessage(params) {
267
+ const binding = await this.getBinding(params.integrationId, params);
268
+ if (!binding?.xpertId) {
269
+ this.logger.debug(`[wechat-personal-trigger] binding miss integrationId=${params.integrationId}`);
270
+ return false;
271
+ }
272
+ const aggregateKey = this.normalizeAggregateKey(params.conversationUserKey);
273
+ if (!aggregateKey) {
274
+ this.logger.warn(`[wechat-personal-trigger] aggregation key missing integrationId=${params.integrationId}`);
275
+ return false;
276
+ }
277
+ const summaryWindowSeconds = this.normalizeNonNegativeSeconds(binding.summaryWindowSeconds, DEFAULT_SUMMARY_WINDOW_SECONDS);
278
+ if (summaryWindowSeconds <= 0) {
279
+ await this.dispatchInboundMessage({
280
+ integrationId: params.integrationId,
281
+ xpertId: binding.xpertId,
282
+ dispatchMode: 'immediate',
283
+ dispatchPayload: {
284
+ xpertId: binding.xpertId,
285
+ input: params.input || '',
286
+ wechatMessage: params.wechatMessage,
287
+ conversationId: params.conversationId,
288
+ conversationUserKey: aggregateKey,
289
+ tenantId: params.tenantId,
290
+ organizationId: params.organizationId,
291
+ executorUserId: params.executorUserId,
292
+ endUserId: params.endUserId
293
+ }
294
+ });
295
+ return true;
296
+ }
297
+ const currentState = await this.aggregationService.get(aggregateKey);
298
+ const sameRoutingTarget = currentState?.integrationId === params.integrationId && currentState?.xpertId === binding.xpertId;
299
+ const nextVersion = (currentState?.version ?? 0) + 1;
300
+ const aggregateState = {
301
+ aggregateKey,
302
+ integrationId: params.integrationId,
303
+ conversationUserKey: aggregateKey,
304
+ xpertId: binding.xpertId,
305
+ version: nextVersion,
306
+ inputParts: [...(sameRoutingTarget ? currentState?.inputParts ?? [] : []), params.input || ''],
307
+ lastMessageAt: Date.now(),
308
+ conversationId: params.conversationId ?? (sameRoutingTarget ? currentState?.conversationId : undefined),
309
+ tenantId: params.tenantId,
310
+ organizationId: params.organizationId,
311
+ executorUserId: params.executorUserId,
312
+ endUserId: params.endUserId,
313
+ latestMessage: {
314
+ integrationId: params.wechatMessage.integrationId,
315
+ uuid: params.wechatMessage.uuid,
316
+ ownerWxid: params.wechatMessage.ownerWxid,
317
+ contactId: params.wechatMessage.contactId,
318
+ chatType: params.wechatMessage.chatType,
319
+ senderId: params.wechatMessage.senderId,
320
+ language: params.wechatMessage.language,
321
+ messageId: params.wechatMessage.messageId
322
+ }
323
+ };
324
+ const ttlSeconds = Math.max(DEFAULT_SESSION_TIMEOUT_SECONDS, this.normalizePositiveSeconds(binding.sessionTimeoutSeconds, DEFAULT_SESSION_TIMEOUT_SECONDS), summaryWindowSeconds * 3);
325
+ await this.aggregationService.save(aggregateState, ttlSeconds);
326
+ await this.handoffPermissionService.enqueue(this.buildFlushMessage(aggregateState), {
327
+ delayMs: summaryWindowSeconds * 1000
328
+ });
329
+ return true;
330
+ }
331
+ async flushBufferedConversation(payload) {
332
+ const aggregateKey = this.normalizeAggregateKey(payload.aggregateKey);
333
+ if (!aggregateKey) {
334
+ return false;
335
+ }
336
+ const state = await this.aggregationService.get(aggregateKey);
337
+ if (!state || state.version !== payload.version) {
338
+ return false;
339
+ }
340
+ await this.dispatchInboundMessage({
341
+ integrationId: state.integrationId,
342
+ xpertId: state.xpertId,
343
+ dispatchMode: `buffered version=${state.version}`,
344
+ dispatchPayload: {
345
+ xpertId: state.xpertId,
346
+ input: state.inputParts.join('\n'),
347
+ wechatMessage: new WechatPersonalMessage({
348
+ integrationId: state.latestMessage.integrationId,
349
+ uuid: state.latestMessage.uuid,
350
+ ownerWxid: state.latestMessage.ownerWxid,
351
+ contactId: state.latestMessage.contactId,
352
+ chatType: state.latestMessage.chatType,
353
+ senderId: state.latestMessage.senderId,
354
+ wechatChannel: this.wechatChannel
355
+ }, {
356
+ status: 'thinking',
357
+ language: state.latestMessage.language,
358
+ messageId: state.latestMessage.messageId
359
+ }),
360
+ conversationId: state.conversationId,
361
+ conversationUserKey: state.conversationUserKey,
362
+ tenantId: state.tenantId,
363
+ organizationId: state.organizationId,
364
+ executorUserId: state.executorUserId,
365
+ endUserId: state.endUserId
366
+ }
367
+ });
368
+ await this.aggregationService.clear(aggregateKey);
369
+ return true;
370
+ }
371
+ buildFlushMessage(state) {
372
+ return {
373
+ id: `wechat-personal-trigger-flush-${randomUUID()}`,
374
+ type: WECHAT_PERSONAL_TRIGGER_FLUSH_MESSAGE_TYPE,
375
+ version: 1,
376
+ tenantId: state.tenantId,
377
+ sessionKey: state.aggregateKey,
378
+ businessKey: state.aggregateKey,
379
+ attempt: 1,
380
+ maxAttempts: 1,
381
+ enqueuedAt: Date.now(),
382
+ traceId: `${state.aggregateKey}:${state.version}`,
383
+ payload: {
384
+ aggregateKey: state.aggregateKey,
385
+ version: state.version
386
+ },
387
+ headers: {
388
+ ...(state.organizationId ? { organizationId: state.organizationId } : {}),
389
+ ...(state.executorUserId ? { userId: state.executorUserId } : {}),
390
+ source: 'api',
391
+ requestedLane: 'main',
392
+ handoffQueue: 'integration',
393
+ ...(state.integrationId ? { integrationId: state.integrationId } : {})
394
+ }
395
+ };
396
+ }
397
+ async dispatchInboundMessage(params) {
398
+ const callback = this.callbacks.get(params.integrationId);
399
+ if (!callback) {
400
+ this.logger.debug(`[wechat-personal-trigger] runtime callback miss, enqueue dispatch integrationId=${params.integrationId} xpertId=${params.xpertId} mode=${params.dispatchMode}`);
401
+ await this.dispatchService.enqueueDispatch(params.dispatchPayload);
402
+ return;
403
+ }
404
+ const handoffMessage = await this.dispatchService.buildDispatchMessage(params.dispatchPayload);
405
+ await Promise.resolve(callback({
406
+ from: WechatPersonalTrigger,
407
+ xpertId: params.xpertId,
408
+ handoffMessage
409
+ }));
410
+ }
411
+ async resolveBindingContext(integrationId) {
412
+ const tenantId = RequestContext.currentTenantId();
413
+ const organizationId = RequestContext.getOrganizationId();
414
+ const userId = RequestContext.currentUserId();
415
+ if (tenantId && organizationId) {
416
+ return {
417
+ tenantId,
418
+ organizationId,
419
+ createdById: userId,
420
+ updatedById: userId
421
+ };
422
+ }
423
+ const integration = await this.integrationPermissionService.read(integrationId);
424
+ return {
425
+ tenantId: tenantId ?? integration?.tenantId ?? null,
426
+ organizationId: organizationId ?? integration?.organizationId ?? null,
427
+ createdById: userId ?? integration?.createdById ?? null,
428
+ updatedById: userId ?? integration?.updatedById ?? userId ?? null
429
+ };
430
+ }
431
+ normalizeAggregateKey(value) {
432
+ if (typeof value !== 'string') {
433
+ return undefined;
434
+ }
435
+ const normalized = value.trim();
436
+ return normalized || undefined;
437
+ }
438
+ normalizePositiveSeconds(value, defaultValue) {
439
+ if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
440
+ return Math.floor(value);
441
+ }
442
+ return defaultValue;
443
+ }
444
+ normalizeNonNegativeSeconds(value, defaultValue) {
445
+ if (typeof value === 'number' && Number.isFinite(value) && value >= 0) {
446
+ return Math.floor(value);
447
+ }
448
+ return defaultValue;
449
+ }
450
+ async removeBindingFromStore(integrationId, expectedXpertId) {
451
+ if (!integrationId) {
452
+ return;
453
+ }
454
+ const scope = await this.resolveQueryTenantScope(integrationId);
455
+ if (expectedXpertId) {
456
+ await this.bindingRepository.delete(this.scopedWhere({ integrationId, xpertId: expectedXpertId }, scope));
457
+ return;
458
+ }
459
+ await this.bindingRepository.delete(this.scopedWhere({ integrationId }, scope));
460
+ }
461
+ async removeBindingsByXpertId(xpertId) {
462
+ if (!xpertId) {
463
+ return;
464
+ }
465
+ await this.bindingRepository.delete(this.scopedWhere({ xpertId }, this.resolveRequestTenantScope()));
466
+ }
467
+ resolveRequestTenantScope() {
468
+ return {
469
+ tenantId: RequestContext.currentTenantId() ?? null,
470
+ organizationId: RequestContext.getOrganizationId() ?? null
471
+ };
472
+ }
473
+ async resolveQueryTenantScope(integrationId, fallback) {
474
+ const requestScope = this.resolveRequestTenantScope();
475
+ if (requestScope.tenantId || requestScope.organizationId || fallback?.tenantId || fallback?.organizationId) {
476
+ return {
477
+ tenantId: fallback?.tenantId ?? requestScope.tenantId ?? null,
478
+ organizationId: fallback?.organizationId ?? requestScope.organizationId ?? null
479
+ };
480
+ }
481
+ if (!integrationId) {
482
+ return requestScope;
483
+ }
484
+ const bindingContext = await this.resolveBindingContext(integrationId);
485
+ return {
486
+ tenantId: bindingContext.tenantId,
487
+ organizationId: bindingContext.organizationId
488
+ };
489
+ }
490
+ scopedWhere(where, scope) {
491
+ const scoped = { ...where };
492
+ if (scope?.tenantId) {
493
+ scoped.tenantId = scope.tenantId;
494
+ }
495
+ if (scope?.organizationId) {
496
+ scoped.organizationId = scope.organizationId;
497
+ }
498
+ return scoped;
499
+ }
500
+ };
501
+ WechatPersonalTriggerStrategy = WechatPersonalTriggerStrategy_1 = __decorate([
502
+ Injectable(),
503
+ WorkflowTriggerStrategy(WechatPersonalTrigger),
504
+ __param(3, InjectRepository(WechatPersonalTriggerBindingEntity)),
505
+ __param(4, Inject(WECHAT_PERSONAL_PLUGIN_CONTEXT)),
506
+ __metadata("design:paramtypes", [WechatPersonalChatDispatchService,
507
+ WechatPersonalTriggerAggregationService,
508
+ WechatPersonalChannelStrategy,
509
+ Repository, Object])
510
+ ], WechatPersonalTriggerStrategy);
511
+ export { WechatPersonalTriggerStrategy };
@@ -0,0 +1,10 @@
1
+ import { WechatPersonalGroupTriggerMode } from '../types.js';
2
+ export declare const WechatPersonalTrigger = "wechat_personal";
3
+ export type TWechatPersonalTriggerConfig = {
4
+ enabled: boolean;
5
+ integrationId: string;
6
+ sessionTimeoutSeconds?: number;
7
+ summaryWindowSeconds?: number;
8
+ groupTriggerMode?: WechatPersonalGroupTriggerMode;
9
+ groupKeywords?: string[] | string;
10
+ };
@@ -0,0 +1,2 @@
1
+ import { WECHAT_PERSONAL_TRIGGER_KEY } from '../constants.js';
2
+ export const WechatPersonalTrigger = WECHAT_PERSONAL_TRIGGER_KEY;
@@ -0,0 +1,103 @@
1
+ team:
2
+ name: wechat-personal-admin-assistant
3
+ type: agent
4
+ title: 个人微信管理员
5
+ description: 管理组织内 wx2.0 个人微信集成、账号、会话、消息日志和回调配置的 Agent
6
+ avatar:
7
+ emoji:
8
+ id: toolbox
9
+ background: rgb(220, 252, 231)
10
+ options:
11
+ templateKey: wechat-personal-admin-assistant
12
+ dataXpert:
13
+ managedBy: data-xpert
14
+ templateKey: wechat-personal-admin-assistant
15
+ assistantKind: wechat-personal-admin-assistant
16
+ businessDomain: wechat-personal
17
+ wechatPersonalRole: admin
18
+ requiredPlugin: '@xpert-ai/plugin-community-wechat'
19
+ requiredPlugins:
20
+ - '@xpert-ai/plugin-community-wechat'
21
+ requiredCapabilities:
22
+ - wechat_personal_bridge
23
+ - wechat-personal-runtime
24
+ - wechat-personal-workbench
25
+ agentConfig:
26
+ recursionLimit: 10000
27
+ features:
28
+ sandbox:
29
+ enabled: false
30
+ version: "1"
31
+ agent:
32
+ key: Agent_WechatPersonalAdmin
33
+ copilotModel:
34
+ referencedId: null
35
+ modelType: llm
36
+ model: qwen3.6-plus
37
+ options:
38
+ context_size: 1000000
39
+ temperature: 0.2
40
+ maxRetries: 4
41
+ max_tokens: 4096
42
+ top_p: 0.9
43
+ knowledgebases: []
44
+ toolsets: []
45
+ tags: []
46
+ nodes:
47
+ - type: agent
48
+ key: Agent_WechatPersonalAdmin
49
+ position:
50
+ x: 820
51
+ y: 20
52
+ entity:
53
+ key: Agent_WechatPersonalAdmin
54
+ name: wechat-personal-admin-assistant
55
+ title: 个人微信管理员
56
+ description: 管理组织内 wx2.0 个人微信集成、账号、会话、消息日志和回调配置的 Agent
57
+ avatar:
58
+ emoji:
59
+ id: toolbox
60
+ background: rgb(220, 252, 231)
61
+ prompt: >
62
+ You are the Personal WeChat administrator assistant for this organization.
63
+
64
+ Your job is to help administrators configure and operate wx2.0 personal WeChat integrations:
65
+ review organization-wide integration status, callback URLs, account callback health, conversation
66
+ bindings, message logs, dispatch errors, and outbound reply failures. Use the Personal WeChat
67
+ runtime tools when answering operational questions.
68
+
69
+ This assistant is not connected to inbound WeChat messages and must not act like an end-user
70
+ chat responder. Do not configure a Personal WeChat trigger in this administrator assistant.
71
+
72
+ When an operation can affect a specific wx2.0 integration or account, ask for or use an explicit
73
+ integrationId and uuid before taking action. Never guess an integration from a similar name when
74
+ multiple integrations exist.
75
+
76
+ Do not reveal API tokens, callback secrets, hidden routing details, queue identifiers, or system
77
+ configuration that is not needed by the administrator. Callback URLs may be shown only as setup
78
+ instructions for administrators.
79
+
80
+ Prefer Chinese for Chinese administrators; otherwise mirror the user's language. Keep answers concise
81
+ and include concrete next steps when diagnosing failures.
82
+ collaboratorNames: []
83
+ toolsetIds: []
84
+ knowledgebaseIds: []
85
+ hash: wechat-personal-admin-agent-v1
86
+ - type: workflow
87
+ key: Middleware_WechatPersonalRuntime
88
+ position:
89
+ x: 1140
90
+ y: 280
91
+ entity:
92
+ type: middleware
93
+ key: Middleware_WechatPersonalRuntime
94
+ title: Personal WeChat Runtime Tools
95
+ provider: WechatPersonalRuntimeMiddleware
96
+ required: true
97
+ options: {}
98
+ hash: wechat-personal-admin-middleware-v1
99
+ connections:
100
+ - type: workflow
101
+ key: Agent_WechatPersonalAdmin/Middleware_WechatPersonalRuntime
102
+ from: Agent_WechatPersonalAdmin
103
+ to: Middleware_WechatPersonalRuntime