@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,12 +0,0 @@
1
- /**
2
- * WeCom Agent 模块导出
3
- */
4
-
5
- export { handleAgentWebhook, type AgentWebhookParams } from "./handler.js";
6
- export {
7
- getAccessToken,
8
- sendText,
9
- uploadMedia,
10
- sendMedia,
11
- downloadMedia,
12
- } from "../transport/agent-api/core.js";
@@ -1,186 +0,0 @@
1
- import path from "node:path";
2
- import { spawn } from "node:child_process";
3
-
4
- import type {
5
- WecomAgentEventRouteHandlerConfig,
6
- WecomAgentScriptRuntimeConfig,
7
- } from "../types/index.js";
8
-
9
- export type AgentEventScriptEnvelope = {
10
- version: "1.0";
11
- channel: "wecom";
12
- accountId: string;
13
- receivedAt: number;
14
- message: {
15
- msgType: string;
16
- eventType: string;
17
- eventKey: string | null;
18
- changeType: string | null;
19
- fromUser: string;
20
- toUser: string | null;
21
- chatId: string | null;
22
- agentId: number | null;
23
- createTime: number | null;
24
- msgId: string | null;
25
- raw: Record<string, unknown>;
26
- };
27
- route: {
28
- matchedRuleId: string;
29
- handlerType: "node_script" | "python_script";
30
- };
31
- };
32
-
33
- export type AgentEventScriptResponse = {
34
- ok?: boolean;
35
- action?: "none" | "reply_text";
36
- reply?: {
37
- text?: string;
38
- };
39
- chainToAgent?: boolean;
40
- audit?: {
41
- tags?: string[];
42
- };
43
- error?: string;
44
- };
45
-
46
- export type AgentEventScriptExecutionMeta = {
47
- command: string;
48
- entryPath: string;
49
- durationMs: number;
50
- exitCode: number | null;
51
- };
52
-
53
- function resolveAllowedRoots(runtime: WecomAgentScriptRuntimeConfig): string[] {
54
- return (runtime.allowPaths ?? []).map((entry) => path.resolve(entry));
55
- }
56
-
57
- function resolveScriptEntry(entry: string): string {
58
- return path.resolve(entry);
59
- }
60
-
61
- function ensureScriptAllowed(entryPath: string, runtime: WecomAgentScriptRuntimeConfig): void {
62
- // 安全兜底:脚本执行必须显式开启
63
- if (runtime.enabled !== true) {
64
- throw new Error("script runtime is disabled");
65
- }
66
- // 安全兜底:必须配置允许目录,拒绝任意路径执行
67
- const roots = resolveAllowedRoots(runtime);
68
- if (roots.length === 0) {
69
- throw new Error("script runtime allowPaths is empty");
70
- }
71
- const allowed = roots.some((root) => entryPath === root || entryPath.startsWith(`${root}${path.sep}`));
72
- if (!allowed) {
73
- throw new Error(`script path is not allowed: ${entryPath}`);
74
- }
75
- }
76
-
77
- export async function runAgentEventScript(params: {
78
- runtime: WecomAgentScriptRuntimeConfig | undefined;
79
- handler: Extract<WecomAgentEventRouteHandlerConfig, { type: "node_script" | "python_script" }>;
80
- envelope: AgentEventScriptEnvelope;
81
- }): Promise<{ response: AgentEventScriptResponse; meta: AgentEventScriptExecutionMeta }> {
82
- const runtime = params.runtime ?? {};
83
- const entryPath = resolveScriptEntry(params.handler.entry);
84
- ensureScriptAllowed(entryPath, runtime);
85
-
86
- // 优先使用 route 覆盖值,其次使用全局 runtime 默认值
87
- const timeoutMs = params.handler.timeoutMs ?? runtime.defaultTimeoutMs ?? 5000;
88
- const maxStdoutBytes = runtime.maxStdoutBytes ?? 262144;
89
- const maxStderrBytes = runtime.maxStderrBytes ?? 131072;
90
- const command = params.handler.type === "python_script"
91
- ? runtime.pythonCommand ?? "python3"
92
- : runtime.nodeCommand ?? "node";
93
- const startedAt = Date.now();
94
-
95
- return await new Promise<{ response: AgentEventScriptResponse; meta: AgentEventScriptExecutionMeta }>((resolve, reject) => {
96
- const child = spawn(command, [entryPath], {
97
- cwd: process.cwd(),
98
- stdio: ["pipe", "pipe", "pipe"],
99
- env: {
100
- PATH: process.env.PATH ?? "",
101
- },
102
- });
103
-
104
- let stdout = "";
105
- let stderr = "";
106
- let stdoutExceeded = false;
107
- let stderrExceeded = false;
108
- let settled = false;
109
- let exitCode: number | null = null;
110
-
111
- const finish = (fn: () => void): void => {
112
- if (settled) return;
113
- settled = true;
114
- clearTimeout(timer);
115
- fn();
116
- };
117
-
118
- const timer = setTimeout(() => {
119
- // 超时强制终止,防止脚本阻塞事件处理链
120
- child.kill("SIGKILL");
121
- finish(() => reject(new Error(`script execution timed out after ${timeoutMs}ms`)));
122
- }, timeoutMs);
123
-
124
- child.stdout.on("data", (chunk: Buffer | string) => {
125
- const value = typeof chunk === "string" ? chunk : chunk.toString("utf8");
126
- // 限制输出体积,避免异常脚本刷爆内存/日志
127
- if (Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(value, "utf8") > maxStdoutBytes) {
128
- stdoutExceeded = true;
129
- return;
130
- }
131
- stdout += value;
132
- });
133
-
134
- child.stderr.on("data", (chunk: Buffer | string) => {
135
- const value = typeof chunk === "string" ? chunk : chunk.toString("utf8");
136
- if (Buffer.byteLength(stderr, "utf8") + Buffer.byteLength(value, "utf8") > maxStderrBytes) {
137
- stderrExceeded = true;
138
- return;
139
- }
140
- stderr += value;
141
- });
142
-
143
- child.on("error", (err) => {
144
- finish(() => reject(err));
145
- });
146
-
147
- child.on("close", (code) => {
148
- exitCode = code;
149
- const meta: AgentEventScriptExecutionMeta = {
150
- command,
151
- entryPath,
152
- durationMs: Date.now() - startedAt,
153
- exitCode,
154
- };
155
- if (stdoutExceeded) {
156
- finish(() => reject(new Error("script stdout exceeded limit")));
157
- return;
158
- }
159
- if (stderrExceeded) {
160
- finish(() => reject(new Error("script stderr exceeded limit")));
161
- return;
162
- }
163
- if (code !== 0) {
164
- finish(() => reject(new Error(`script exited with code ${code}: ${stderr.trim() || stdout.trim()}`)));
165
- return;
166
- }
167
- const trimmed = stdout.trim();
168
- if (!trimmed) {
169
- // 空输出按无动作处理,减少脚本端样板代码
170
- finish(() => resolve({ response: { ok: true, action: "none" }, meta }));
171
- return;
172
- }
173
- try {
174
- // 脚本协议要求 stdout 必须是 JSON
175
- const parsed = JSON.parse(trimmed) as AgentEventScriptResponse;
176
- finish(() => resolve({ response: parsed, meta }));
177
- } catch (err) {
178
- finish(() => reject(new Error(`script output is not valid JSON: ${String(err)}`)));
179
- }
180
- });
181
-
182
- // 将完整 envelope 传给脚本,再关闭 stdin
183
- child.stdin.write(JSON.stringify(params.envelope));
184
- child.stdin.end();
185
- });
186
- }
@@ -1 +0,0 @@
1
- process.stdout.write("this is not json");
@@ -1,29 +0,0 @@
1
- let raw = "";
2
- process.stdin.setEncoding("utf8");
3
- process.stdin.on("data", (chunk) => {
4
- raw += chunk;
5
- });
6
- process.stdin.on("end", () => {
7
- const payload = JSON.parse(raw || "{}");
8
- const eventType = payload?.message?.eventType ?? "unknown";
9
- const eventKey = payload?.message?.eventKey ?? "";
10
- const changeType = payload?.message?.changeType ?? "";
11
-
12
- if (eventKey === "PASS_TO_DEFAULT") {
13
- process.stdout.write(JSON.stringify({
14
- ok: true,
15
- action: "none",
16
- chainToAgent: true,
17
- }));
18
- return;
19
- }
20
-
21
- process.stdout.write(JSON.stringify({
22
- ok: true,
23
- action: "reply_text",
24
- reply: {
25
- text: `script:${eventType}:${eventKey}:${changeType}`,
26
- },
27
- chainToAgent: false,
28
- }));
29
- });
@@ -1,17 +0,0 @@
1
- import json
2
- import sys
3
-
4
- payload = json.load(sys.stdin)
5
- message = payload.get("message", {})
6
- event_type = message.get("eventType", "unknown")
7
- event_key = message.get("eventKey") or ""
8
- change_type = message.get("changeType") or ""
9
-
10
- json.dump({
11
- "ok": True,
12
- "action": "reply_text",
13
- "reply": {
14
- "text": f"python:{event_type}:{event_key}:{change_type}"
15
- },
16
- "chainToAgent": False
17
- }, sys.stdout)
@@ -1,276 +0,0 @@
1
- import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk";
2
- import { formatErrorMessage } from "openclaw/plugin-sdk/infra-runtime";
3
- import type { ResolvedRuntimeAccount } from "../config/runtime-config.js";
4
- import { WecomAuditLog } from "../observability/audit-log.js";
5
- import { WecomStatusRegistry } from "../observability/status-registry.js";
6
- import { summarizeTransportSessions } from "../observability/transport-session-view.js";
7
- import { dispatchInboundEvent } from "../runtime/dispatcher.js";
8
- import { WecomMediaService } from "../shared/media-service.js";
9
- import { InMemoryRuntimeStore } from "../store/memory-store.js";
10
- import type {
11
- AccountRuntimeStatusSnapshot,
12
- ReplyHandle,
13
- ReplyPayload,
14
- TransportSessionPatch,
15
- TransportSessionSnapshot,
16
- UnifiedInboundEvent,
17
- WecomAuditCategory,
18
- WecomRuntimeHealth,
19
- WecomTransportKind,
20
- } from "../types/index.js";
21
-
22
- export class WecomAccountRuntime {
23
- readonly store = new InMemoryRuntimeStore();
24
- readonly mediaService: WecomMediaService;
25
- readonly auditLog = new WecomAuditLog();
26
- readonly statusRegistry = new WecomStatusRegistry();
27
- private readonly runtimeStatus: AccountRuntimeStatusSnapshot;
28
-
29
- constructor(
30
- readonly core: PluginRuntime,
31
- readonly cfg: OpenClawConfig,
32
- readonly resolved: ResolvedRuntimeAccount,
33
- readonly log: {
34
- info?: (message: string) => void;
35
- warn?: (message: string) => void;
36
- error?: (message: string) => void;
37
- } = {},
38
- private readonly statusSink?: (snapshot: Record<string, unknown>) => void,
39
- ) {
40
- this.mediaService = new WecomMediaService(core, cfg);
41
- this.runtimeStatus = {
42
- accountId: resolved.account.accountId,
43
- health: "idle",
44
- ownerId: null,
45
- ownerDriftAt: null,
46
- lastError: null,
47
- lastErrorAt: null,
48
- lastInboundAt: null,
49
- lastOutboundAt: null,
50
- recentInboundSummary: null,
51
- recentOutboundSummary: null,
52
- recentIssueCategory: null,
53
- recentIssueSummary: null,
54
- transportSessions: [],
55
- };
56
- }
57
-
58
- get account() {
59
- return this.resolved.account;
60
- }
61
-
62
- async handleEvent(event: UnifiedInboundEvent, replyHandle: ReplyHandle): Promise<void> {
63
- const dispatchStartedAt = Date.now();
64
- this.runtimeStatus.lastInboundAt = Date.now();
65
- this.runtimeStatus.recentInboundSummary = `${event.transport} ${event.inboundKind} ${event.messageId}`;
66
- this.log.info?.(
67
- `[wecom-runtime] inbound account=${event.accountId} transport=${event.transport} kind=${event.inboundKind} messageId=${event.messageId} peer=${event.conversation.peerKind}:${event.conversation.peerId}`,
68
- );
69
- this.log.info?.(
70
- `[wecom-runtime] dispatch-start account=${event.accountId} transport=${event.transport} kind=${event.inboundKind} messageId=${event.messageId}`,
71
- );
72
- this.emitStatus();
73
-
74
- const trackedReplyHandle: ReplyHandle = {
75
- context: replyHandle.context,
76
- deliver: async (payload: ReplyPayload, info) => {
77
- const deliverStartedAt = Date.now();
78
- const textLen = payload.text?.trim().length ?? 0;
79
- const mediaCount = (payload.mediaUrls?.length ?? 0) + (payload.mediaUrl ? 1 : 0);
80
- this.log.info?.(
81
- `[wecom-runtime] deliver-start account=${event.accountId} transport=${replyHandle.context.transport} kind=${info.kind} messageId=${event.messageId} textLen=${textLen} mediaCount=${mediaCount} reasoning=${String(payload.isReasoning === true)}`,
82
- );
83
- await replyHandle.deliver(payload, info);
84
- this.runtimeStatus.lastOutboundAt = Date.now();
85
- const outboundSummary =
86
- payload.text?.trim() || payload.mediaUrl || payload.mediaUrls?.[0] || info.kind;
87
- this.runtimeStatus.recentOutboundSummary = `${replyHandle.context.transport} ${outboundSummary.slice(0, 120)}`;
88
- this.log.info?.(
89
- `[wecom-runtime] outbound account=${event.accountId} transport=${replyHandle.context.transport} kind=${info.kind} messageId=${event.messageId} summary=${JSON.stringify(this.runtimeStatus.recentOutboundSummary)}`,
90
- );
91
- this.log.info?.(
92
- `[wecom-runtime] deliver-done account=${event.accountId} transport=${replyHandle.context.transport} kind=${info.kind} messageId=${event.messageId} durationMs=${Date.now() - deliverStartedAt}`,
93
- );
94
- this.emitStatus();
95
- },
96
- fail: async (error: unknown) => {
97
- const formattedError = formatErrorMessage(error);
98
- this.recordOperationalIssue({
99
- transport: replyHandle.context.transport,
100
- category: "runtime-error",
101
- messageId: event.messageId,
102
- raw: replyHandle.context.raw,
103
- summary: `reply-fail ${formattedError}`,
104
- error: formattedError,
105
- });
106
- this.log.error?.(
107
- `[wecom-runtime] reply-fail account=${event.accountId} transport=${replyHandle.context.transport} messageId=${event.messageId} error=${formattedError}`,
108
- );
109
- await replyHandle.fail?.(error);
110
- },
111
- markExternalActivity: () => {
112
- replyHandle.markExternalActivity?.();
113
- },
114
- };
115
-
116
- try {
117
- await dispatchInboundEvent({
118
- core: this.core,
119
- cfg: this.cfg,
120
- store: this.store,
121
- auditLog: this.auditLog,
122
- mediaService: this.mediaService,
123
- event,
124
- replyHandle: trackedReplyHandle,
125
- });
126
- this.log.info?.(
127
- `[wecom-runtime] dispatch-done account=${event.accountId} transport=${event.transport} kind=${event.inboundKind} messageId=${event.messageId} durationMs=${Date.now() - dispatchStartedAt}`,
128
- );
129
- } catch (error) {
130
- this.log.error?.(
131
- `[wecom-runtime] dispatch-fail account=${event.accountId} transport=${event.transport} kind=${event.inboundKind} messageId=${event.messageId} durationMs=${Date.now() - dispatchStartedAt} error=${formatErrorMessage(error)}`,
132
- );
133
- throw error;
134
- }
135
- }
136
-
137
- updateTransportSession(snapshot: TransportSessionSnapshot): void {
138
- const previous = this.store.readTransportSession(snapshot.accountId, snapshot.transport);
139
- this.store.writeTransportSession(snapshot);
140
- this.statusRegistry.write(snapshot);
141
- this.log.info?.(
142
- `[wecom-runtime] session account=${snapshot.accountId} transport=${snapshot.transport} running=${snapshot.running} owner=${snapshot.ownerId ?? "none"} connected=${String(snapshot.connected ?? false)} authenticated=${String(snapshot.authenticated ?? false)} error=${snapshot.lastError ?? "none"}`,
143
- );
144
- if (
145
- previous?.ownerId &&
146
- snapshot.ownerId &&
147
- previous.ownerId !== snapshot.ownerId &&
148
- previous.running
149
- ) {
150
- this.recordOperationalIssue({
151
- transport: snapshot.transport,
152
- category: "owner-drift",
153
- summary: `owner drift ${previous.ownerId} -> ${snapshot.ownerId}`,
154
- });
155
- }
156
- if (snapshot.lastError) {
157
- this.runtimeStatus.lastError = snapshot.lastError;
158
- this.runtimeStatus.lastErrorAt = Date.now();
159
- } else if (snapshot.running) {
160
- this.runtimeStatus.lastError = null;
161
- }
162
- this.emitStatus();
163
- }
164
-
165
- touchTransportSession(transport: WecomTransportKind, patch: TransportSessionPatch): void {
166
- const current = this.store.readTransportSession(this.account.accountId, transport);
167
- const next: TransportSessionSnapshot = {
168
- accountId: this.account.accountId,
169
- transport,
170
- running: patch.running ?? current?.running ?? true,
171
- ownerId: patch.ownerId ?? current?.ownerId,
172
- connected: patch.connected ?? current?.connected,
173
- authenticated: patch.authenticated ?? current?.authenticated,
174
- lastConnectedAt: patch.lastConnectedAt ?? current?.lastConnectedAt,
175
- lastDisconnectedAt: patch.lastDisconnectedAt ?? current?.lastDisconnectedAt,
176
- lastInboundAt: patch.lastInboundAt ?? current?.lastInboundAt,
177
- lastOutboundAt: patch.lastOutboundAt ?? current?.lastOutboundAt,
178
- lastError: "lastError" in patch ? (patch.lastError ?? undefined) : current?.lastError,
179
- };
180
- this.updateTransportSession(next);
181
- }
182
-
183
- listTransportSessions() {
184
- return this.statusRegistry.read(this.account.accountId);
185
- }
186
-
187
- listAuditEntries() {
188
- return this.auditLog.list();
189
- }
190
-
191
- buildRuntimeStatus(): AccountRuntimeStatusSnapshot {
192
- const sessions = this.listTransportSessions();
193
- const primarySession = this.resolvePrimarySession(sessions);
194
- return {
195
- ...this.runtimeStatus,
196
- health: this.computeHealth(sessions),
197
- transport: primarySession?.transport,
198
- ownerId: primarySession?.ownerId ?? this.runtimeStatus.ownerId ?? null,
199
- connected: primarySession?.connected,
200
- authenticated: primarySession?.authenticated,
201
- lastError:
202
- primarySession?.lastError ??
203
- (primarySession?.running ? null : (this.runtimeStatus.lastError ?? null)),
204
- transportSessions: summarizeTransportSessions(sessions),
205
- };
206
- }
207
-
208
- recordOperationalIssue(params: {
209
- transport: WecomTransportKind;
210
- category: WecomAuditCategory;
211
- summary: string;
212
- messageId?: string;
213
- raw?: ReplyHandle["context"]["raw"];
214
- error?: string;
215
- }): void {
216
- this.auditLog.appendOperational({
217
- accountId: this.account.accountId,
218
- transport: params.transport,
219
- category: params.category,
220
- messageId: params.messageId,
221
- summary: params.summary,
222
- raw: params.raw,
223
- error: params.error,
224
- });
225
- if (params.category === "owner-drift" || params.category === "ws-kicked") {
226
- this.runtimeStatus.ownerDriftAt = Date.now();
227
- }
228
- this.runtimeStatus.lastError = params.error ?? params.summary;
229
- this.runtimeStatus.lastErrorAt = Date.now();
230
- this.runtimeStatus.recentIssueCategory = params.category;
231
- this.runtimeStatus.recentIssueSummary = params.summary;
232
- const sink =
233
- params.category === "runtime-error" || params.category === "fallback-delivery-failed"
234
- ? this.log.error
235
- : this.log.warn;
236
- sink?.(
237
- `[wecom-runtime] issue account=${this.account.accountId} transport=${params.transport} category=${params.category} messageId=${params.messageId ?? "n/a"} summary=${params.summary}`,
238
- );
239
- this.emitStatus();
240
- }
241
-
242
- private emitStatus(): void {
243
- this.statusSink?.(this.buildRuntimeStatus() as unknown as Record<string, unknown>);
244
- }
245
-
246
- private resolvePrimarySession(
247
- sessions: TransportSessionSnapshot[],
248
- ): TransportSessionSnapshot | undefined {
249
- const primaryTransport = this.account.bot?.configured
250
- ? this.account.bot.primaryTransport === "ws"
251
- ? "bot-ws"
252
- : "bot-webhook"
253
- : this.account.agent?.callbackConfigured
254
- ? "agent-callback"
255
- : undefined;
256
- if (!primaryTransport) {
257
- return sessions[0];
258
- }
259
- return sessions.find((session) => session.transport === primaryTransport) ?? sessions[0];
260
- }
261
-
262
- private computeHealth(sessions: TransportSessionSnapshot[]): WecomRuntimeHealth {
263
- if (sessions.length === 0) {
264
- return this.runtimeStatus.lastError ? "down" : "idle";
265
- }
266
- const hasRunning = sessions.some((session) => session.running);
267
- const hasError = sessions.some((session) => Boolean(session.lastError));
268
- if (hasRunning && !hasError) {
269
- return "healthy";
270
- }
271
- if (hasRunning) {
272
- return "degraded";
273
- }
274
- return hasError ? "down" : "idle";
275
- }
276
- }
@@ -1,29 +0,0 @@
1
- import type { ChannelGatewayContext } from "openclaw/plugin-sdk";
2
-
3
- import { resolveWecomRuntimeAccount } from "../config/runtime-config.js";
4
- import type { ResolvedWecomAccount } from "../types/index.js";
5
- import { WecomAccountRuntime } from "./account-runtime.js";
6
- import { getWecomRuntime } from "./index.js";
7
-
8
- export function createAccountRuntime(ctx: ChannelGatewayContext<ResolvedWecomAccount>): WecomAccountRuntime {
9
- const resolved = resolveWecomRuntimeAccount({
10
- cfg: ctx.cfg,
11
- accountId: ctx.accountId,
12
- });
13
- return new WecomAccountRuntime(
14
- getWecomRuntime(),
15
- ctx.cfg,
16
- resolved,
17
- {
18
- info: (message) => ctx.log?.info(message),
19
- warn: (message) => ctx.log?.warn(message),
20
- error: (message) => ctx.log?.error(message),
21
- },
22
- (snapshot) => {
23
- ctx.setStatus({
24
- accountId: ctx.accountId,
25
- ...snapshot,
26
- });
27
- },
28
- );
29
- }