@yanhaidao/wecom 2.4.120 → 2.5.110

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 (323) hide show
  1. package/README.md +4 -5
  2. package/dist/index.js +68 -0
  3. package/dist/src/accounts.js +20 -0
  4. package/dist/src/agent/handler.js +895 -0
  5. package/dist/src/agent/index.js +5 -0
  6. package/dist/src/app/account-runtime.js +216 -0
  7. package/dist/src/app/bootstrap.js +19 -0
  8. package/dist/src/app/index.js +118 -0
  9. package/dist/src/capability/agent/delivery-service.js +63 -0
  10. package/dist/src/capability/agent/fallback-policy.js +6 -0
  11. package/dist/src/capability/agent/ingress-service.js +33 -0
  12. package/dist/src/capability/agent/upstream-delivery-service.js +71 -0
  13. package/dist/src/capability/bot/dispatch-config.js +45 -0
  14. package/dist/src/capability/bot/fallback-delivery.js +147 -0
  15. package/dist/src/capability/bot/local-path-delivery.js +178 -0
  16. package/dist/src/capability/bot/sandbox-media.js +138 -0
  17. package/dist/src/capability/bot/service.js +49 -0
  18. package/dist/src/capability/bot/stream-delivery.js +321 -0
  19. package/dist/src/capability/bot/stream-finalizer.js +81 -0
  20. package/dist/src/capability/bot/stream-orchestrator.js +318 -0
  21. package/dist/src/capability/bot/types.js +1 -0
  22. package/{src/capability/calendar/client.ts → dist/src/capability/calendar/client.js} +118 -241
  23. package/{src/capability/calendar/schema.ts → dist/src/capability/calendar/schema.js} +0 -38
  24. package/dist/src/capability/calendar/tool.js +365 -0
  25. package/dist/src/capability/calendar/types.js +12 -0
  26. package/{src/capability/doc/client.ts → dist/src/capability/doc/client.js} +370 -605
  27. package/{src/capability/doc/schema.ts → dist/src/capability/doc/schema.js} +345 -394
  28. package/dist/src/capability/doc/tool.js +1556 -0
  29. package/dist/src/capability/doc/types.js +113 -0
  30. package/dist/src/capability/mcp/index.js +3 -0
  31. package/dist/src/capability/mcp/schema.js +102 -0
  32. package/dist/src/capability/mcp/tool.js +146 -0
  33. package/dist/src/capability/mcp/transport.js +293 -0
  34. package/dist/src/channel.js +224 -0
  35. package/dist/src/config/accounts.js +236 -0
  36. package/dist/src/config/derived-paths.js +31 -0
  37. package/dist/src/config/index.js +7 -0
  38. package/dist/src/config/media.js +110 -0
  39. package/dist/src/config/network.js +32 -0
  40. package/dist/src/config/routing.js +20 -0
  41. package/dist/src/config/runtime-config.js +25 -0
  42. package/dist/src/config/schema.js +4 -0
  43. package/{src/config-schema.ts → dist/src/config-schema.js} +1 -1
  44. package/dist/src/context-store.js +219 -0
  45. package/{src/crypto/aes.ts → dist/src/crypto/aes.js} +11 -28
  46. package/dist/src/crypto/index.js +9 -0
  47. package/{src/crypto/signature.ts → dist/src/crypto/signature.js} +3 -18
  48. package/{src/crypto/xml.ts → dist/src/crypto/xml.js} +3 -11
  49. package/dist/src/crypto.js +145 -0
  50. package/dist/src/domain/models.js +1 -0
  51. package/dist/src/domain/policies.js +32 -0
  52. package/{src/dynamic-agent.ts → dist/src/dynamic-agent.js} +36 -73
  53. package/dist/src/gateway-monitor.js +139 -0
  54. package/dist/src/http.js +114 -0
  55. package/{src/media.ts → dist/src/media.js} +21 -40
  56. package/dist/src/monitor/limits.js +7 -0
  57. package/dist/src/monitor/state.js +28 -0
  58. package/dist/src/monitor.js +84 -0
  59. package/dist/src/observability/audit-log.js +30 -0
  60. package/dist/src/observability/legacy-operational-event-store.js +22 -0
  61. package/dist/src/observability/raw-envelope-log.js +24 -0
  62. package/dist/src/observability/status-registry.js +9 -0
  63. package/dist/src/observability/transport-session-view.js +14 -0
  64. package/dist/src/onboarding.js +546 -0
  65. package/dist/src/outbound.js +557 -0
  66. package/dist/src/runtime/dispatcher.js +57 -0
  67. package/{src/runtime/index.ts → dist/src/runtime/index.js} +0 -1
  68. package/dist/src/runtime/outbound-intent.js +1 -0
  69. package/dist/src/runtime/reply-orchestrator.js +38 -0
  70. package/dist/src/runtime/routing-bridge.js +26 -0
  71. package/dist/src/runtime/session-manager.js +112 -0
  72. package/dist/src/runtime/source-registry.js +174 -0
  73. package/dist/src/runtime.js +1 -0
  74. package/dist/src/shared/command-auth.js +57 -0
  75. package/{src/shared/index.ts → dist/src/shared/index.js} +0 -1
  76. package/dist/src/shared/media-asset.js +65 -0
  77. package/dist/src/shared/media-service.js +59 -0
  78. package/dist/src/shared/media-types.js +1 -0
  79. package/{src/shared/xml-parser.ts → dist/src/shared/xml-parser.js} +72 -63
  80. package/dist/src/store/active-reply-store.js +41 -0
  81. package/dist/src/store/interfaces.js +1 -0
  82. package/dist/src/store/memory-store.js +33 -0
  83. package/dist/src/store/stream-batch-store.js +319 -0
  84. package/{src/target.ts → dist/src/target.js} +15 -48
  85. package/dist/src/transport/agent-api/client.js +168 -0
  86. package/dist/src/transport/agent-api/core.js +337 -0
  87. package/dist/src/transport/agent-api/delivery.js +28 -0
  88. package/dist/src/transport/agent-api/media-upload.js +4 -0
  89. package/dist/src/transport/agent-api/reply.js +24 -0
  90. package/dist/src/transport/agent-api/upstream-delivery.js +30 -0
  91. package/dist/src/transport/agent-api/upstream-media-upload.js +46 -0
  92. package/dist/src/transport/agent-api/upstream-reply.js +26 -0
  93. package/dist/src/transport/agent-callback/http-handler.js +30 -0
  94. package/dist/src/transport/agent-callback/inbound.js +4 -0
  95. package/dist/src/transport/agent-callback/reply.js +8 -0
  96. package/dist/src/transport/agent-callback/request-handler.js +189 -0
  97. package/dist/src/transport/agent-callback/session.js +15 -0
  98. package/dist/src/transport/bot-webhook/active-reply.js +27 -0
  99. package/dist/src/transport/bot-webhook/http-handler.js +31 -0
  100. package/dist/src/transport/bot-webhook/inbound-normalizer.js +496 -0
  101. package/dist/src/transport/bot-webhook/inbound.js +4 -0
  102. package/dist/src/transport/bot-webhook/message-shape.js +98 -0
  103. package/dist/src/transport/bot-webhook/protocol.js +124 -0
  104. package/dist/src/transport/bot-webhook/reply.js +9 -0
  105. package/dist/src/transport/bot-webhook/request-handler.js +285 -0
  106. package/dist/src/transport/bot-webhook/session.js +15 -0
  107. package/dist/src/transport/bot-ws/inbound.js +147 -0
  108. package/dist/src/transport/bot-ws/media.js +236 -0
  109. package/dist/src/transport/bot-ws/reply.js +310 -0
  110. package/dist/src/transport/bot-ws/sdk-adapter.js +257 -0
  111. package/dist/src/transport/bot-ws/session.js +15 -0
  112. package/dist/src/transport/http/common.js +78 -0
  113. package/dist/src/transport/http/registry.js +71 -0
  114. package/dist/src/transport/http/request-handler.js +51 -0
  115. package/{src/transport/index.ts → dist/src/transport/index.js} +2 -10
  116. package/dist/src/types/account.js +1 -0
  117. package/dist/src/types/config.js +1 -0
  118. package/dist/src/types/constants.js +28 -0
  119. package/dist/src/types/events.js +1 -0
  120. package/dist/src/types/index.js +1 -0
  121. package/dist/src/types/legacy-stream.js +1 -0
  122. package/dist/src/types/message.js +5 -0
  123. package/dist/src/types/runtime-context.js +1 -0
  124. package/dist/src/types/runtime.js +1 -0
  125. package/dist/src/types.js +1 -0
  126. package/dist/src/upstream/index.js +111 -0
  127. package/dist/src/wecom_msg_adapter/markdown_adapter.js +280 -0
  128. package/openclaw.plugin.json +15 -0
  129. package/package.json +18 -1
  130. package/.github/workflows/release.yml +0 -143
  131. package/GOVERNANCE.md +0 -26
  132. package/MENU_EVENT_CONF.md +0 -500
  133. package/MENU_EVENT_PLAN.md +0 -440
  134. package/SKILLS_CAL.md +0 -895
  135. package/SKILLS_DOC.md +0 -2288
  136. package/UPSTREAM_CONFIG.md +0 -170
  137. package/UPSTREAM_PLAN.md +0 -175
  138. package/assets/01.bot-add.png +0 -0
  139. package/assets/01.bot-setp2.png +0 -0
  140. package/assets/01.image.jpg +0 -0
  141. package/assets/02.agent.add.png +0 -0
  142. package/assets/02.agent.api-set.png +0 -0
  143. package/assets/02.image.jpg +0 -0
  144. package/assets/03.agent.page.png +0 -0
  145. package/assets/03.bot.page.png +0 -0
  146. package/assets/link-me.jpg +0 -0
  147. package/assets/register.png +0 -0
  148. package/changelog/v2.2.28.md +0 -70
  149. package/changelog/v2.3.10.md +0 -17
  150. package/changelog/v2.3.11.md +0 -19
  151. package/changelog/v2.3.12.md +0 -25
  152. package/changelog/v2.3.13.md +0 -19
  153. package/changelog/v2.3.14.md +0 -48
  154. package/changelog/v2.3.15.md +0 -15
  155. package/changelog/v2.3.16.md +0 -11
  156. package/changelog/v2.3.18.md +0 -22
  157. package/changelog/v2.3.19.md +0 -73
  158. package/changelog/v2.3.2.md +0 -28
  159. package/changelog/v2.3.26.md +0 -21
  160. package/changelog/v2.3.27.md +0 -33
  161. package/changelog/v2.3.4.md +0 -20
  162. package/changelog/v2.3.9.md +0 -22
  163. package/changelog/v2.4.12.md +0 -37
  164. package/compat-single-account.md +0 -148
  165. package/index.test.ts +0 -38
  166. package/scripts/test-proxy.ts +0 -70
  167. package/scripts/wecom/README.md +0 -123
  168. package/scripts/wecom/menu-click-help.js +0 -59
  169. package/scripts/wecom/menu-click-help.py +0 -55
  170. package/src/accounts.ts +0 -34
  171. package/src/agent/api-client.upload.test.ts +0 -109
  172. package/src/agent/event-router.test.ts +0 -421
  173. package/src/agent/event-router.ts +0 -272
  174. package/src/agent/handler.event-filter.test.ts +0 -135
  175. package/src/agent/handler.ts +0 -1250
  176. package/src/agent/index.ts +0 -12
  177. package/src/agent/script-runner.ts +0 -186
  178. package/src/agent/test-fixtures/invalid-json-script.mjs +0 -1
  179. package/src/agent/test-fixtures/reply-event-script.mjs +0 -29
  180. package/src/agent/test-fixtures/reply-event-script.py +0 -17
  181. package/src/app/account-runtime.ts +0 -276
  182. package/src/app/bootstrap.ts +0 -29
  183. package/src/app/index.ts +0 -192
  184. package/src/capability/agent/delivery-service.ts +0 -87
  185. package/src/capability/agent/fallback-policy.ts +0 -13
  186. package/src/capability/agent/ingress-service.ts +0 -38
  187. package/src/capability/agent/upstream-delivery-service.ts +0 -96
  188. package/src/capability/bot/dispatch-config.ts +0 -47
  189. package/src/capability/bot/fallback-delivery.ts +0 -178
  190. package/src/capability/bot/local-path-delivery.ts +0 -215
  191. package/src/capability/bot/sandbox-media.test.ts +0 -221
  192. package/src/capability/bot/sandbox-media.ts +0 -176
  193. package/src/capability/bot/service.ts +0 -56
  194. package/src/capability/bot/stream-delivery.ts +0 -379
  195. package/src/capability/bot/stream-finalizer.ts +0 -120
  196. package/src/capability/bot/stream-orchestrator.ts +0 -371
  197. package/src/capability/bot/types.ts +0 -8
  198. package/src/capability/calendar/SKILLS_CHECKLIST.md +0 -251
  199. package/src/capability/calendar/tool.ts +0 -417
  200. package/src/capability/calendar/types.ts +0 -309
  201. package/src/capability/doc/tool.ts +0 -1629
  202. package/src/capability/doc/types.ts +0 -792
  203. package/src/capability/mcp/index.ts +0 -10
  204. package/src/capability/mcp/schema.ts +0 -107
  205. package/src/capability/mcp/tool.ts +0 -174
  206. package/src/capability/mcp/transport.ts +0 -394
  207. package/src/channel.config.test.ts +0 -180
  208. package/src/channel.lifecycle.test.ts +0 -255
  209. package/src/channel.meta.test.ts +0 -26
  210. package/src/channel.ts +0 -256
  211. package/src/config/accounts.resolve.test.ts +0 -75
  212. package/src/config/accounts.ts +0 -312
  213. package/src/config/derived-paths.test.ts +0 -111
  214. package/src/config/derived-paths.ts +0 -41
  215. package/src/config/index.ts +0 -22
  216. package/src/config/media.test.ts +0 -113
  217. package/src/config/media.ts +0 -139
  218. package/src/config/network.ts +0 -20
  219. package/src/config/routing.test.ts +0 -88
  220. package/src/config/routing.ts +0 -26
  221. package/src/config/runtime-config.ts +0 -46
  222. package/src/config/schema.ts +0 -144
  223. package/src/context-store.ts +0 -297
  224. package/src/crypto/index.ts +0 -24
  225. package/src/crypto.test.ts +0 -32
  226. package/src/crypto.ts +0 -176
  227. package/src/domain/models.ts +0 -7
  228. package/src/domain/policies.ts +0 -36
  229. package/src/dynamic-agent.account-scope.test.ts +0 -17
  230. package/src/gateway-monitor.ts +0 -181
  231. package/src/http.ts +0 -137
  232. package/src/media.test.ts +0 -82
  233. package/src/monitor/limits.ts +0 -7
  234. package/src/monitor/state.queue.test.ts +0 -185
  235. package/src/monitor/state.ts +0 -34
  236. package/src/monitor.active.test.ts +0 -245
  237. package/src/monitor.inbound-filter.test.ts +0 -63
  238. package/src/monitor.integration.test.ts +0 -208
  239. package/src/monitor.ts +0 -121
  240. package/src/monitor.webhook.test.ts +0 -774
  241. package/src/observability/audit-log.ts +0 -48
  242. package/src/observability/legacy-operational-event-store.ts +0 -36
  243. package/src/observability/raw-envelope-log.ts +0 -28
  244. package/src/observability/status-registry.ts +0 -13
  245. package/src/observability/transport-session-view.ts +0 -14
  246. package/src/onboarding.test.ts +0 -336
  247. package/src/onboarding.ts +0 -704
  248. package/src/outbound.test.ts +0 -1271
  249. package/src/outbound.ts +0 -746
  250. package/src/runtime/dispatcher.ts +0 -71
  251. package/src/runtime/outbound-intent.ts +0 -4
  252. package/src/runtime/reply-orchestrator.test.ts +0 -71
  253. package/src/runtime/reply-orchestrator.ts +0 -67
  254. package/src/runtime/routing-bridge.test.ts +0 -115
  255. package/src/runtime/routing-bridge.ts +0 -44
  256. package/src/runtime/session-manager.test.ts +0 -174
  257. package/src/runtime/session-manager.ts +0 -139
  258. package/src/runtime/source-registry.ts +0 -249
  259. package/src/runtime.ts +0 -14
  260. package/src/shared/command-auth.ts +0 -87
  261. package/src/shared/media-asset.ts +0 -78
  262. package/src/shared/media-service.test.ts +0 -111
  263. package/src/shared/media-service.ts +0 -84
  264. package/src/shared/media-types.ts +0 -5
  265. package/src/shared/xml-parser.test.ts +0 -50
  266. package/src/store/active-reply-store.ts +0 -42
  267. package/src/store/interfaces.ts +0 -11
  268. package/src/store/memory-store.ts +0 -43
  269. package/src/store/stream-batch-store.ts +0 -350
  270. package/src/transport/agent-api/client.ts +0 -277
  271. package/src/transport/agent-api/core.ts +0 -463
  272. package/src/transport/agent-api/delivery.ts +0 -41
  273. package/src/transport/agent-api/media-upload.ts +0 -11
  274. package/src/transport/agent-api/reply.ts +0 -39
  275. package/src/transport/agent-api/upstream-delivery.ts +0 -45
  276. package/src/transport/agent-api/upstream-media-upload.ts +0 -70
  277. package/src/transport/agent-api/upstream-reply.ts +0 -43
  278. package/src/transport/agent-callback/http-handler.ts +0 -47
  279. package/src/transport/agent-callback/inbound.ts +0 -5
  280. package/src/transport/agent-callback/reply.ts +0 -13
  281. package/src/transport/agent-callback/request-handler.ts +0 -244
  282. package/src/transport/agent-callback/session.ts +0 -23
  283. package/src/transport/bot-webhook/active-reply.ts +0 -39
  284. package/src/transport/bot-webhook/http-handler.ts +0 -48
  285. package/src/transport/bot-webhook/inbound-normalizer.ts +0 -371
  286. package/src/transport/bot-webhook/inbound.ts +0 -5
  287. package/src/transport/bot-webhook/message-shape.ts +0 -89
  288. package/src/transport/bot-webhook/protocol.ts +0 -148
  289. package/src/transport/bot-webhook/reply.ts +0 -15
  290. package/src/transport/bot-webhook/request-handler.ts +0 -394
  291. package/src/transport/bot-webhook/session.ts +0 -23
  292. package/src/transport/bot-ws/inbound.test.ts +0 -96
  293. package/src/transport/bot-ws/inbound.ts +0 -116
  294. package/src/transport/bot-ws/media.test.ts +0 -44
  295. package/src/transport/bot-ws/media.ts +0 -321
  296. package/src/transport/bot-ws/reply.test.ts +0 -450
  297. package/src/transport/bot-ws/reply.ts +0 -365
  298. package/src/transport/bot-ws/sdk-adapter.test.ts +0 -187
  299. package/src/transport/bot-ws/sdk-adapter.ts +0 -314
  300. package/src/transport/bot-ws/session.ts +0 -28
  301. package/src/transport/http/common.ts +0 -109
  302. package/src/transport/http/registry.ts +0 -92
  303. package/src/transport/http/request-handler.ts +0 -84
  304. package/src/types/account.ts +0 -72
  305. package/src/types/config.ts +0 -166
  306. package/src/types/constants.ts +0 -31
  307. package/src/types/events.ts +0 -21
  308. package/src/types/global.d.ts +0 -9
  309. package/src/types/index.ts +0 -17
  310. package/src/types/legacy-stream.ts +0 -50
  311. package/src/types/message.ts +0 -187
  312. package/src/types/runtime-context.ts +0 -28
  313. package/src/types/runtime.ts +0 -165
  314. package/src/types.ts +0 -41
  315. package/src/upstream/index.ts +0 -150
  316. package/src/upstream.test.ts +0 -84
  317. package/src/wecom_msg_adapter/markdown_adapter.ts +0 -331
  318. package/tsconfig.json +0 -22
  319. package/vitest.config.ts +0 -26
  320. /package/{src/capability/agent/index.ts → dist/src/capability/agent/index.js} +0 -0
  321. /package/{src/capability/bot/index.ts → dist/src/capability/bot/index.js} +0 -0
  322. /package/{src/capability/calendar/index.ts → dist/src/capability/calendar/index.js} +0 -0
  323. /package/{src/capability/index.ts → dist/src/capability/index.js} +0 -0
