crewly 1.4.69 → 1.4.70
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/dist/backend/backend/src/constants.d.ts +1 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +1 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +4 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
- package/dist/backend/backend/src/middleware/require-auth.middleware.d.ts +17 -9
- package/dist/backend/backend/src/middleware/require-auth.middleware.d.ts.map +1 -1
- package/dist/backend/backend/src/middleware/require-auth.middleware.js +60 -10
- package/dist/backend/backend/src/middleware/require-auth.middleware.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +3 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +6 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js +14 -2
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/wechat-messenger.adapter.d.ts +47 -0
- package/dist/backend/backend/src/services/messaging/adapters/wechat-messenger.adapter.d.ts.map +1 -0
- package/dist/backend/backend/src/services/messaging/adapters/wechat-messenger.adapter.js +69 -0
- package/dist/backend/backend/src/services/messaging/adapters/wechat-messenger.adapter.js.map +1 -0
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wechat/wechat-bridge.service.d.ts +69 -0
- package/dist/backend/backend/src/services/wechat/wechat-bridge.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wechat/wechat-bridge.service.js +133 -0
- package/dist/backend/backend/src/services/wechat/wechat-bridge.service.js.map +1 -0
- package/dist/backend/backend/src/services/wechat/wechat.controller.d.ts +51 -0
- package/dist/backend/backend/src/services/wechat/wechat.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wechat/wechat.controller.js +104 -0
- package/dist/backend/backend/src/services/wechat/wechat.controller.js.map +1 -0
- package/dist/backend/backend/src/services/wechat/wechat.service.d.ts +171 -0
- package/dist/backend/backend/src/services/wechat/wechat.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wechat/wechat.service.js +411 -0
- package/dist/backend/backend/src/services/wechat/wechat.service.js.map +1 -0
- package/dist/cli/backend/src/constants.d.ts +1 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +1 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat Messenger Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements the MessengerAdapter interface for the WeChat iLink Bot.
|
|
5
|
+
* Delegates to WeChatService for actual operations.
|
|
6
|
+
*
|
|
7
|
+
* @module services/messaging/adapters/wechat-messenger.adapter
|
|
8
|
+
*/
|
|
9
|
+
import { getWeChatService } from '../../wechat/wechat.service.js';
|
|
10
|
+
import { WeChatBridge } from '../../wechat/wechat-bridge.service.js';
|
|
11
|
+
/**
|
|
12
|
+
* Messenger adapter for WeChat using the iLink Bot API.
|
|
13
|
+
*/
|
|
14
|
+
export class WeChatMessengerAdapter {
|
|
15
|
+
platform = 'wechat';
|
|
16
|
+
/**
|
|
17
|
+
* Initialize the adapter by restoring persisted WeChat connection.
|
|
18
|
+
*
|
|
19
|
+
* @param config - Configuration (unused — token loaded from disk)
|
|
20
|
+
*/
|
|
21
|
+
async initialize(config) {
|
|
22
|
+
const service = getWeChatService();
|
|
23
|
+
await service.tryRestore();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Send a text message via WeChat.
|
|
27
|
+
*
|
|
28
|
+
* Uses the WeChatBridge to find the context token for the channel
|
|
29
|
+
* (conversation ID) and send the reply.
|
|
30
|
+
*
|
|
31
|
+
* @param channel - Conversation ID (e.g., "wechat-user123")
|
|
32
|
+
* @param text - Message content
|
|
33
|
+
* @param _options - Send options (unused for WeChat)
|
|
34
|
+
*/
|
|
35
|
+
async sendMessage(channel, text, _options) {
|
|
36
|
+
const bridge = WeChatBridge.getInstance();
|
|
37
|
+
const contextToken = bridge.getContextToken(channel);
|
|
38
|
+
if (!contextToken) {
|
|
39
|
+
throw new Error(`No WeChat context token for channel: ${channel}`);
|
|
40
|
+
}
|
|
41
|
+
const service = getWeChatService();
|
|
42
|
+
await service.sendMessage(text, contextToken);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the current connection status.
|
|
46
|
+
*
|
|
47
|
+
* @returns Status object with connection state
|
|
48
|
+
*/
|
|
49
|
+
getStatus() {
|
|
50
|
+
const service = getWeChatService();
|
|
51
|
+
const status = service.getStatus();
|
|
52
|
+
return {
|
|
53
|
+
connected: service.isConnected(),
|
|
54
|
+
platform: this.platform,
|
|
55
|
+
details: {
|
|
56
|
+
state: status.state,
|
|
57
|
+
botName: status.botName,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Disconnect the WeChat service.
|
|
63
|
+
*/
|
|
64
|
+
async disconnect() {
|
|
65
|
+
const service = getWeChatService();
|
|
66
|
+
service.disconnect();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=wechat-messenger.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-messenger.adapter.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/messaging/adapters/wechat-messenger.adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAGrE;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACxB,QAAQ,GAAG,QAA6B,CAAC;IAElD;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,MAA+B;QAC9C,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAAY,EAAE,QAAsB;QACrE,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAErD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,wCAAwC,OAAO,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACH,SAAS;QACP,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QAEnC,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE;YAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE;gBACP,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB;SACF,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,OAAO,CAAC,UAAU,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Supported messenger platforms.
|
|
3
3
|
*/
|
|
4
|
-
export type MessengerPlatform = 'slack' | 'telegram' | 'discord' | 'google-chat';
|
|
4
|
+
export type MessengerPlatform = 'slack' | 'telegram' | 'discord' | 'google-chat' | 'wechat';
|
|
5
5
|
/**
|
|
6
6
|
* A message received from any messenger platform.
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messenger-adapter.interface.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/messaging/messenger-adapter.interface.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"messenger-adapter.interface.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/messaging/messenger-adapter.interface.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,kEAAkE;IAClE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,mDAAmD;IACnD,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,wCAAwC;IACxC,SAAS,IAAI;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,iBAAiB,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACpG,wCAAwC;IACxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat Orchestrator Bridge
|
|
3
|
+
*
|
|
4
|
+
* Routes incoming WeChat messages to the orchestrator message queue
|
|
5
|
+
* and sends orchestrator replies back via WeChat.
|
|
6
|
+
*
|
|
7
|
+
* Similar to SlackOrchestratorBridge but for the WeChat iLink Bot channel.
|
|
8
|
+
*
|
|
9
|
+
* @module services/wechat/wechat-bridge.service
|
|
10
|
+
*/
|
|
11
|
+
/** Minimal interface for MessageQueueService to avoid circular imports. */
|
|
12
|
+
interface IMessageQueueServiceLike {
|
|
13
|
+
enqueue(input: {
|
|
14
|
+
content: string;
|
|
15
|
+
conversationId: string;
|
|
16
|
+
source: 'wechat';
|
|
17
|
+
sourceMetadata?: Record<string, string>;
|
|
18
|
+
}): unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Bridge between WeChat messages and the orchestrator.
|
|
22
|
+
*
|
|
23
|
+
* Listens for 'message' events from WeChatService and enqueues them
|
|
24
|
+
* into the orchestrator message queue. Stores context_token per
|
|
25
|
+
* conversation so replies can be routed back through WeChat.
|
|
26
|
+
*/
|
|
27
|
+
export declare class WeChatBridge {
|
|
28
|
+
private static instance;
|
|
29
|
+
private readonly logger;
|
|
30
|
+
private messageQueue;
|
|
31
|
+
private contextTokens;
|
|
32
|
+
private initialized;
|
|
33
|
+
private constructor();
|
|
34
|
+
/**
|
|
35
|
+
* Get the singleton instance.
|
|
36
|
+
*
|
|
37
|
+
* @returns WeChatBridge instance
|
|
38
|
+
*/
|
|
39
|
+
static getInstance(): WeChatBridge;
|
|
40
|
+
/**
|
|
41
|
+
* Initialize the bridge with the message queue service.
|
|
42
|
+
*
|
|
43
|
+
* @param messageQueue - The orchestrator message queue for enqueuing messages
|
|
44
|
+
*/
|
|
45
|
+
initialize(messageQueue: IMessageQueueServiceLike): void;
|
|
46
|
+
/**
|
|
47
|
+
* Send a reply back to WeChat using the stored context token.
|
|
48
|
+
*
|
|
49
|
+
* @param conversationId - The conversation ID to reply to
|
|
50
|
+
* @param text - Reply text
|
|
51
|
+
* @returns True if sent successfully
|
|
52
|
+
*/
|
|
53
|
+
sendReply(conversationId: string, text: string): Promise<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Get the stored context token for a conversation.
|
|
56
|
+
*
|
|
57
|
+
* @param conversationId - Conversation ID
|
|
58
|
+
* @returns Context token or undefined
|
|
59
|
+
*/
|
|
60
|
+
getContextToken(conversationId: string): string | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Handle an incoming WeChat message by enqueuing it for the orchestrator.
|
|
63
|
+
*
|
|
64
|
+
* @param msg - Incoming WeChat message
|
|
65
|
+
*/
|
|
66
|
+
private handleIncomingMessage;
|
|
67
|
+
}
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=wechat-bridge.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-bridge.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wechat/wechat-bridge.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,2EAA2E;AAC3E,UAAU,wBAAwB;IAChC,OAAO,CAAC,KAAK,EAAE;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,QAAQ,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACzC,GAAG,OAAO,CAAC;CACb;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO;IAIP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,YAAY;IAOlC;;;;OAIG;IACH,UAAU,CAAC,YAAY,EAAE,wBAAwB,GAAG,IAAI;IAgBxD;;;;;;OAMG;IACG,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBvE;;;;;OAKG;IACH,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQ3D;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;CAmC9B"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat Orchestrator Bridge
|
|
3
|
+
*
|
|
4
|
+
* Routes incoming WeChat messages to the orchestrator message queue
|
|
5
|
+
* and sends orchestrator replies back via WeChat.
|
|
6
|
+
*
|
|
7
|
+
* Similar to SlackOrchestratorBridge but for the WeChat iLink Bot channel.
|
|
8
|
+
*
|
|
9
|
+
* @module services/wechat/wechat-bridge.service
|
|
10
|
+
*/
|
|
11
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
12
|
+
import { getWeChatService } from './wechat.service.js';
|
|
13
|
+
/**
|
|
14
|
+
* Bridge between WeChat messages and the orchestrator.
|
|
15
|
+
*
|
|
16
|
+
* Listens for 'message' events from WeChatService and enqueues them
|
|
17
|
+
* into the orchestrator message queue. Stores context_token per
|
|
18
|
+
* conversation so replies can be routed back through WeChat.
|
|
19
|
+
*/
|
|
20
|
+
export class WeChatBridge {
|
|
21
|
+
static instance = null;
|
|
22
|
+
logger;
|
|
23
|
+
messageQueue = null;
|
|
24
|
+
contextTokens = new Map();
|
|
25
|
+
initialized = false;
|
|
26
|
+
constructor() {
|
|
27
|
+
this.logger = LoggerService.getInstance().createComponentLogger('WeChatBridge');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the singleton instance.
|
|
31
|
+
*
|
|
32
|
+
* @returns WeChatBridge instance
|
|
33
|
+
*/
|
|
34
|
+
static getInstance() {
|
|
35
|
+
if (!WeChatBridge.instance) {
|
|
36
|
+
WeChatBridge.instance = new WeChatBridge();
|
|
37
|
+
}
|
|
38
|
+
return WeChatBridge.instance;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Initialize the bridge with the message queue service.
|
|
42
|
+
*
|
|
43
|
+
* @param messageQueue - The orchestrator message queue for enqueuing messages
|
|
44
|
+
*/
|
|
45
|
+
initialize(messageQueue) {
|
|
46
|
+
if (this.initialized)
|
|
47
|
+
return;
|
|
48
|
+
this.messageQueue = messageQueue;
|
|
49
|
+
const wechat = getWeChatService();
|
|
50
|
+
wechat.on('message', (msg) => this.handleIncomingMessage(msg));
|
|
51
|
+
wechat.on('disconnected', () => {
|
|
52
|
+
this.logger.info('WeChat disconnected — bridge paused');
|
|
53
|
+
this.contextTokens.clear();
|
|
54
|
+
});
|
|
55
|
+
this.initialized = true;
|
|
56
|
+
this.logger.info('WeChat bridge initialized');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Send a reply back to WeChat using the stored context token.
|
|
60
|
+
*
|
|
61
|
+
* @param conversationId - The conversation ID to reply to
|
|
62
|
+
* @param text - Reply text
|
|
63
|
+
* @returns True if sent successfully
|
|
64
|
+
*/
|
|
65
|
+
async sendReply(conversationId, text) {
|
|
66
|
+
const contextToken = this.contextTokens.get(conversationId);
|
|
67
|
+
if (!contextToken) {
|
|
68
|
+
this.logger.warn('No context token for WeChat reply', { conversationId });
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const wechat = getWeChatService();
|
|
73
|
+
await wechat.sendMessage(text, contextToken);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
this.logger.error('Failed to send WeChat reply', {
|
|
78
|
+
conversationId,
|
|
79
|
+
error: err instanceof Error ? err.message : String(err),
|
|
80
|
+
});
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the stored context token for a conversation.
|
|
86
|
+
*
|
|
87
|
+
* @param conversationId - Conversation ID
|
|
88
|
+
* @returns Context token or undefined
|
|
89
|
+
*/
|
|
90
|
+
getContextToken(conversationId) {
|
|
91
|
+
return this.contextTokens.get(conversationId);
|
|
92
|
+
}
|
|
93
|
+
// -------------------------------------------------------------------------
|
|
94
|
+
// Internal
|
|
95
|
+
// -------------------------------------------------------------------------
|
|
96
|
+
/**
|
|
97
|
+
* Handle an incoming WeChat message by enqueuing it for the orchestrator.
|
|
98
|
+
*
|
|
99
|
+
* @param msg - Incoming WeChat message
|
|
100
|
+
*/
|
|
101
|
+
handleIncomingMessage(msg) {
|
|
102
|
+
if (!this.messageQueue) {
|
|
103
|
+
this.logger.warn('Message queue not available, dropping WeChat message');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Skip non-text messages
|
|
107
|
+
if (msg.msg_type !== 'text') {
|
|
108
|
+
this.logger.debug('Skipping non-text WeChat message', { msgType: msg.msg_type });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Store context token for reply routing
|
|
112
|
+
const conversationId = `wechat-${msg.from_user}`;
|
|
113
|
+
this.contextTokens.set(conversationId, msg.context_token);
|
|
114
|
+
// Enqueue for orchestrator processing
|
|
115
|
+
this.messageQueue.enqueue({
|
|
116
|
+
content: msg.content,
|
|
117
|
+
conversationId,
|
|
118
|
+
source: 'wechat',
|
|
119
|
+
sourceMetadata: {
|
|
120
|
+
fromUser: msg.from_user,
|
|
121
|
+
fromUserName: msg.from_user_name,
|
|
122
|
+
msgId: msg.msg_id,
|
|
123
|
+
contextToken: msg.context_token,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
this.logger.info('WeChat message enqueued for orchestrator', {
|
|
127
|
+
from: msg.from_user_name,
|
|
128
|
+
conversationId,
|
|
129
|
+
contentLength: msg.content.length,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=wechat-bridge.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-bridge.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wechat/wechat-bridge.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat REST Controller
|
|
3
|
+
*
|
|
4
|
+
* HTTP endpoints for managing the WeChat iLink Bot integration.
|
|
5
|
+
*
|
|
6
|
+
* Routes:
|
|
7
|
+
* - POST /api/wechat/qrcode — Generate login QR code
|
|
8
|
+
* - GET /api/wechat/status — Get connection status
|
|
9
|
+
* - POST /api/wechat/disconnect — Disconnect WeChat
|
|
10
|
+
*
|
|
11
|
+
* @module services/wechat/wechat.controller
|
|
12
|
+
*/
|
|
13
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
14
|
+
import { Router } from 'express';
|
|
15
|
+
/**
|
|
16
|
+
* POST /api/wechat/qrcode
|
|
17
|
+
*
|
|
18
|
+
* Generate a WeChat login QR code. The frontend displays this QR code
|
|
19
|
+
* for the user to scan with their WeChat app.
|
|
20
|
+
*
|
|
21
|
+
* @param _req - Express request (no body required)
|
|
22
|
+
* @param res - Response with { success, data: { qrcodeUrl, ticket } }
|
|
23
|
+
* @param next - Next function
|
|
24
|
+
*/
|
|
25
|
+
export declare function getQRCode(_req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* GET /api/wechat/status
|
|
28
|
+
*
|
|
29
|
+
* Get the current WeChat connection status.
|
|
30
|
+
*
|
|
31
|
+
* @param _req - Express request
|
|
32
|
+
* @param res - Response with { success, data: { state, botName, connectedAt } }
|
|
33
|
+
*/
|
|
34
|
+
export declare function getStatus(_req: Request, res: Response): void;
|
|
35
|
+
/**
|
|
36
|
+
* POST /api/wechat/disconnect
|
|
37
|
+
*
|
|
38
|
+
* Disconnect the WeChat bot and clear credentials.
|
|
39
|
+
*
|
|
40
|
+
* @param _req - Express request
|
|
41
|
+
* @param res - Response with { success }
|
|
42
|
+
* @param next - Next function
|
|
43
|
+
*/
|
|
44
|
+
export declare function disconnectWeChat(_req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Create the WeChat router with all endpoints.
|
|
47
|
+
*
|
|
48
|
+
* @returns Express router for /api/wechat/*
|
|
49
|
+
*/
|
|
50
|
+
export declare function createWeChatRouter(): Router;
|
|
51
|
+
//# sourceMappingURL=wechat.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wechat/wechat.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAMjC;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB/F;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAQ5D;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CActG;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAQ3C"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat REST Controller
|
|
3
|
+
*
|
|
4
|
+
* HTTP endpoints for managing the WeChat iLink Bot integration.
|
|
5
|
+
*
|
|
6
|
+
* Routes:
|
|
7
|
+
* - POST /api/wechat/qrcode — Generate login QR code
|
|
8
|
+
* - GET /api/wechat/status — Get connection status
|
|
9
|
+
* - POST /api/wechat/disconnect — Disconnect WeChat
|
|
10
|
+
*
|
|
11
|
+
* @module services/wechat/wechat.controller
|
|
12
|
+
*/
|
|
13
|
+
import { Router } from 'express';
|
|
14
|
+
import { getWeChatService } from './wechat.service.js';
|
|
15
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
16
|
+
const logger = LoggerService.getInstance().createComponentLogger('WeChatController');
|
|
17
|
+
/**
|
|
18
|
+
* POST /api/wechat/qrcode
|
|
19
|
+
*
|
|
20
|
+
* Generate a WeChat login QR code. The frontend displays this QR code
|
|
21
|
+
* for the user to scan with their WeChat app.
|
|
22
|
+
*
|
|
23
|
+
* @param _req - Express request (no body required)
|
|
24
|
+
* @param res - Response with { success, data: { qrcodeUrl, ticket } }
|
|
25
|
+
* @param next - Next function
|
|
26
|
+
*/
|
|
27
|
+
export async function getQRCode(_req, res, next) {
|
|
28
|
+
try {
|
|
29
|
+
const service = getWeChatService();
|
|
30
|
+
const qrData = await service.getQRCode();
|
|
31
|
+
res.json({
|
|
32
|
+
success: true,
|
|
33
|
+
data: {
|
|
34
|
+
qrcodeUrl: qrData.qrcode_url,
|
|
35
|
+
ticket: qrData.qrcode_ticket,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
// Start polling for QR code status in the background
|
|
39
|
+
service.pollQRCodeStatus(qrData.qrcode_ticket).catch((err) => {
|
|
40
|
+
logger.warn('QR code status polling ended', {
|
|
41
|
+
error: err instanceof Error ? err.message : String(err),
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.error('Failed to generate WeChat QR code', {
|
|
47
|
+
error: error instanceof Error ? error.message : String(error),
|
|
48
|
+
});
|
|
49
|
+
next(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* GET /api/wechat/status
|
|
54
|
+
*
|
|
55
|
+
* Get the current WeChat connection status.
|
|
56
|
+
*
|
|
57
|
+
* @param _req - Express request
|
|
58
|
+
* @param res - Response with { success, data: { state, botName, connectedAt } }
|
|
59
|
+
*/
|
|
60
|
+
export function getStatus(_req, res) {
|
|
61
|
+
const service = getWeChatService();
|
|
62
|
+
const status = service.getStatus();
|
|
63
|
+
res.json({
|
|
64
|
+
success: true,
|
|
65
|
+
data: status,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* POST /api/wechat/disconnect
|
|
70
|
+
*
|
|
71
|
+
* Disconnect the WeChat bot and clear credentials.
|
|
72
|
+
*
|
|
73
|
+
* @param _req - Express request
|
|
74
|
+
* @param res - Response with { success }
|
|
75
|
+
* @param next - Next function
|
|
76
|
+
*/
|
|
77
|
+
export async function disconnectWeChat(_req, res, next) {
|
|
78
|
+
try {
|
|
79
|
+
const service = getWeChatService();
|
|
80
|
+
service.disconnect();
|
|
81
|
+
await service.removeConfig();
|
|
82
|
+
logger.info('WeChat disconnected');
|
|
83
|
+
res.json({ success: true });
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
logger.error('Failed to disconnect WeChat', {
|
|
87
|
+
error: error instanceof Error ? error.message : String(error),
|
|
88
|
+
});
|
|
89
|
+
next(error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create the WeChat router with all endpoints.
|
|
94
|
+
*
|
|
95
|
+
* @returns Express router for /api/wechat/*
|
|
96
|
+
*/
|
|
97
|
+
export function createWeChatRouter() {
|
|
98
|
+
const router = Router();
|
|
99
|
+
router.post('/qrcode', getQRCode);
|
|
100
|
+
router.get('/status', getStatus);
|
|
101
|
+
router.post('/disconnect', disconnectWeChat);
|
|
102
|
+
return router;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=wechat.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wechat/wechat.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat iLink Bot Service
|
|
3
|
+
*
|
|
4
|
+
* Integrates with the Tencent iLink Bot API for WeChat messaging.
|
|
5
|
+
* Supports QR code login, message polling, and sending replies.
|
|
6
|
+
*
|
|
7
|
+
* API Base: https://ilinkai.weixin.qq.com
|
|
8
|
+
* Auth: Bearer token with AuthorizationType: ilink_bot_token header
|
|
9
|
+
*
|
|
10
|
+
* @module services/wechat/wechat.service
|
|
11
|
+
*/
|
|
12
|
+
import { EventEmitter } from 'events';
|
|
13
|
+
/** Persisted WeChat config. */
|
|
14
|
+
export interface WeChatConfig {
|
|
15
|
+
botToken: string;
|
|
16
|
+
connectedAt: string;
|
|
17
|
+
botName?: string;
|
|
18
|
+
}
|
|
19
|
+
/** QR code response from iLink API. */
|
|
20
|
+
export interface QRCodeResponse {
|
|
21
|
+
qrcode_url: string;
|
|
22
|
+
qrcode_ticket: string;
|
|
23
|
+
}
|
|
24
|
+
/** QR code status from iLink API. */
|
|
25
|
+
export interface QRCodeStatus {
|
|
26
|
+
status: 'waiting' | 'scanned' | 'confirmed' | 'expired';
|
|
27
|
+
bot_token?: string;
|
|
28
|
+
bot_name?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Incoming WeChat message from getupdates. */
|
|
31
|
+
export interface WeChatMessage {
|
|
32
|
+
msg_id: string;
|
|
33
|
+
from_user: string;
|
|
34
|
+
from_user_name: string;
|
|
35
|
+
content: string;
|
|
36
|
+
msg_type: string;
|
|
37
|
+
context_token: string;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
}
|
|
40
|
+
/** Service connection state. */
|
|
41
|
+
export type WeChatConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
42
|
+
/**
|
|
43
|
+
* WeChat iLink Bot Service.
|
|
44
|
+
*
|
|
45
|
+
* Singleton service that manages the WeChat bot connection lifecycle:
|
|
46
|
+
* - QR code generation for login
|
|
47
|
+
* - Long-polling for incoming messages
|
|
48
|
+
* - Sending replies
|
|
49
|
+
* - Persisting credentials to disk
|
|
50
|
+
*
|
|
51
|
+
* Events:
|
|
52
|
+
* - `message` — Fired for each incoming WeChat message
|
|
53
|
+
* - `connected` — Fired when QR code scan is confirmed
|
|
54
|
+
* - `disconnected` — Fired when service disconnects
|
|
55
|
+
* - `error` — Fired on unrecoverable errors
|
|
56
|
+
*/
|
|
57
|
+
export declare class WeChatService extends EventEmitter {
|
|
58
|
+
private static instance;
|
|
59
|
+
private readonly logger;
|
|
60
|
+
private state;
|
|
61
|
+
private botToken;
|
|
62
|
+
private botName;
|
|
63
|
+
private pollCursor;
|
|
64
|
+
private pollTimer;
|
|
65
|
+
private isPolling;
|
|
66
|
+
private constructor();
|
|
67
|
+
/**
|
|
68
|
+
* Get the singleton instance.
|
|
69
|
+
*
|
|
70
|
+
* @returns WeChatService instance
|
|
71
|
+
*/
|
|
72
|
+
static getInstance(): WeChatService;
|
|
73
|
+
/**
|
|
74
|
+
* Reset the singleton (for testing).
|
|
75
|
+
*/
|
|
76
|
+
static resetInstance(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Get a QR code for WeChat login.
|
|
79
|
+
*
|
|
80
|
+
* Calls the iLink API to generate a QR code that the user scans
|
|
81
|
+
* with their WeChat app to authorize the bot.
|
|
82
|
+
*
|
|
83
|
+
* @returns QR code URL and ticket for status polling
|
|
84
|
+
* @throws Error if API call fails
|
|
85
|
+
*/
|
|
86
|
+
getQRCode(): Promise<QRCodeResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* Poll the QR code status until the user scans and confirms.
|
|
89
|
+
*
|
|
90
|
+
* @param ticket - QR code ticket from getQRCode()
|
|
91
|
+
* @returns Resolved when confirmed, rejected on timeout/error
|
|
92
|
+
*/
|
|
93
|
+
pollQRCodeStatus(ticket: string): Promise<{
|
|
94
|
+
botToken: string;
|
|
95
|
+
botName?: string;
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Send a message via WeChat.
|
|
99
|
+
*
|
|
100
|
+
* @param content - Message text
|
|
101
|
+
* @param contextToken - Context token from the received message (maintains thread)
|
|
102
|
+
* @throws Error if not connected or API call fails
|
|
103
|
+
*/
|
|
104
|
+
sendMessage(content: string, contextToken: string): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Get the current connection state.
|
|
107
|
+
*
|
|
108
|
+
* @returns Connection status object
|
|
109
|
+
*/
|
|
110
|
+
getStatus(): {
|
|
111
|
+
state: WeChatConnectionState;
|
|
112
|
+
botName: string | null;
|
|
113
|
+
connectedAt: string | null;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Check if the service is connected.
|
|
117
|
+
*
|
|
118
|
+
* @returns True if connected with a valid bot token
|
|
119
|
+
*/
|
|
120
|
+
isConnected(): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Disconnect and stop message polling.
|
|
123
|
+
*/
|
|
124
|
+
disconnect(): void;
|
|
125
|
+
/**
|
|
126
|
+
* Try to restore connection from persisted config.
|
|
127
|
+
*
|
|
128
|
+
* @returns True if config was loaded and connection restored
|
|
129
|
+
*/
|
|
130
|
+
tryRestore(): Promise<boolean>;
|
|
131
|
+
/**
|
|
132
|
+
* Start long-polling for incoming messages.
|
|
133
|
+
*/
|
|
134
|
+
private startMessagePolling;
|
|
135
|
+
/**
|
|
136
|
+
* Stop message polling.
|
|
137
|
+
*/
|
|
138
|
+
private stopMessagePolling;
|
|
139
|
+
/**
|
|
140
|
+
* Long-poll for new messages from the iLink API.
|
|
141
|
+
* Automatically reschedules on completion or error.
|
|
142
|
+
*/
|
|
143
|
+
private pollMessages;
|
|
144
|
+
/**
|
|
145
|
+
* Persist bot token to disk.
|
|
146
|
+
*/
|
|
147
|
+
private persistConfig;
|
|
148
|
+
/**
|
|
149
|
+
* Load persisted config from disk.
|
|
150
|
+
*
|
|
151
|
+
* @returns Config or null if not found
|
|
152
|
+
*/
|
|
153
|
+
private loadConfig;
|
|
154
|
+
/**
|
|
155
|
+
* Remove persisted config from disk.
|
|
156
|
+
*/
|
|
157
|
+
removeConfig(): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Build authorization headers for iLink API.
|
|
160
|
+
*
|
|
161
|
+
* @returns Headers with Bearer token and AuthorizationType
|
|
162
|
+
*/
|
|
163
|
+
private authHeaders;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get the WeChat service singleton.
|
|
167
|
+
*
|
|
168
|
+
* @returns WeChatService instance
|
|
169
|
+
*/
|
|
170
|
+
export declare function getWeChatService(): WeChatService;
|
|
171
|
+
//# sourceMappingURL=wechat.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wechat/wechat.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAqCtC,+BAA+B;AAC/B,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gCAAgC;AAChC,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAM1F;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO;IAKP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,aAAa;IAOnC;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAW5B;;;;;;;;OAQG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IA0B1C;;;;;OAKG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA4DvF;;;;;;OAMG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBvE;;;;OAIG;IACH,SAAS,IAAI;QAAE,KAAK,EAAE,qBAAqB,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAQjG;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,UAAU,IAAI,IAAI;IAUlB;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAqBpC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAM3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;OAGG;YACW,YAAY;IAqE1B;;OAEG;YACW,aAAa;IAiB3B;;;;OAIG;YACW,UAAU;IASxB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;;;OAIG;IACH,OAAO,CAAC,WAAW;CAOpB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD"}
|