@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,371 +0,0 @@
1
- import { pathToFileURL } from "node:url";
2
-
3
- import type { PluginRuntime } from "openclaw/plugin-sdk";
4
-
5
- import { resolveWecomMediaMaxBytes, shouldRejectWecomDefaultRoute } from "../../config/index.js";
6
- import { ensureDynamicAgentListed, generateAgentId, shouldUseDynamicAgent } from "../../dynamic-agent.js";
7
- import { LIMITS, type StreamStore } from "../../monitor/state.js";
8
- import { getWecomRuntime } from "../../runtime.js";
9
- import { buildWecomUnauthorizedCommandPrompt, resolveWecomCommandAuthorization } from "../../shared/command-auth.js";
10
- import type { PendingInbound } from "../../types/legacy-stream.js";
11
- import type { WecomBotInboundMessage as WecomInboundMessage } from "../../types/index.js";
12
- import type { WecomWebhookTarget } from "../../types/runtime-context.js";
13
- import { looksLikeSendLocalFileIntent, processBotInboundMessage } from "../../transport/bot-webhook/inbound-normalizer.js";
14
- import { resolveWecomSenderUserId } from "../../transport/bot-webhook/message-shape.js";
15
- import { buildWecomBotDispatchConfig } from "./dispatch-config.js";
16
- import { sendBotFallbackPromptNow } from "./fallback-delivery.js";
17
- import { finalizeBotStream } from "./stream-finalizer.js";
18
- import { handleDirectLocalPathIntent } from "./local-path-delivery.js";
19
- import { stageWecomInboundMediaForSession } from "./sandbox-media.js";
20
- import { createBotReplyDispatcher } from "./stream-delivery.js";
21
- import type { BotRuntimeLogger, RecordBotOperationalEvent } from "./types.js";
22
-
23
- export type StartBotAgentStreamParams = {
24
- target: WecomWebhookTarget;
25
- accountId: string;
26
- msg: WecomInboundMessage;
27
- streamId: string;
28
- mergedContents?: string[] | string;
29
- mergedMsgids?: string[];
30
- };
31
-
32
- export function createBotStreamOrchestrator(params: {
33
- streamStore: StreamStore;
34
- recordBotOperationalEvent: RecordBotOperationalEvent;
35
- }) {
36
- const { streamStore, recordBotOperationalEvent } = params;
37
-
38
- const logVerbose: BotRuntimeLogger = (target, message) => {
39
- const should =
40
- target.core.logging?.shouldLogVerbose?.() ??
41
- (() => {
42
- try {
43
- return getWecomRuntime().logging.shouldLogVerbose();
44
- } catch {
45
- return false;
46
- }
47
- })();
48
- if (!should) return;
49
- target.runtime.log?.(`[wecom] ${message}`);
50
- };
51
-
52
- const logInfo: BotRuntimeLogger = (target, message) => {
53
- target.runtime.log?.(`[wecom] ${message}`);
54
- };
55
-
56
- const truncateUtf8Bytes = (text: string, maxBytes: number): string => {
57
- const buf = Buffer.from(text, "utf8");
58
- if (buf.length <= maxBytes) return text;
59
- return buf.subarray(buf.length - maxBytes).toString("utf8");
60
- };
61
-
62
- const computeTaskKey = (target: WecomWebhookTarget, msg: WecomInboundMessage): string | undefined => {
63
- const msgid = msg.msgid ? String(msg.msgid) : "";
64
- if (!msgid) return undefined;
65
- const aibotid = String((msg as any).aibotid ?? "unknown").trim() || "unknown";
66
- return `bot:${target.account.accountId}:${aibotid}:${msgid}`;
67
- };
68
-
69
- async function flushPending(pending: PendingInbound): Promise<void> {
70
- const { streamId, target, msg, contents, msgids, conversationKey, batchKey } = pending;
71
- const mergedContents = contents.filter((c) => c.trim()).join("\n").trim();
72
-
73
- let core: PluginRuntime | null = null;
74
- try {
75
- core = getWecomRuntime();
76
- } catch (err) {
77
- logVerbose(target, `flush pending: runtime not ready: ${String(err)}`);
78
- streamStore.markFinished(streamId);
79
- logInfo(target, `queue: runtime not ready,结束批次并推进 streamId=${streamId}`);
80
- streamStore.onStreamFinished(streamId);
81
- return;
82
- }
83
-
84
- if (!core) return;
85
-
86
- streamStore.markStarted(streamId);
87
- const enrichedTarget: WecomWebhookTarget = { ...target, core };
88
- logInfo(
89
- target,
90
- `flush pending: start batch streamId=${streamId} batchKey=${batchKey} conversationKey=${conversationKey} mergedCount=${contents.length}`,
91
- );
92
- logVerbose(target, `防抖结束: 开始处理聚合消息 数量=${contents.length} streamId=${streamId}`);
93
-
94
- startAgentForStream({
95
- target: enrichedTarget,
96
- accountId: target.account.accountId,
97
- msg,
98
- streamId,
99
- mergedContents: contents.length > 1 ? mergedContents : undefined,
100
- mergedMsgids: msgids.length > 1 ? msgids : undefined,
101
- }).catch((err) => {
102
- streamStore.updateStream(streamId, (state) => {
103
- state.error = err instanceof Error ? err.message : String(err);
104
- state.content = state.content || `Error: ${state.error}`;
105
- state.finished = true;
106
- });
107
- target.runtime.error?.(`[${target.account.accountId}] wecom agent failed (处理失败): ${String(err)}`);
108
- streamStore.onStreamFinished(streamId);
109
- });
110
- }
111
-
112
- async function startAgentForStream(params: StartBotAgentStreamParams): Promise<void> {
113
- const { target, msg, streamId } = params;
114
- const core = target.core;
115
- const config = target.config;
116
- const account = target.account;
117
-
118
- const userId = resolveWecomSenderUserId(msg) || "unknown";
119
- const chatType = msg.chattype === "group" ? "group" : "direct";
120
- const chatId = msg.chattype === "group" ? (msg.chatid?.trim() || "unknown") : userId;
121
- const taskKey = computeTaskKey(target, msg);
122
- const aibotid = String((msg as any).aibotid ?? "").trim() || undefined;
123
-
124
- streamStore.updateStream(streamId, (s) => {
125
- s.userId = userId;
126
- s.chatType = chatType;
127
- s.chatId = chatId;
128
- s.taskKey = taskKey;
129
- s.aibotid = aibotid;
130
- });
131
-
132
- let { body: rawBody, media } = await processBotInboundMessage({
133
- target,
134
- msg,
135
- recordOperationalIssue: (event) => recordBotOperationalEvent(target, event),
136
- });
137
-
138
- if (params.mergedContents) {
139
- rawBody = Array.isArray(params.mergedContents) ? params.mergedContents.join("\n") : params.mergedContents;
140
- }
141
-
142
- const handledLocalPath = await handleDirectLocalPathIntent({
143
- streamStore,
144
- target,
145
- streamId,
146
- rawBody,
147
- userId,
148
- chatType,
149
- logVerbose,
150
- looksLikeSendLocalFileIntent,
151
- });
152
- if (handledLocalPath) return;
153
-
154
- let mediaPath: string | undefined;
155
- let mediaType: string | undefined;
156
- const mediaFilename = media?.filename;
157
- if (media) {
158
- try {
159
- const maxBytes = resolveWecomMediaMaxBytes(target.config, target.account.accountId);
160
- const saved = await core.channel.media.saveMediaBuffer(media.buffer, media.contentType, "inbound", maxBytes, media.filename);
161
- mediaPath = saved.path;
162
- mediaType = saved.contentType;
163
- logVerbose(target, `saved inbound media to ${mediaPath} (${mediaType})`);
164
- } catch (err) {
165
- target.runtime.error?.(`Failed to save inbound media: ${String(err)}`);
166
- }
167
- }
168
-
169
- const route = core.channel.routing.resolveAgentRoute({
170
- cfg: config,
171
- channel: "wecom",
172
- accountId: account.accountId,
173
- peer: { kind: chatType === "group" ? "group" : "direct", id: chatId },
174
- });
175
-
176
- const useDynamicAgent = shouldUseDynamicAgent({
177
- chatType: chatType === "group" ? "group" : "dm",
178
- senderId: userId,
179
- config,
180
- });
181
-
182
- if (shouldRejectWecomDefaultRoute({ cfg: config, matchedBy: route.matchedBy, useDynamicAgent })) {
183
- const prompt =
184
- `当前账号(${account.accountId})未绑定 OpenClaw Agent,已拒绝回退到默认主智能体。` +
185
- `请在 bindings 中添加:{"agentId":"你的Agent","match":{"channel":"wecom","accountId":"${account.accountId}"}}`;
186
- target.runtime.error?.(
187
- `[wecom] routing guard: blocked default fallback accountId=${account.accountId} matchedBy=${route.matchedBy} streamId=${streamId}`,
188
- );
189
- streamStore.updateStream(streamId, (s) => {
190
- s.finished = true;
191
- s.content = prompt;
192
- });
193
- try {
194
- await sendBotFallbackPromptNow({ streamId, text: prompt });
195
- } catch (err) {
196
- target.runtime.error?.(`routing guard prompt push failed streamId=${streamId}: ${String(err)}`);
197
- }
198
- streamStore.onStreamFinished(streamId);
199
- return;
200
- }
201
-
202
- if (useDynamicAgent) {
203
- const targetAgentId = generateAgentId(chatType === "group" ? "group" : "dm", chatId, account.accountId);
204
- route.agentId = targetAgentId;
205
- route.sessionKey = `agent:${targetAgentId}:wecom:${account.accountId}:${chatType === "group" ? "group" : "dm"}:${chatId}`;
206
- ensureDynamicAgentListed(targetAgentId, core).catch(() => { });
207
- logVerbose(target, `dynamic agent routing: ${targetAgentId}, sessionKey=${route.sessionKey}`);
208
- }
209
-
210
- if (mediaPath) {
211
- try {
212
- const stagedSessionPath = await stageWecomInboundMediaForSession({
213
- cfg: target.config,
214
- accountId: target.account.accountId,
215
- agentId: route.agentId,
216
- sessionKey: route.sessionKey,
217
- mediaPath,
218
- filename: mediaFilename,
219
- });
220
- mediaPath = stagedSessionPath;
221
- logVerbose(target, `session media staged to ${mediaPath}`);
222
- } catch (err) {
223
- target.runtime.error?.(`Failed to stage inbound media for session workspace: ${String(err)}`);
224
- }
225
- }
226
-
227
- logVerbose(target, `starting agent processing (streamId=${streamId}, agentId=${route.agentId}, peerKind=${chatType}, peerId=${chatId})`);
228
- logVerbose(target, `启动 Agent 处理: streamId=${streamId} 路由=${route.agentId} 类型=${chatType} ID=${chatId}`);
229
-
230
- const fromLabel = chatType === "group" ? `group:${chatId}` : `user:${userId}`;
231
- const storePath = core.channel.session.resolveStorePath(config.session?.store, { agentId: route.agentId });
232
- const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(config);
233
- const previousTimestamp = core.channel.session.readSessionUpdatedAt({
234
- storePath,
235
- sessionKey: route.sessionKey,
236
- });
237
- const body = core.channel.reply.formatAgentEnvelope({
238
- channel: "WeCom",
239
- from: fromLabel,
240
- previousTimestamp,
241
- envelope: envelopeOptions,
242
- body: rawBody,
243
- });
244
-
245
- const authz = await resolveWecomCommandAuthorization({
246
- core,
247
- cfg: config,
248
- accountConfig: account.config,
249
- rawBody,
250
- senderUserId: userId,
251
- });
252
- const commandAuthorized = authz.commandAuthorized;
253
- logVerbose(
254
- target,
255
- `authz: dmPolicy=${authz.dmPolicy} shouldCompute=${authz.shouldComputeAuth} sender=${userId.toLowerCase()} senderAllowed=${authz.senderAllowed} authorizerConfigured=${authz.authorizerConfigured} commandAuthorized=${String(authz.commandAuthorized)}`,
256
- );
257
-
258
- if (authz.shouldComputeAuth && authz.commandAuthorized !== true) {
259
- const prompt = buildWecomUnauthorizedCommandPrompt({ senderUserId: userId, dmPolicy: authz.dmPolicy, scope: "bot" });
260
- streamStore.updateStream(streamId, (s) => {
261
- s.finished = true;
262
- s.content = prompt;
263
- });
264
- try {
265
- await sendBotFallbackPromptNow({ streamId, text: prompt });
266
- logInfo(target, `authz: 未授权命令已提示用户 streamId=${streamId}`);
267
- } catch (err) {
268
- target.runtime.error?.(`authz: 未授权命令提示推送失败 streamId=${streamId}: ${String(err)}`);
269
- }
270
- streamStore.onStreamFinished(streamId);
271
- return;
272
- }
273
-
274
- const attachments = mediaPath
275
- ? [
276
- {
277
- name: media?.filename || "file",
278
- mimeType: mediaType,
279
- url: pathToFileURL(mediaPath).href,
280
- },
281
- ]
282
- : undefined;
283
-
284
- const ctxPayload = core.channel.reply.finalizeInboundContext({
285
- Body: body,
286
- RawBody: rawBody,
287
- CommandBody: rawBody,
288
- Attachments: attachments,
289
- From: chatType === "group" ? `wecom:group:${chatId}` : `wecom:user:${userId}`,
290
- To: chatType === "group" ? `wecom:group:${chatId}` : `wecom:user:${chatId}`,
291
- SessionKey: route.sessionKey,
292
- AccountId: route.accountId,
293
- ChatType: chatType,
294
- ConversationLabel: fromLabel,
295
- SenderName: userId,
296
- SenderId: userId,
297
- Provider: "wecom",
298
- Surface: "wecom",
299
- MessageSid: msg.msgid,
300
- CommandAuthorized: commandAuthorized,
301
- OriginatingChannel: "wecom",
302
- OriginatingTo: chatType === "group" ? `wecom:group:${chatId}` : `wecom:user:${chatId}`,
303
- MediaPath: mediaPath,
304
- MediaType: mediaType,
305
- MediaUrl: mediaPath,
306
- });
307
-
308
- await core.channel.session.recordInboundSession({
309
- storePath,
310
- sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
311
- ctx: ctxPayload,
312
- onRecordError: (err) => {
313
- target.runtime.error?.(`wecom: failed updating session meta: ${String(err)}`);
314
- },
315
- });
316
-
317
- const tableMode = core.channel.text.resolveMarkdownTableMode({
318
- cfg: config,
319
- channel: "wecom",
320
- accountId: account.accountId,
321
- });
322
- const cfgForDispatch = buildWecomBotDispatchConfig(config);
323
- logVerbose(target, "tool-policy: WeCom Bot 会话已禁用 message 工具(tools.deny += message;并同步到 tools.sandbox.tools.deny,防止绕过 Bot 交付)");
324
-
325
- await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
326
- ctx: ctxPayload,
327
- cfg: cfgForDispatch,
328
- replyOptions: { disableBlockStreaming: false },
329
- dispatcherOptions: createBotReplyDispatcher({
330
- streamStore,
331
- target,
332
- accountId: account.accountId,
333
- config,
334
- msg,
335
- streamId,
336
- rawBody,
337
- chatType,
338
- userId,
339
- core,
340
- tableMode,
341
- logVerbose,
342
- truncateUtf8Bytes,
343
- recordBotOperationalEvent,
344
- }),
345
- });
346
-
347
- const rawBodyNormalized = rawBody.trim();
348
- const isResetCommand = /^\/(new|reset)(?:\s|$)/i.test(rawBodyNormalized);
349
- const resetCommandKind = isResetCommand ? (rawBodyNormalized.match(/^\/(new|reset)/i)?.[1]?.toLowerCase() ?? "new") : null;
350
-
351
- await finalizeBotStream({
352
- streamStore,
353
- target,
354
- streamId,
355
- chatType,
356
- core,
357
- config,
358
- accountId: account.accountId,
359
- isResetCommand,
360
- resetCommandKind,
361
- logInfo,
362
- logVerbose,
363
- recordBotOperationalEvent,
364
- });
365
- }
366
-
367
- return {
368
- flushPending,
369
- startAgentForStream,
370
- };
371
- }
@@ -1,8 +0,0 @@
1
- import type { WecomRuntimeAuditEvent, WecomWebhookTarget } from "../../types/runtime-context.js";
2
-
3
- export type BotRuntimeLogger = (target: WecomWebhookTarget, message: string) => void;
4
-
5
- export type RecordBotOperationalEvent = (
6
- target: Pick<WecomWebhookTarget, "account" | "auditSink">,
7
- event: Omit<WecomRuntimeAuditEvent, "transport">,
8
- ) => void;
@@ -1,251 +0,0 @@
1
- # WeCom Calendar Skills 技能清单
2
-
3
- ## 技能列表
4
-
5
- ### wecom_calendar - 企业微信日历工具
6
-
7
- **技能 ID**: `wecom_calendar`
8
- **标签**: `WeCom Calendar`
9
- **描述**: 企业微信日历工具。支持创建/更新/删除日历和日程,管理日程参与者,获取日历详情等功能。
10
-
11
- ## 支持的 Actions (13 个)
12
-
13
- ### 日历管理 (4 个)
14
-
15
- #### 1. calendar_create - 创建日历
16
- **参数**:
17
- - `summary` (必填): 日历标题,1-128 字符
18
- - `color` (必填): RGB 颜色编码,如 #FF3030
19
- - `description` (可选): 日历描述,0-512 字符
20
- - `admins` (可选): 日历管理员 userid 列表,最多 3 人
21
- - `set_as_default` (可选): 是否设为默认日历,0-否,1-是(第三方应用不支持)
22
- - `shares` (可选): 通知范围成员列表,最多 2000 人
23
- - `is_public` (可选): 是否公共日历,0-否,1-是
24
- - `public_range` (可选): 公开范围
25
- - `userids`: 公开的成员列表,最多 1000 个
26
- - `partyids`: 公开的部门列表,最多 100 个
27
- - `is_corp_calendar` (可选): 是否全员日历,0-否,1-是
28
-
29
- **返回**: `{ ok: true, action: "calendar_create", calId: string, raw: object }`
30
-
31
- #### 2. calendar_update - 更新日历
32
- **参数**:
33
- - `cal_id` (必填): 日历 ID
34
- - `summary` (必填): 日历标题,1-128 字符
35
- - `color` (必填): RGB 颜色编码
36
- - `description` (可选): 日历描述,0-512 字符
37
- - `admins` (可选): 日历管理员,最多 3 人
38
- - `shares` (可选): 通知范围成员,最多 2000 人
39
- - `public_range` (可选): 公开范围
40
- - `skip_public_range` (可选): 是否不更新可订阅范围,0-否,1-是
41
-
42
- **返回**: `{ ok: true, action: "calendar_update", calId: string, raw: object }`
43
-
44
- #### 3. calendar_get - 获取日历详情
45
- **参数**:
46
- - `cal_id_list` (必填): 日历 ID 列表,一次最多 1000 条
47
-
48
- **返回**: `{ ok: true, action: "calendar_get", calendarList: array, raw: object }`
49
-
50
- #### 4. calendar_delete - 删除日历
51
- **参数**:
52
- - `cal_id` (必填): 日历 ID
53
-
54
- **返回**: `{ ok: true, action: "calendar_delete", calId: string, raw: object }`
55
-
56
- ### 日程管理 (7 个)
57
-
58
- #### 5. schedule_create - 创建日程
59
- **参数**:
60
- - `start_time` (必填): 日程开始时间,Unix 时间戳(秒)
61
- - `end_time` (必填): 日程结束时间,Unix 时间戳(秒)
62
- - `is_whole_day` (可选): 是否全天日程,0-否,1-是
63
- - `summary` (可选): 日程标题,0-128 字符
64
- - `description` (可选): 日程描述,不多于 1000 字符
65
- - `location` (可选): 日程地址,不多于 128 字符
66
- - `attendees` (可选): 日程参与者列表,最多 1000 人
67
- - `admins` (可选): 日程管理员,最多 3 人
68
- - `reminders` (可选): 提醒相关信息
69
- - `is_remind`: 是否需要提醒,0-否,1-是
70
- - `is_repeat`: 是否重复日程,0-否,1-是
71
- - `remind_before_event_secs`: 日程开始前多少秒提醒 [0,300,900,3600,86400]
72
- - `remind_time_diffs`: 提醒时间与日程开始时间的差值数组
73
- - `repeat_type`: 重复类型 [0-每日,1-每周,2-每月,5-每年,7-工作日]
74
- - `repeat_until`: 重复结束时刻,Unix 时间戳
75
- - `is_custom_repeat`: 是否自定义重复,0-否,1-是
76
- - `repeat_interval`: 重复间隔
77
- - `repeat_day_of_week`: 每周周几重复 [1-7]
78
- - `repeat_day_of_month`: 每月哪几天重复 [1-31]
79
- - `timezone`: 时区 [-12 到 +12]
80
- - `cal_id` (可选): 日程所属日历 ID(第三方应用必须指定)
81
-
82
- **返回**: `{ ok: true, action: "schedule_create", scheduleId: string, raw: object }`
83
-
84
- #### 6. schedule_update - 更新日程
85
- **参数**:
86
- - `schedule_id` (必填): 日程 ID
87
- - `start_time` (必填): 日程开始时间
88
- - `end_time` (必填): 日程结束时间
89
- - `is_whole_day` (可选): 是否全天日程
90
- - `summary` (可选): 日程标题
91
- - `description` (可选): 日程描述
92
- - `location` (可选): 日程地址
93
- - `attendees` (可选): 日程参与者
94
- - `admins` (可选): 日程管理员
95
- - `reminders` (可选): 提醒相关信息
96
- - `skip_attendees` (可选): 是否不更新参与人,0-否,1-是
97
- - `op_mode` (可选): 操作模式 [0-全部修改,1-仅修改此日程,2-修改将来的所有日程]
98
- - `op_start_time` (可选): 操作起始时间
99
-
100
- **返回**: `{ ok: true, action: "schedule_update", scheduleId: string, raw: object }`
101
-
102
- #### 7. schedule_add_attendees - 新增日程参与者
103
- **参数**:
104
- - `schedule_id` (必填): 日程 ID
105
- - `attendees` (必填): 日程参与者列表,累计最多 1000 人
106
-
107
- **返回**: `{ ok: true, action: "schedule_add_attendees", scheduleId: string, raw: object }`
108
-
109
- #### 8. schedule_del_attendees - 删除日程参与者
110
- **参数**:
111
- - `schedule_id` (必填): 日程 ID
112
- - `attendees` (必填): 日程参与者列表,最多 1000 人
113
-
114
- **返回**: `{ ok: true, action: "schedule_del_attendees", scheduleId: string, raw: object }`
115
-
116
- #### 9. schedule_get_by_calendar - 获取日历下的日程列表
117
- **参数**:
118
- - `cal_id` (必填): 日历 ID
119
- - `offset` (可选): 分页偏移量,默认 0
120
- - `limit` (可选): 分页大小,默认 500,范围 1-1000
121
-
122
- **返回**: `{ ok: true, action: "schedule_get_by_calendar", scheduleList: array, raw: object }`
123
-
124
- #### 10. schedule_get - 获取日程详情
125
- **参数**:
126
- - `schedule_id_list` (必填): 日程 ID 列表,一次最多 1000 条
127
-
128
- **返回**: `{ ok: true, action: "schedule_get", scheduleList: array, meetingCode: string, meetingLink: string, raw: object }`
129
-
130
- #### 11. schedule_delete - 取消日程
131
- **参数**:
132
- - `schedule_id` (必填): 日程 ID
133
- - `op_mode` (可选): 操作模式 [0-删除所有,1-仅删除此日程,2-删除本次及后续]
134
- - `op_start_time` (可选): 操作起始时间
135
-
136
- **返回**: `{ ok: true, action: "schedule_delete", scheduleId: string, raw: object }`
137
-
138
- ### 默认日历管理 (2 个)
139
-
140
- #### 12. schedule_get_system_calid - 获取默认日历本 ID
141
- **参数**:
142
- - `userid` (必填): 指定成员的 userid
143
-
144
- **返回**: `{ ok: true, action: "schedule_get_system_calid", calId: string, raw: object }`
145
-
146
- #### 13. schedule_create_in_system - 在默认日历创建日程
147
- **参数**:
148
- - `organizer` (必填): 日程创建者 userid
149
- - `start_time` (必填): 日程开始时间
150
- - `end_time` (必填): 日程结束时间
151
- - `is_whole_day` (可选): 是否全天日程
152
- - `summary` (可选): 日程标题
153
- - `description` (可选): 日程描述
154
- - `location` (可选): 日程地址
155
- - `attendees` (可选): 日程参与者
156
- - `reminders` (可选): 提醒相关信息
157
-
158
- **返回**: `{ ok: true, action: "schedule_create_in_system", scheduleId: string, raw: object }`
159
-
160
- ## 与官方文档对比验证
161
-
162
- ### 接口完整性 ✓
163
- - [x] 创建日历 (calendar/add) - 完整实现
164
- - [x] 更新日历 (calendar/update) - 完整实现
165
- - [x] 获取日历 (calendar/get) - 完整实现
166
- - [x] 删除日历 (calendar/del) - 完整实现
167
- - [x] 创建日程 (schedule/add) - 完整实现
168
- - [x] 更新日程 (schedule/update) - 完整实现
169
- - [x] 新增参与者 (schedule/add_attendees) - 完整实现
170
- - [x] 删除参与者 (schedule/del_attendees) - 完整实现
171
- - [x] 获取日程列表 (schedule/get_by_calendar) - 完整实现
172
- - [x] 获取日程详情 (schedule/get) - 完整实现
173
- - [x] 取消日程 (schedule/del) - 完整实现
174
- - [x] 获取默认日历 ID (calendar/get_system_calid) - 完整实现
175
- - [x] 创建默认日历日程 (schedule/add_schedule_in_system_cal) - 完整实现
176
- - [x] 更新日程回执 (schedule/respond) - 已实现(client.ts)
177
- - [x] 同步日程 (schedule/sync) - 已实现(client.ts)
178
-
179
- ### 参数验证 ✓
180
- - [x] 所有必填参数都有 required 声明
181
- - [x] 所有参数的类型、格式、取值范围都正确
182
- - [x] 所有接口限制都有验证(数量、字符)
183
- - [x] 所有枚举值都正确定义
184
-
185
- ### 返回值处理 ✓
186
- - [x] 所有接口返回结果结构正确
187
- - [x] 错误处理完善(HTTP 错误、JSON 错误、业务错误)
188
- - [x] 重试机制实现(3 次)
189
-
190
- ### 特殊功能 ✓
191
- - [x] op_mode 操作模式支持(0/1/2)
192
- - [x] op_start_time 重复日程操作
193
- - [x] 提醒时间枚举值验证
194
- - [x] 时区范围验证(-12 到 +12)
195
- - [x] 重复日程自定义设置
196
-
197
- ## 已知限制和注意事项
198
-
199
- 1. **第三方应用**:不支持 `set_as_default` 参数
200
- 2. **全员日历**:每个企业最多 20 个,不支持指定颜色
201
- 3. **公共日历**:每人最多创建或订阅 100 个
202
- 4. **日程数量**:每个应用每天最多 2 万个
203
- 5. **重复日程修改**:需指定 op_mode 和 op_start_time
204
- 6. **会议室关联**:已预约会议室的日程更新时间受限
205
-
206
- ## 待实现功能
207
-
208
- 1. **回调事件处理** - 需要在 webhook 中添加以下事件处理:
209
- - delete_calendar
210
- - modify_calendar
211
- - modify_schedule
212
- - delete_schedule
213
- - respond_schedule
214
- - add_schedule
215
-
216
- 2. **完整实现** - client.ts 和 tool.ts 需要完善所有方法的具体实现
217
-
218
- ## 使用示例
219
-
220
- ```json
221
- // 创建日历
222
- {
223
- "action": "calendar_create",
224
- "summary": "团队日历",
225
- "color": "#FF3030",
226
- "description": "团队共享日历",
227
- "admins": ["zhangsan", "lisi"],
228
- "shares": [{"userid": "wangwu", "permission": 1}]
229
- }
230
-
231
- // 创建日程
232
- {
233
- "action": "schedule_create",
234
- "start_time": 1679011200,
235
- "end_time": 1679014800,
236
- "summary": "项目评审会议",
237
- "location": "10 楼会议室",
238
- "attendees": [{"userid": "user1"}, {"userid": "user2"}],
239
- "reminders": {
240
- "is_remind": 1,
241
- "remind_before_event_secs": 3600,
242
- "timezone": 8
243
- }
244
- }
245
-
246
- // 获取日程详情
247
- {
248
- "action": "schedule_get",
249
- "schedule_id_list": ["schedule_id_1", "schedule_id_2"]
250
- }
251
- ```