@@ -1,272 +0,0 @@
1
- import { extractAgentId, extractMsgId } from "../shared/xml-parser.js";
2
- import type {
3
- ResolvedAgentAccount,
4
- WecomAgentEventRouteConfig,
5
- WecomAgentInboundMessage,
6
- } from "../types/index.js";
7
- import type { WecomRuntimeAuditEvent } from "../types/runtime-context.js";
8
- import { runAgentEventScript, type AgentEventScriptEnvelope } from "./script-runner.js";
9
-
10
- export type AgentInboundEventRouteResult = {
11
- handled: boolean;
12
- chainToAgent: boolean;
13
- replyText?: string;
14
- matchedRouteId?: string;
15
- reason: string;
16
- error?: string;
17
- };
18
-
19
- // 统一比较口径:事件类型按小写处理
20
- function normalizeLower(value: unknown): string {
21
- return String(value ?? "").trim().toLowerCase();
22
- }
23
-
24
- // 事件键值按原大小写保留,仅做首尾清理
25
- function normalizeText(value: unknown): string {
26
- return String(value ?? "").trim();
27
- }
28
-
29
- function testPatternSafe(params: {
30
- pattern: string;
31
- value: string;
32
- onInvalidPattern?: (errorMessage: string) => void;
33
- }): boolean {
34
- try {
35
- return new RegExp(params.pattern).test(params.value);
36
- } catch (err) {
37
- const message = err instanceof Error ? err.message : String(err);
38
- params.onInvalidPattern?.(message);
39
- // 配置了非法正则时按“不匹配”处理,避免中断 webhook 主流程
40
- return false;
41
- }
42
- }
43
-
44
- function matchesRoute(params: {
45
- route: WecomAgentEventRouteConfig;
46
- eventType: string;
47
- changeType: string;
48
- eventKey: string;
49
- onInvalidPattern?: (errorMessage: string) => void;
50
- }): boolean {
51
- // 三层匹配:eventType -> changeType/eventKey(含 prefix/regex)
52
- const when = params.route.when ?? {};
53
-
54
- if (when.eventType && normalizeLower(when.eventType) !== params.eventType) return false;
55
- if (when.changeType && normalizeLower(when.changeType) !== params.changeType) return false;
56
- if (when.eventKey && normalizeText(when.eventKey) !== params.eventKey) return false;
57
- if (when.eventKeyPrefix && !params.eventKey.startsWith(normalizeText(when.eventKeyPrefix))) return false;
58
- if (when.eventKeyPattern && !testPatternSafe({
59
- pattern: when.eventKeyPattern,
60
- value: params.eventKey,
61
- onInvalidPattern: params.onInvalidPattern,
62
- })) return false;
63
-
64
- return true;
65
- }
66
-
67
- function buildScriptEnvelope(params: {
68
- accountId: string;
69
- msgType: string;
70
- eventType: string;
71
- eventKey: string;
72
- changeType: string;
73
- fromUser: string;
74
- toUser?: string;
75
- chatId?: string;
76
- msg: WecomAgentInboundMessage;
77
- matchedRuleId: string;
78
- handlerType: "node_script" | "python_script";
79
- }): AgentEventScriptEnvelope {
80
- // 透传给外部脚本:标准化字段 + 原始 XML 解析对象 raw
81
- const rawAgentId = extractAgentId(params.msg);
82
- const numericAgentId = typeof rawAgentId === "number"
83
- ? rawAgentId
84
- : Number.isFinite(Number(rawAgentId)) ? Number(rawAgentId) : null;
85
-
86
- return {
87
- version: "1.0",
88
- channel: "wecom",
89
- accountId: params.accountId,
90
- receivedAt: Date.now(),
91
- message: {
92
- msgType: params.msgType,
93
- eventType: params.eventType,
94
- eventKey: params.eventKey || null,
95
- changeType: params.changeType || null,
96
- fromUser: params.fromUser,
97
- toUser: params.toUser ?? null,
98
- chatId: params.chatId ?? null,
99
- agentId: numericAgentId,
100
- createTime: typeof params.msg.CreateTime === "number" ? params.msg.CreateTime : Number.isFinite(Number(params.msg.CreateTime)) ? Number(params.msg.CreateTime) : null,
101
- msgId: extractMsgId(params.msg) ?? null,
102
- raw: { ...(params.msg as Record<string, unknown>) },
103
- },
104
- route: {
105
- matchedRuleId: params.matchedRuleId,
106
- handlerType: params.handlerType,
107
- },
108
- };
109
- }
110
-
111
- export async function routeAgentInboundEvent(params: {
112
- agent: ResolvedAgentAccount;
113
- msgType: string;
114
- eventType: string;
115
- fromUser: string;
116
- chatId?: string;
117
- msg: WecomAgentInboundMessage;
118
- log?: (msg: string) => void;
119
- auditSink?: (event: WecomRuntimeAuditEvent) => void;
120
- }): Promise<AgentInboundEventRouteResult> {
121
- if (normalizeLower(params.msgType) !== "event") {
122
- return {
123
- handled: false,
124
- chainToAgent: false,
125
- reason: "not_event",
126
- };
127
- }
128
-
129
- const routing = params.agent.config.eventRouting;
130
- const routes = routing?.routes ?? [];
131
- const changeType = normalizeLower(params.msg.ChangeType);
132
- const eventKey = normalizeText(params.msg.EventKey);
133
- // 路由采用“首个命中即执行”策略
134
- const matchedRoute = routes.find((route) => matchesRoute({
135
- route,
136
- eventType: params.eventType,
137
- changeType,
138
- eventKey,
139
- onInvalidPattern: (errorMessage) => {
140
- const routeId = route.id?.trim() || "anonymous";
141
- params.log?.(
142
- `[wecom-agent] invalid eventKeyPattern in route routeId=${routeId} pattern=${route.when?.eventKeyPattern ?? ""} error=${errorMessage}`,
143
- );
144
- params.auditSink?.({
145
- transport: "agent-callback",
146
- category: "runtime-error",
147
- messageId: extractMsgId(params.msg) ?? undefined,
148
- summary: `invalid route eventKeyPattern routeId=${routeId}`,
149
- raw: {
150
- transport: "agent-callback",
151
- envelopeType: "xml",
152
- body: params.msg,
153
- },
154
- error: `routeId=${routeId} pattern=${route.when?.eventKeyPattern ?? ""} error=${errorMessage}`,
155
- });
156
- },
157
- }));
158
-
159
- if (!matchedRoute) {
160
- // 未命中时由 unmatchedAction 决定:忽略 or 继续默认 AI 流程
161
- if (routing?.unmatchedAction === "forwardToAgent") {
162
- return {
163
- handled: false,
164
- chainToAgent: true,
165
- reason: "unmatched_event_forwardToAgent",
166
- };
167
- }
168
- return {
169
- handled: true,
170
- chainToAgent: false,
171
- reason: "unmatched_event_ignored",
172
- };
173
- }
174
-
175
- const matchedRouteId = matchedRoute.id?.trim() || `${params.eventType || "event"}:${eventKey || "default"}`;
176
- params.log?.(`[wecom-agent] event route matched routeId=${matchedRouteId} event=${params.eventType} eventKey=${eventKey || "N/A"}`);
177
-
178
- if (matchedRoute.handler.type === "builtin") {
179
- // 内置 handler:当前仅实现 echo,用于联调和最小可用场景
180
- if ((matchedRoute.handler.name ?? "echo") === "echo") {
181
- const replyText = [`event=${params.eventType}`,
182
- eventKey ? `eventKey=${eventKey}` : "",
183
- changeType ? `changeType=${changeType}` : "",
184
- ].filter(Boolean).join(" ");
185
- return {
186
- handled: true,
187
- chainToAgent: matchedRoute.handler.chainToAgent === true,
188
- replyText,
189
- matchedRouteId,
190
- reason: "builtin_echo",
191
- };
192
- }
193
- }
194
-
195
- if (matchedRoute.handler.type !== "node_script" && matchedRoute.handler.type !== "python_script") {
196
- return {
197
- handled: true,
198
- chainToAgent: false,
199
- matchedRouteId,
200
- reason: "unsupported_handler",
201
- };
202
- }
203
-
204
- try {
205
- // 外部脚本 handler:通过 stdin 输入 envelope,stdout 返回 JSON 协议
206
- const { response: scriptResponse, meta } = await runAgentEventScript({
207
- runtime: params.agent.config.scriptRuntime,
208
- handler: matchedRoute.handler,
209
- envelope: buildScriptEnvelope({
210
- accountId: params.agent.accountId,
211
- msgType: params.msgType,
212
- eventType: params.eventType,
213
- eventKey,
214
- changeType,
215
- fromUser: params.fromUser,
216
- toUser: typeof params.msg.ToUserName === "string" ? params.msg.ToUserName : undefined,
217
- chatId: params.chatId,
218
- msg: params.msg,
219
- matchedRuleId: matchedRouteId,
220
- handlerType: matchedRoute.handler.type,
221
- }),
222
- });
223
-
224
- params.auditSink?.({
225
- transport: "agent-callback",
226
- category: "inbound",
227
- messageId: extractMsgId(params.msg) ?? undefined,
228
- summary:
229
- `event route script ok routeId=${matchedRouteId} handler=${matchedRoute.handler.type} ` +
230
- `event=${params.eventType} durationMs=${meta.durationMs} exitCode=${meta.exitCode ?? "null"}`,
231
- raw: {
232
- transport: "agent-callback",
233
- envelopeType: "xml",
234
- body: params.msg,
235
- },
236
- });
237
-
238
- return {
239
- handled: true,
240
- chainToAgent:
241
- scriptResponse.chainToAgent === true || matchedRoute.handler.chainToAgent === true,
242
- replyText: scriptResponse.action === "reply_text" ? scriptResponse.reply?.text : undefined,
243
- matchedRouteId,
244
- reason: `script_${matchedRoute.handler.type}`,
245
- };
246
- } catch (err) {
247
- // 脚本失败时不抛出到上层,转为“已处理 + 审计错误”,避免中断 webhook 主流程
248
- const message = err instanceof Error ? err.message : String(err);
249
- params.log?.(
250
- `[wecom-agent] event route script failed routeId=${matchedRouteId} handler=${matchedRoute.handler.type} error=${message}`,
251
- );
252
- params.auditSink?.({
253
- transport: "agent-callback",
254
- category: "runtime-error",
255
- messageId: extractMsgId(params.msg) ?? undefined,
256
- summary: `event route script failed routeId=${matchedRouteId} handler=${matchedRoute.handler.type} event=${params.eventType}`,
257
- raw: {
258
- transport: "agent-callback",
259
- envelopeType: "xml",
260
- body: params.msg,
261
- },
262
- error: message,
263
- });
264
- return {
265
- handled: true,
266
- chainToAgent: false,
267
- matchedRouteId,
268
- reason: `script_${matchedRoute.handler.type}_error`,
269
- error: message,
270
- };
271
- }
272
- }
@@ -1,135 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
-
3
- import { shouldProcessAgentInboundMessage, shouldSuppressAgentReplyText } from "./handler.js";
4
-
5
- describe("shouldProcessAgentInboundMessage", () => {
6
- it("allows enter_agent/subscribe through the filter (handled earlier by static welcome)", () => {
7
- const enterAgent = shouldProcessAgentInboundMessage({
8
- msgType: "event",
9
- eventType: "enter_agent",
10
- fromUser: "zhangsan",
11
- });
12
- expect(enterAgent.shouldProcess).toBe(true);
13
- expect(enterAgent.reason).toBe("allowed_event:enter_agent");
14
-
15
- const subscribe = shouldProcessAgentInboundMessage({
16
- msgType: "event",
17
- eventType: "subscribe",
18
- fromUser: "lisi",
19
- });
20
- expect(subscribe.shouldProcess).toBe(true);
21
- expect(subscribe.reason).toBe("allowed_event:subscribe");
22
- });
23
-
24
- it("skips unknown event callbacks so they do not create sessions", () => {
25
- const unknown = shouldProcessAgentInboundMessage({
26
- msgType: "event",
27
- eventType: "some_random_event",
28
- fromUser: "zhangsan",
29
- });
30
- expect(unknown.shouldProcess).toBe(false);
31
- expect(unknown.reason).toBe("event:some_random_event");
32
- });
33
-
34
- it("blocks event processing when eventEnabled is false", () => {
35
- const disabled = shouldProcessAgentInboundMessage({
36
- msgType: "event",
37
- eventType: "click",
38
- fromUser: "zhangsan",
39
- eventEnabled: false,
40
- });
41
- expect(disabled.shouldProcess).toBe(false);
42
- expect(disabled.reason).toBe("event_disabled");
43
- });
44
-
45
- it("allows configured custom event types", () => {
46
- const custom = shouldProcessAgentInboundMessage({
47
- msgType: "event",
48
- eventType: "click",
49
- fromUser: "zhangsan",
50
- eventEnabled: true,
51
- allowedEventTypes: ["click"],
52
- });
53
- expect(custom.shouldProcess).toBe(true);
54
- expect(custom.reason).toBe("allowed_event:click");
55
- });
56
-
57
- it("normalizes configured event type values before matching", () => {
58
- const custom = shouldProcessAgentInboundMessage({
59
- msgType: "event",
60
- eventType: "view_miniprogram",
61
- fromUser: "zhangsan",
62
- eventEnabled: true,
63
- allowedEventTypes: [" VIEW_MINIPROGRAM "],
64
- });
65
- expect(custom.shouldProcess).toBe(true);
66
- expect(custom.reason).toBe("allowed_event:view_miniprogram");
67
- });
68
-
69
- it("skips system sender callbacks", () => {
70
- const systemSender = shouldProcessAgentInboundMessage({
71
- msgType: "text",
72
- fromUser: "sys",
73
- });
74
- expect(systemSender.shouldProcess).toBe(false);
75
- expect(systemSender.reason).toBe("system_sender");
76
- });
77
-
78
- it("skips messages with missing sender id", () => {
79
- const missingSender = shouldProcessAgentInboundMessage({
80
- msgType: "text",
81
- fromUser: " ",
82
- });
83
- expect(missingSender.shouldProcess).toBe(false);
84
- expect(missingSender.reason).toBe("missing_sender");
85
- });
86
-
87
-
88
- it("allows group chat messages when sender id is missing", () => {
89
- const groupWithoutSender = shouldProcessAgentInboundMessage({
90
- msgType: "file",
91
- fromUser: " ",
92
- chatId: "wrbchat_123",
93
- });
94
- expect(groupWithoutSender.shouldProcess).toBe(true);
95
- expect(groupWithoutSender.reason).toBe("missing_sender_but_group_chat");
96
- });
97
-
98
- it("allows normal user text message processing", () => {
99
- const normalMessage = shouldProcessAgentInboundMessage({
100
- msgType: "text",
101
- fromUser: "wangwu",
102
- });
103
- expect(normalMessage.shouldProcess).toBe(true);
104
- expect(normalMessage.reason).toBe("user_message");
105
- });
106
- });
107
-
108
- describe("shouldSuppressAgentReplyText", () => {
109
- it("keeps plain text replies when no media reply has been seen", () => {
110
- expect(
111
- shouldSuppressAgentReplyText({
112
- text: "这里是正常文本",
113
- mediaReplySeen: false,
114
- }),
115
- ).toBe(false);
116
- });
117
-
118
- it("suppresses companion text once the reply flow includes media", () => {
119
- expect(
120
- shouldSuppressAgentReplyText({
121
- text: "文件已发送,请查收",
122
- mediaReplySeen: true,
123
- }),
124
- ).toBe(true);
125
- });
126
-
127
- it("does not suppress empty text even after media replies", () => {
128
- expect(
129
- shouldSuppressAgentReplyText({
130
- text: " ",
131
- mediaReplySeen: true,
132
- }),
133
- ).toBe(false);
134
- });
135
- });