@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,270 @@
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
+ import { BadRequestException, Body, Controller, Get, Header, HttpCode, Inject, Param, Post, Query, Request } from '@nestjs/common';
14
+ import { INTEGRATION_PERMISSION_SERVICE_TOKEN, RequestContext, runWithRequestContext } from '@xpert-ai/plugin-sdk';
15
+ import { Public } from './decorators.js';
16
+ import { WECHAT_PERSONAL_PROVIDER_KEY } from './constants.js';
17
+ import { WECHAT_PERSONAL_PLUGIN_CONTEXT } from './tokens.js';
18
+ import { WechatPersonalConversationService } from './conversation.service.js';
19
+ import { normalizeString } from './types.js';
20
+ import { WechatPersonalChannelStrategy } from './wechat-personal-channel.strategy.js';
21
+ let WechatPersonalController = class WechatPersonalController {
22
+ constructor(conversation, wechatChannel, pluginContext) {
23
+ this.conversation = conversation;
24
+ this.wechatChannel = wechatChannel;
25
+ this.pluginContext = pluginContext;
26
+ }
27
+ get integrationPermissionService() {
28
+ if (!this._integrationPermissionService) {
29
+ this._integrationPermissionService = this.pluginContext.resolve(INTEGRATION_PERMISSION_SERVICE_TOKEN);
30
+ }
31
+ return this._integrationPermissionService;
32
+ }
33
+ async webhook(integrationId, req, body, querySecret) {
34
+ const integration = await this.readWechatPersonalIntegration(integrationId);
35
+ this.verifyCallbackSecret(integration, req, querySecret);
36
+ const payload = this.parseBodyToObject(body);
37
+ if (!payload) {
38
+ return 'success';
39
+ }
40
+ const event = this.wechatChannel.normalizeWebhookEvent(payload);
41
+ if (!event) {
42
+ return 'success';
43
+ }
44
+ const ctx = {
45
+ integration,
46
+ tenantId: integration.tenantId,
47
+ organizationId: integration.organizationId
48
+ };
49
+ const contextUser = RequestContext.currentUser() ?? req.user ?? {
50
+ id: `wechat-personal:${integration.id}:anonymous`,
51
+ tenantId: integration.tenantId,
52
+ organizationId: integration.organizationId
53
+ };
54
+ const requestHeaders = {
55
+ ['tenant-id']: integration.tenantId,
56
+ ['organization-id']: integration.organizationId
57
+ };
58
+ if (integration.options?.preferLanguage) {
59
+ requestHeaders.language = integration.options.preferLanguage;
60
+ }
61
+ await new Promise((resolve, reject) => {
62
+ runWithRequestContext({
63
+ user: contextUser,
64
+ headers: requestHeaders
65
+ }, {}, () => {
66
+ this.conversation.handleInboundEvent(event, ctx).then(() => resolve()).catch(reject);
67
+ });
68
+ });
69
+ return 'success';
70
+ }
71
+ async getIntegrationSelectOptions(req, keyword) {
72
+ const options = await this.fetchProviderSelectOptions(req, WECHAT_PERSONAL_PROVIDER_KEY);
73
+ const normalizedKeyword = this.toSafeString(keyword).toLowerCase();
74
+ if (!normalizedKeyword) {
75
+ return options;
76
+ }
77
+ return options.filter((item) => {
78
+ const label = item.label.toLowerCase();
79
+ const value = item.value.toLowerCase();
80
+ const description = this.toSafeString(item.description).toLowerCase();
81
+ return label.includes(normalizedKeyword) || value.includes(normalizedKeyword) || description.includes(normalizedKeyword);
82
+ });
83
+ }
84
+ async getCallbackConfig(integrationId) {
85
+ const integration = await this.readWechatPersonalIntegration(integrationId);
86
+ return this.conversation.buildCallbackConfig(integration.id, integration.options?.callbackSecret);
87
+ }
88
+ async registerCallback(integrationId, uuid, body) {
89
+ const integration = await this.readWechatPersonalIntegration(integrationId);
90
+ const callbackConfig = this.conversation.buildCallbackConfig(integration.id, integration.options?.callbackSecret);
91
+ const result = await this.wechatChannel.registerCallback({
92
+ integrationId: integration.id,
93
+ uuid,
94
+ callbackUrl: normalizeString(body?.callbackUrl) || callbackConfig.webhookUrl,
95
+ enabled: body?.enabled !== false
96
+ });
97
+ if (!result.success) {
98
+ throw new BadRequestException(result.error || 'Register wx2.0 callback failed');
99
+ }
100
+ return result;
101
+ }
102
+ async sendText(integrationId, body) {
103
+ const integration = await this.readWechatPersonalIntegration(integrationId);
104
+ const result = await this.wechatChannel.sendTextByIntegrationId(integration.id, {
105
+ uuid: body?.uuid,
106
+ contactId: body?.contactId || body?.contactid,
107
+ content: body?.text || body?.content || body?.textcontent || '',
108
+ atUsers: Array.isArray(body?.atUsers) ? body.atUsers : Array.isArray(body?.atusers) ? body.atusers : []
109
+ });
110
+ if (!result.success) {
111
+ throw new BadRequestException(result.error || 'Send wx2.0 text failed');
112
+ }
113
+ return result;
114
+ }
115
+ async readWechatPersonalIntegration(integrationId) {
116
+ const integration = await this.integrationPermissionService.read(integrationId, {
117
+ relations: ['tenant']
118
+ });
119
+ if (!integration) {
120
+ throw new BadRequestException(`Integration ${integrationId} not found. Please save the personal WeChat integration first.`);
121
+ }
122
+ if (integration.provider !== WECHAT_PERSONAL_PROVIDER_KEY) {
123
+ throw new BadRequestException(`Integration ${integrationId} is not provider '${WECHAT_PERSONAL_PROVIDER_KEY}'`);
124
+ }
125
+ return integration;
126
+ }
127
+ verifyCallbackSecret(integration, req, querySecret) {
128
+ const expected = this.toSafeString(integration.options?.callbackSecret);
129
+ if (!expected) {
130
+ return;
131
+ }
132
+ const provided = this.toSafeString(querySecret) ||
133
+ this.toSafeString(req.headers['x-wechat-callback-secret']) ||
134
+ this.toSafeString(req.headers['x-xpert-callback-secret']);
135
+ if (provided !== expected) {
136
+ throw new BadRequestException('Invalid personal WeChat callback secret');
137
+ }
138
+ }
139
+ async fetchProviderSelectOptions(req, provider) {
140
+ try {
141
+ const host = this.toSafeString(req.get('host'));
142
+ if (!host) {
143
+ return [];
144
+ }
145
+ const protocol = this.toSafeString(req.protocol) || 'http';
146
+ const url = new URL(`${protocol}://${host}/api/integration/select-options`);
147
+ url.searchParams.set('provider', provider);
148
+ const headers = {};
149
+ const authorization = this.toSafeString(req.headers?.authorization);
150
+ const organizationId = this.toSafeString(req.headers?.['organization-id']);
151
+ const tenantId = this.toSafeString(req.headers?.['tenant-id']);
152
+ const language = this.toSafeString(req.headers?.language);
153
+ if (authorization) {
154
+ headers.authorization = authorization;
155
+ }
156
+ if (organizationId) {
157
+ headers['organization-id'] = organizationId;
158
+ }
159
+ if (tenantId) {
160
+ headers['tenant-id'] = tenantId;
161
+ }
162
+ if (language) {
163
+ headers.language = language;
164
+ }
165
+ const response = await fetch(url.toString(), {
166
+ method: 'GET',
167
+ headers
168
+ });
169
+ if (!response.ok) {
170
+ return [];
171
+ }
172
+ const payload = (await response.json().catch(() => null));
173
+ if (!Array.isArray(payload)) {
174
+ return [];
175
+ }
176
+ return payload
177
+ .map((item) => (item && typeof item === 'object' ? item : null))
178
+ .filter((item) => Boolean(item))
179
+ .map((item) => ({
180
+ value: this.toSafeString(item.value),
181
+ label: this.toSafeString(item.label) || this.toSafeString(item.value),
182
+ description: this.toSafeString(item.description) || undefined,
183
+ icon: this.toSafeString(item.icon) || undefined
184
+ }))
185
+ .filter((item) => Boolean(item.value));
186
+ }
187
+ catch {
188
+ return [];
189
+ }
190
+ }
191
+ parseBodyToObject(body) {
192
+ if (!body) {
193
+ return null;
194
+ }
195
+ if (typeof body === 'string') {
196
+ const text = body.trim();
197
+ if (!text) {
198
+ return null;
199
+ }
200
+ try {
201
+ return JSON.parse(text);
202
+ }
203
+ catch {
204
+ return null;
205
+ }
206
+ }
207
+ if (typeof body === 'object') {
208
+ return body;
209
+ }
210
+ return null;
211
+ }
212
+ toSafeString(value) {
213
+ if (Array.isArray(value)) {
214
+ return this.toSafeString(value[0]);
215
+ }
216
+ return typeof value === 'string' ? value.trim() : '';
217
+ }
218
+ };
219
+ __decorate([
220
+ Public(),
221
+ Post('webhook/:id'),
222
+ HttpCode(200),
223
+ Header('Content-Type', 'text/plain; charset=utf-8'),
224
+ __param(0, Param('id')),
225
+ __param(1, Request()),
226
+ __param(2, Body()),
227
+ __param(3, Query('secret')),
228
+ __metadata("design:type", Function),
229
+ __metadata("design:paramtypes", [String, Object, Object, String]),
230
+ __metadata("design:returntype", Promise)
231
+ ], WechatPersonalController.prototype, "webhook", null);
232
+ __decorate([
233
+ Get('integration-select-options'),
234
+ __param(0, Request()),
235
+ __param(1, Query('keyword')),
236
+ __metadata("design:type", Function),
237
+ __metadata("design:paramtypes", [Object, String]),
238
+ __metadata("design:returntype", Promise)
239
+ ], WechatPersonalController.prototype, "getIntegrationSelectOptions", null);
240
+ __decorate([
241
+ Get(':integrationId/callback-config'),
242
+ __param(0, Param('integrationId')),
243
+ __metadata("design:type", Function),
244
+ __metadata("design:paramtypes", [String]),
245
+ __metadata("design:returntype", Promise)
246
+ ], WechatPersonalController.prototype, "getCallbackConfig", null);
247
+ __decorate([
248
+ Post(':integrationId/accounts/:uuid/register-callback'),
249
+ __param(0, Param('integrationId')),
250
+ __param(1, Param('uuid')),
251
+ __param(2, Body()),
252
+ __metadata("design:type", Function),
253
+ __metadata("design:paramtypes", [String, String, Object]),
254
+ __metadata("design:returntype", Promise)
255
+ ], WechatPersonalController.prototype, "registerCallback", null);
256
+ __decorate([
257
+ Post(':integrationId/send-text'),
258
+ __param(0, Param('integrationId')),
259
+ __param(1, Body()),
260
+ __metadata("design:type", Function),
261
+ __metadata("design:paramtypes", [String, Object]),
262
+ __metadata("design:returntype", Promise)
263
+ ], WechatPersonalController.prototype, "sendText", null);
264
+ WechatPersonalController = __decorate([
265
+ Controller('wechat-personal'),
266
+ __param(2, Inject(WECHAT_PERSONAL_PLUGIN_CONTEXT)),
267
+ __metadata("design:paramtypes", [WechatPersonalConversationService,
268
+ WechatPersonalChannelStrategy, Object])
269
+ ], WechatPersonalController);
270
+ export { WechatPersonalController };
@@ -0,0 +1,20 @@
1
+ import { TAgentMiddlewareMeta } from '@xpert-ai/contracts';
2
+ import { AgentMiddleware, IAgentMiddlewareContext, IAgentMiddlewareStrategy, PromiseOrValue } from '@xpert-ai/plugin-sdk';
3
+ import { WechatPersonalConversationService } from './conversation.service.js';
4
+ import { WechatPersonalChannelStrategy } from './wechat-personal-channel.strategy.js';
5
+ type WechatPersonalRuntimeMiddlewareOptions = {
6
+ integrationId?: string;
7
+ };
8
+ export declare class WechatPersonalRuntimeMiddleware implements IAgentMiddlewareStrategy<WechatPersonalRuntimeMiddlewareOptions> {
9
+ private readonly conversationService;
10
+ private readonly wechatChannel;
11
+ readonly meta: TAgentMiddlewareMeta;
12
+ constructor(conversationService: WechatPersonalConversationService, wechatChannel: WechatPersonalChannelStrategy);
13
+ createMiddleware(options: WechatPersonalRuntimeMiddlewareOptions, context: IAgentMiddlewareContext): PromiseOrValue<AgentMiddleware>;
14
+ private resolveIntegrationId;
15
+ private safeJson;
16
+ private success;
17
+ private error;
18
+ private missingIntegrationId;
19
+ }
20
+ export {};
@@ -0,0 +1,267 @@
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
+ import { Injectable } from '@nestjs/common';
11
+ import { tool } from '@langchain/core/tools';
12
+ import { AgentMiddlewareStrategy } from '@xpert-ai/plugin-sdk';
13
+ import { z } from 'zod/v3';
14
+ import { WECHAT_PERSONAL_FEATURE, WECHAT_PERSONAL_GET_CALLBACK_CONFIG_TOOL_NAME, WECHAT_PERSONAL_GET_RUNTIME_STATUS_TOOL_NAME, WECHAT_PERSONAL_ICON, WECHAT_PERSONAL_LIST_ACCOUNTS_TOOL_NAME, WECHAT_PERSONAL_LIST_CONVERSATIONS_TOOL_NAME, WECHAT_PERSONAL_MIDDLEWARE_NAME, WECHAT_PERSONAL_REGISTER_CALLBACK_TOOL_NAME, WECHAT_PERSONAL_RESET_CONVERSATION_TOOL_NAME, WECHAT_PERSONAL_RUNTIME_FEATURE, WECHAT_PERSONAL_SEARCH_MESSAGE_LOGS_TOOL_NAME, WECHAT_PERSONAL_SET_ACCOUNT_ENABLED_TOOL_NAME, WECHAT_PERSONAL_WORKBENCH_FEATURE } from './constants.js';
15
+ import { normalizeString } from './types.js';
16
+ import { WechatPersonalConversationService } from './conversation.service.js';
17
+ import { WechatPersonalChannelStrategy } from './wechat-personal-channel.strategy.js';
18
+ const integrationField = z.string().optional().describe('Personal WeChat integration id. Defaults to the middleware node option.');
19
+ const runtimeStatusSchema = z.object({
20
+ integrationId: integrationField
21
+ });
22
+ const callbackConfigSchema = z.object({
23
+ integrationId: integrationField
24
+ });
25
+ const listAccountsSchema = z.object({
26
+ integrationId: integrationField,
27
+ search: z.string().optional().describe('Keyword for uuid, owner wxid, display name, status or last error.'),
28
+ page: z.number().int().min(1).optional().describe('Page number. Defaults to 1.'),
29
+ pageSize: z.number().int().min(1).max(100).optional().describe('Page size. Defaults to 50.')
30
+ });
31
+ const listConversationsSchema = z.object({
32
+ integrationId: integrationField,
33
+ search: z.string().optional().describe('Keyword for account uuid, contact id, sender id, xpert id or conversation id.'),
34
+ page: z.number().int().min(1).optional().describe('Page number. Defaults to 1.'),
35
+ pageSize: z.number().int().min(1).max(100).optional().describe('Page size. Defaults to 50.')
36
+ });
37
+ const searchMessageLogsSchema = z.object({
38
+ integrationId: integrationField,
39
+ direction: z.enum(['inbound', 'outbound', 'system']).optional().describe('Message direction filter.'),
40
+ status: z.enum(['received', 'dispatched', 'sent', 'skipped', 'failed']).optional().describe('Message status filter.'),
41
+ search: z.string().optional().describe('Keyword for contact, sender, message id, content, error or conversation id.'),
42
+ page: z.number().int().min(1).optional().describe('Page number. Defaults to 1.'),
43
+ pageSize: z.number().int().min(1).max(100).optional().describe('Page size. Defaults to 50.')
44
+ });
45
+ const resetConversationSchema = z.object({
46
+ integrationId: integrationField,
47
+ bindingId: z.string().min(1).describe('Conversation binding id returned by wechat_personal_list_conversations.')
48
+ });
49
+ const registerCallbackSchema = z.object({
50
+ integrationId: integrationField,
51
+ uuid: z.string().min(1).describe('wx2.0 account uuid/key.'),
52
+ callbackUrl: z.string().optional().describe('Optional callback URL. Defaults to the Xpert webhook URL.'),
53
+ enabled: z.boolean().optional().describe('Whether the wx2.0 per-account callback should be enabled. Defaults to true.')
54
+ });
55
+ const setAccountEnabledSchema = z.object({
56
+ integrationId: integrationField,
57
+ uuid: z.string().min(1).describe('wx2.0 account uuid/key.'),
58
+ enabled: z.boolean().describe('Whether this account should accept inbound callbacks.')
59
+ });
60
+ let WechatPersonalRuntimeMiddleware = class WechatPersonalRuntimeMiddleware {
61
+ constructor(conversationService, wechatChannel) {
62
+ this.conversationService = conversationService;
63
+ this.wechatChannel = wechatChannel;
64
+ this.meta = {
65
+ name: WECHAT_PERSONAL_MIDDLEWARE_NAME,
66
+ label: {
67
+ en_US: 'Personal WeChat Runtime',
68
+ zh_Hans: '个人微信运行时'
69
+ },
70
+ description: {
71
+ en_US: 'Expose Personal WeChat workbench discovery and runtime management tools to an assistant.',
72
+ zh_Hans: '为助手暴露个人微信工作台发现能力和运行时管理工具。'
73
+ },
74
+ icon: {
75
+ type: 'svg',
76
+ value: WECHAT_PERSONAL_ICON,
77
+ color: '#16a34a'
78
+ },
79
+ features: [WECHAT_PERSONAL_FEATURE, WECHAT_PERSONAL_RUNTIME_FEATURE, WECHAT_PERSONAL_WORKBENCH_FEATURE],
80
+ configSchema: {
81
+ type: 'object',
82
+ properties: {
83
+ integrationId: {
84
+ type: 'string',
85
+ title: {
86
+ en_US: 'Personal WeChat Integration',
87
+ zh_Hans: '个人微信集成'
88
+ },
89
+ 'x-ui': {
90
+ component: 'remoteSelect',
91
+ selectUrl: '/api/wechat-personal/integration-select-options'
92
+ }
93
+ }
94
+ },
95
+ required: []
96
+ }
97
+ };
98
+ }
99
+ createMiddleware(options, context) {
100
+ return {
101
+ name: WECHAT_PERSONAL_MIDDLEWARE_NAME,
102
+ tools: [
103
+ tool(async (input) => this.safeJson(async () => {
104
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
105
+ return this.success(integrationId
106
+ ? 'Personal WeChat runtime status was returned.'
107
+ : 'Organization Personal WeChat runtime status was returned.', integrationId
108
+ ? await this.conversationService.getRuntimeStatus(integrationId)
109
+ : await this.conversationService.getOrganizationRuntimeStatus());
110
+ }), {
111
+ name: WECHAT_PERSONAL_GET_RUNTIME_STATUS_TOOL_NAME,
112
+ description: 'Get Personal WeChat runtime status: callback URLs, trigger binding, summary counts, recent accounts and recent errors. Use for setup and operations questions.',
113
+ schema: runtimeStatusSchema
114
+ }),
115
+ tool(async (input) => this.safeJson(async () => {
116
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
117
+ if (!integrationId) {
118
+ return this.success('Organization Personal WeChat callback configurations were returned.', (await this.conversationService.getOrganizationWorkbenchData({ pageSize: 1 })).integrations?.map((integration) => ({
119
+ id: integration.id,
120
+ name: integration.name,
121
+ callbackConfig: integration.callbackConfig
122
+ })) ?? []);
123
+ }
124
+ const integration = await this.wechatChannel.readIntegrationById(integrationId);
125
+ if (!integration) {
126
+ return this.error(`Personal WeChat integration "${integrationId}" was not found.`);
127
+ }
128
+ return this.success('Personal WeChat callback configuration was returned.', this.conversationService.buildCallbackConfig(integration.id, integration.options?.callbackSecret));
129
+ }), {
130
+ name: WECHAT_PERSONAL_GET_CALLBACK_CONFIG_TOOL_NAME,
131
+ description: 'Get the Xpert webhook URL and SetCallback curl template for configuring wx2.0 callbacks.',
132
+ schema: callbackConfigSchema
133
+ }),
134
+ tool(async (input) => this.safeJson(async () => {
135
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
136
+ return this.success(integrationId ? 'Personal WeChat accounts were listed.' : 'Organization Personal WeChat accounts were listed.', integrationId
137
+ ? await this.conversationService.listAccounts(integrationId, input)
138
+ : await this.conversationService.listOrganizationAccounts(input));
139
+ }), {
140
+ name: WECHAT_PERSONAL_LIST_ACCOUNTS_TOOL_NAME,
141
+ description: 'List wx2.0 personal WeChat accounts captured by callbacks, including enabled state, online status and recent errors.',
142
+ schema: listAccountsSchema
143
+ }),
144
+ tool(async (input) => this.safeJson(async () => {
145
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
146
+ return this.success(integrationId
147
+ ? 'Personal WeChat conversation bindings were listed.'
148
+ : 'Organization Personal WeChat conversation bindings were listed.', integrationId
149
+ ? await this.conversationService.listConversations(integrationId, input)
150
+ : await this.conversationService.listOrganizationConversations(input));
151
+ }), {
152
+ name: WECHAT_PERSONAL_LIST_CONVERSATIONS_TOOL_NAME,
153
+ description: 'List Personal WeChat conversation bindings. Use this to find a binding id before resetting a conversation.',
154
+ schema: listConversationsSchema
155
+ }),
156
+ tool(async (input) => this.safeJson(async () => {
157
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
158
+ return this.success(integrationId
159
+ ? 'Personal WeChat message logs were searched.'
160
+ : 'Organization Personal WeChat message logs were searched.', integrationId
161
+ ? await this.conversationService.searchMessageLogs(integrationId, input)
162
+ : await this.conversationService.searchOrganizationMessageLogs(input));
163
+ }), {
164
+ name: WECHAT_PERSONAL_SEARCH_MESSAGE_LOGS_TOOL_NAME,
165
+ description: 'Search inbound, outbound and system Personal WeChat message logs for diagnostics and audit questions.',
166
+ schema: searchMessageLogsSchema
167
+ }),
168
+ tool(async (input) => this.safeJson(async () => {
169
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
170
+ if (!integrationId) {
171
+ return this.missingIntegrationId();
172
+ }
173
+ await this.conversationService.restartConversationBinding(integrationId, input.bindingId);
174
+ return this.success('Personal WeChat conversation was reset.', {
175
+ bindingId: input.bindingId
176
+ });
177
+ }), {
178
+ name: WECHAT_PERSONAL_RESET_CONVERSATION_TOOL_NAME,
179
+ description: 'Reset one Personal WeChat conversation binding by binding id so the next inbound message starts a fresh Agent conversation.',
180
+ schema: resetConversationSchema
181
+ }),
182
+ tool(async (input) => this.safeJson(async () => {
183
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
184
+ if (!integrationId) {
185
+ return this.missingIntegrationId();
186
+ }
187
+ const integration = await this.wechatChannel.readIntegrationById(integrationId);
188
+ if (!integration) {
189
+ return this.error(`Personal WeChat integration "${integrationId}" was not found.`);
190
+ }
191
+ const callbackConfig = this.conversationService.buildCallbackConfig(integration.id, integration.options?.callbackSecret);
192
+ const result = await this.wechatChannel.registerCallback({
193
+ integrationId: integration.id,
194
+ uuid: input.uuid,
195
+ callbackUrl: normalizeString(input.callbackUrl) || callbackConfig.webhookUrl,
196
+ enabled: input.enabled !== false
197
+ });
198
+ return result.success
199
+ ? this.success('wx2.0 SetCallback registration succeeded.', result)
200
+ : this.error(result.error || 'wx2.0 SetCallback registration failed.', result);
201
+ }), {
202
+ name: WECHAT_PERSONAL_REGISTER_CALLBACK_TOOL_NAME,
203
+ description: 'Register or update a wx2.0 per-account callback for a known account uuid/key. This is an administrative setup action.',
204
+ schema: registerCallbackSchema
205
+ }),
206
+ tool(async (input) => this.safeJson(async () => {
207
+ const integrationId = await this.resolveIntegrationId(input.integrationId, options, context);
208
+ if (!integrationId) {
209
+ return this.missingIntegrationId();
210
+ }
211
+ await this.conversationService.setAccountEnabled(integrationId, input.uuid, input.enabled);
212
+ return this.success('Personal WeChat account enabled state was updated.', {
213
+ uuid: input.uuid,
214
+ enabled: input.enabled
215
+ });
216
+ }), {
217
+ name: WECHAT_PERSONAL_SET_ACCOUNT_ENABLED_TOOL_NAME,
218
+ description: 'Enable or disable inbound processing for one wx2.0 personal WeChat account already seen by this integration.',
219
+ schema: setAccountEnabledSchema
220
+ })
221
+ ]
222
+ };
223
+ }
224
+ async resolveIntegrationId(inputIntegrationId, options, context) {
225
+ const nodeOptions = context.node?.options;
226
+ const explicitIntegrationId = normalizeString(inputIntegrationId) ||
227
+ normalizeString(options?.integrationId) ||
228
+ normalizeString(nodeOptions?.integrationId);
229
+ if (explicitIntegrationId) {
230
+ return explicitIntegrationId;
231
+ }
232
+ const xpertId = normalizeString(context.xpertId);
233
+ return xpertId ? this.conversationService.getBoundIntegrationIdForXpert(xpertId) : null;
234
+ }
235
+ async safeJson(factory) {
236
+ try {
237
+ return JSON.stringify(await factory(), null, 2);
238
+ }
239
+ catch (err) {
240
+ return JSON.stringify(this.error(err instanceof Error ? err.message : String(err)), null, 2);
241
+ }
242
+ }
243
+ success(message, data) {
244
+ return {
245
+ success: true,
246
+ message,
247
+ data
248
+ };
249
+ }
250
+ error(message, data) {
251
+ return {
252
+ success: false,
253
+ message,
254
+ data
255
+ };
256
+ }
257
+ missingIntegrationId() {
258
+ return this.error('Missing Personal WeChat integrationId. Select an integration in the middleware options first.');
259
+ }
260
+ };
261
+ WechatPersonalRuntimeMiddleware = __decorate([
262
+ Injectable(),
263
+ AgentMiddlewareStrategy(WECHAT_PERSONAL_MIDDLEWARE_NAME),
264
+ __metadata("design:paramtypes", [WechatPersonalConversationService,
265
+ WechatPersonalChannelStrategy])
266
+ ], WechatPersonalRuntimeMiddleware);
267
+ export { WechatPersonalRuntimeMiddleware };
@@ -0,0 +1,2 @@
1
+ export declare class WechatPersonalPlugin {
2
+ }
@@ -0,0 +1,58 @@
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
+ import { XpertServerPlugin } from '@xpert-ai/plugin-sdk';
8
+ import { TypeOrmModule } from '@nestjs/typeorm';
9
+ import { DiscoveryModule } from '@nestjs/core';
10
+ import { WechatPersonalController } from './wechat-personal.controller.js';
11
+ import { WechatPersonalConversationService } from './conversation.service.js';
12
+ import { WechatPersonalClient } from './wechat-personal.client.js';
13
+ import { WechatPersonalChannelStrategy } from './wechat-personal-channel.strategy.js';
14
+ import { WechatPersonalIntegrationStrategy } from './wechat-personal-integration.strategy.js';
15
+ import { WechatPersonalAccountEntity, WechatPersonalConversationBindingEntity, WechatPersonalMessageLogEntity, WechatPersonalTriggerBindingEntity } from './entities/index.js';
16
+ import { WechatPersonalChatCallbackProcessor, WechatPersonalChatDispatchService, WechatPersonalChatRunStateService } from './handoff/index.js';
17
+ import { WechatPersonalTriggerAggregationService, WechatPersonalTriggerFlushProcessor, WechatPersonalTriggerStrategy } from './workflow/index.js';
18
+ import { WechatPersonalViewProvider } from './views/wechat-personal-view.provider.js';
19
+ import { WechatPersonalRuntimeMiddleware } from './wechat-personal.middleware.js';
20
+ const entities = [
21
+ WechatPersonalTriggerBindingEntity,
22
+ WechatPersonalConversationBindingEntity,
23
+ WechatPersonalAccountEntity,
24
+ WechatPersonalMessageLogEntity
25
+ ];
26
+ let WechatPersonalPlugin = class WechatPersonalPlugin {
27
+ };
28
+ WechatPersonalPlugin = __decorate([
29
+ XpertServerPlugin({
30
+ imports: [DiscoveryModule, TypeOrmModule.forFeature(entities)],
31
+ entities,
32
+ providers: [
33
+ WechatPersonalClient,
34
+ WechatPersonalConversationService,
35
+ WechatPersonalChannelStrategy,
36
+ WechatPersonalIntegrationStrategy,
37
+ WechatPersonalTriggerStrategy,
38
+ WechatPersonalTriggerAggregationService,
39
+ WechatPersonalTriggerFlushProcessor,
40
+ WechatPersonalChatDispatchService,
41
+ WechatPersonalChatRunStateService,
42
+ WechatPersonalChatCallbackProcessor,
43
+ WechatPersonalRuntimeMiddleware,
44
+ WechatPersonalViewProvider
45
+ ],
46
+ controllers: [WechatPersonalController],
47
+ exports: [
48
+ WechatPersonalClient,
49
+ WechatPersonalChannelStrategy,
50
+ WechatPersonalIntegrationStrategy,
51
+ WechatPersonalTriggerStrategy,
52
+ WechatPersonalConversationService,
53
+ WechatPersonalRuntimeMiddleware,
54
+ WechatPersonalViewProvider
55
+ ]
56
+ })
57
+ ], WechatPersonalPlugin);
58
+ export { WechatPersonalPlugin };
@@ -0,0 +1,2 @@
1
+ import type { XpertTemplateContribution } from '@xpert-ai/plugin-sdk';
2
+ export declare const wechatPersonalTemplates: XpertTemplateContribution[];