@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.
- package/README.md +4 -5
- package/dist/index.js +68 -0
- package/dist/src/accounts.js +20 -0
- package/dist/src/agent/handler.js +895 -0
- package/dist/src/agent/index.js +5 -0
- package/dist/src/app/account-runtime.js +216 -0
- package/dist/src/app/bootstrap.js +19 -0
- package/dist/src/app/index.js +118 -0
- package/dist/src/capability/agent/delivery-service.js +63 -0
- package/dist/src/capability/agent/fallback-policy.js +6 -0
- package/dist/src/capability/agent/ingress-service.js +33 -0
- package/dist/src/capability/agent/upstream-delivery-service.js +71 -0
- package/dist/src/capability/bot/dispatch-config.js +45 -0
- package/dist/src/capability/bot/fallback-delivery.js +147 -0
- package/dist/src/capability/bot/local-path-delivery.js +178 -0
- package/dist/src/capability/bot/sandbox-media.js +138 -0
- package/dist/src/capability/bot/service.js +49 -0
- package/dist/src/capability/bot/stream-delivery.js +321 -0
- package/dist/src/capability/bot/stream-finalizer.js +81 -0
- package/dist/src/capability/bot/stream-orchestrator.js +318 -0
- package/dist/src/capability/bot/types.js +1 -0
- package/{src/capability/calendar/client.ts → dist/src/capability/calendar/client.js} +118 -241
- package/{src/capability/calendar/schema.ts → dist/src/capability/calendar/schema.js} +0 -38
- package/dist/src/capability/calendar/tool.js +365 -0
- package/dist/src/capability/calendar/types.js +12 -0
- package/{src/capability/doc/client.ts → dist/src/capability/doc/client.js} +370 -605
- package/{src/capability/doc/schema.ts → dist/src/capability/doc/schema.js} +345 -394
- package/dist/src/capability/doc/tool.js +1556 -0
- package/dist/src/capability/doc/types.js +113 -0
- package/dist/src/capability/mcp/index.js +3 -0
- package/dist/src/capability/mcp/schema.js +102 -0
- package/dist/src/capability/mcp/tool.js +146 -0
- package/dist/src/capability/mcp/transport.js +293 -0
- package/dist/src/channel.js +224 -0
- package/dist/src/config/accounts.js +236 -0
- package/dist/src/config/derived-paths.js +31 -0
- package/dist/src/config/index.js +7 -0
- package/dist/src/config/media.js +110 -0
- package/dist/src/config/network.js +32 -0
- package/dist/src/config/routing.js +20 -0
- package/dist/src/config/runtime-config.js +25 -0
- package/dist/src/config/schema.js +4 -0
- package/{src/config-schema.ts → dist/src/config-schema.js} +1 -1
- package/dist/src/context-store.js +219 -0
- package/{src/crypto/aes.ts → dist/src/crypto/aes.js} +11 -28
- package/dist/src/crypto/index.js +9 -0
- package/{src/crypto/signature.ts → dist/src/crypto/signature.js} +3 -18
- package/{src/crypto/xml.ts → dist/src/crypto/xml.js} +3 -11
- package/dist/src/crypto.js +145 -0
- package/dist/src/domain/models.js +1 -0
- package/dist/src/domain/policies.js +32 -0
- package/{src/dynamic-agent.ts → dist/src/dynamic-agent.js} +36 -73
- package/dist/src/gateway-monitor.js +139 -0
- package/dist/src/http.js +114 -0
- package/{src/media.ts → dist/src/media.js} +21 -40
- package/dist/src/monitor/limits.js +7 -0
- package/dist/src/monitor/state.js +28 -0
- package/dist/src/monitor.js +84 -0
- package/dist/src/observability/audit-log.js +30 -0
- package/dist/src/observability/legacy-operational-event-store.js +22 -0
- package/dist/src/observability/raw-envelope-log.js +24 -0
- package/dist/src/observability/status-registry.js +9 -0
- package/dist/src/observability/transport-session-view.js +14 -0
- package/dist/src/onboarding.js +546 -0
- package/dist/src/outbound.js +557 -0
- package/dist/src/runtime/dispatcher.js +57 -0
- package/{src/runtime/index.ts → dist/src/runtime/index.js} +0 -1
- package/dist/src/runtime/outbound-intent.js +1 -0
- package/dist/src/runtime/reply-orchestrator.js +38 -0
- package/dist/src/runtime/routing-bridge.js +26 -0
- package/dist/src/runtime/session-manager.js +112 -0
- package/dist/src/runtime/source-registry.js +174 -0
- package/dist/src/runtime.js +1 -0
- package/dist/src/shared/command-auth.js +57 -0
- package/{src/shared/index.ts → dist/src/shared/index.js} +0 -1
- package/dist/src/shared/media-asset.js +65 -0
- package/dist/src/shared/media-service.js +59 -0
- package/dist/src/shared/media-types.js +1 -0
- package/{src/shared/xml-parser.ts → dist/src/shared/xml-parser.js} +72 -63
- package/dist/src/store/active-reply-store.js +41 -0
- package/dist/src/store/interfaces.js +1 -0
- package/dist/src/store/memory-store.js +33 -0
- package/dist/src/store/stream-batch-store.js +319 -0
- package/{src/target.ts → dist/src/target.js} +15 -48
- package/dist/src/transport/agent-api/client.js +168 -0
- package/dist/src/transport/agent-api/core.js +337 -0
- package/dist/src/transport/agent-api/delivery.js +28 -0
- package/dist/src/transport/agent-api/media-upload.js +4 -0
- package/dist/src/transport/agent-api/reply.js +24 -0
- package/dist/src/transport/agent-api/upstream-delivery.js +30 -0
- package/dist/src/transport/agent-api/upstream-media-upload.js +46 -0
- package/dist/src/transport/agent-api/upstream-reply.js +26 -0
- package/dist/src/transport/agent-callback/http-handler.js +30 -0
- package/dist/src/transport/agent-callback/inbound.js +4 -0
- package/dist/src/transport/agent-callback/reply.js +8 -0
- package/dist/src/transport/agent-callback/request-handler.js +189 -0
- package/dist/src/transport/agent-callback/session.js +15 -0
- package/dist/src/transport/bot-webhook/active-reply.js +27 -0
- package/dist/src/transport/bot-webhook/http-handler.js +31 -0
- package/dist/src/transport/bot-webhook/inbound-normalizer.js +496 -0
- package/dist/src/transport/bot-webhook/inbound.js +4 -0
- package/dist/src/transport/bot-webhook/message-shape.js +98 -0
- package/dist/src/transport/bot-webhook/protocol.js +124 -0
- package/dist/src/transport/bot-webhook/reply.js +9 -0
- package/dist/src/transport/bot-webhook/request-handler.js +285 -0
- package/dist/src/transport/bot-webhook/session.js +15 -0
- package/dist/src/transport/bot-ws/inbound.js +147 -0
- package/dist/src/transport/bot-ws/media.js +236 -0
- package/dist/src/transport/bot-ws/reply.js +310 -0
- package/dist/src/transport/bot-ws/sdk-adapter.js +257 -0
- package/dist/src/transport/bot-ws/session.js +15 -0
- package/dist/src/transport/http/common.js +78 -0
- package/dist/src/transport/http/registry.js +71 -0
- package/dist/src/transport/http/request-handler.js +51 -0
- package/{src/transport/index.ts → dist/src/transport/index.js} +2 -10
- package/dist/src/types/account.js +1 -0
- package/dist/src/types/config.js +1 -0
- package/dist/src/types/constants.js +28 -0
- package/dist/src/types/events.js +1 -0
- package/dist/src/types/index.js +1 -0
- package/dist/src/types/legacy-stream.js +1 -0
- package/dist/src/types/message.js +5 -0
- package/dist/src/types/runtime-context.js +1 -0
- package/dist/src/types/runtime.js +1 -0
- package/dist/src/types.js +1 -0
- package/dist/src/upstream/index.js +111 -0
- package/dist/src/wecom_msg_adapter/markdown_adapter.js +280 -0
- package/openclaw.plugin.json +15 -0
- package/package.json +18 -1
- package/.github/workflows/release.yml +0 -143
- package/GOVERNANCE.md +0 -26
- package/MENU_EVENT_CONF.md +0 -500
- package/MENU_EVENT_PLAN.md +0 -440
- package/SKILLS_CAL.md +0 -895
- package/SKILLS_DOC.md +0 -2288
- package/UPSTREAM_CONFIG.md +0 -170
- package/UPSTREAM_PLAN.md +0 -175
- package/assets/01.bot-add.png +0 -0
- package/assets/01.bot-setp2.png +0 -0
- package/assets/01.image.jpg +0 -0
- package/assets/02.agent.add.png +0 -0
- package/assets/02.agent.api-set.png +0 -0
- package/assets/02.image.jpg +0 -0
- package/assets/03.agent.page.png +0 -0
- package/assets/03.bot.page.png +0 -0
- package/assets/link-me.jpg +0 -0
- package/assets/register.png +0 -0
- package/changelog/v2.2.28.md +0 -70
- package/changelog/v2.3.10.md +0 -17
- package/changelog/v2.3.11.md +0 -19
- package/changelog/v2.3.12.md +0 -25
- package/changelog/v2.3.13.md +0 -19
- package/changelog/v2.3.14.md +0 -48
- package/changelog/v2.3.15.md +0 -15
- package/changelog/v2.3.16.md +0 -11
- package/changelog/v2.3.18.md +0 -22
- package/changelog/v2.3.19.md +0 -73
- package/changelog/v2.3.2.md +0 -28
- package/changelog/v2.3.26.md +0 -21
- package/changelog/v2.3.27.md +0 -33
- package/changelog/v2.3.4.md +0 -20
- package/changelog/v2.3.9.md +0 -22
- package/changelog/v2.4.12.md +0 -37
- package/compat-single-account.md +0 -148
- package/index.test.ts +0 -38
- package/scripts/test-proxy.ts +0 -70
- package/scripts/wecom/README.md +0 -123
- package/scripts/wecom/menu-click-help.js +0 -59
- package/scripts/wecom/menu-click-help.py +0 -55
- package/src/accounts.ts +0 -34
- package/src/agent/api-client.upload.test.ts +0 -109
- package/src/agent/event-router.test.ts +0 -421
- package/src/agent/event-router.ts +0 -272
- package/src/agent/handler.event-filter.test.ts +0 -135
- package/src/agent/handler.ts +0 -1250
- package/src/agent/index.ts +0 -12
- package/src/agent/script-runner.ts +0 -186
- package/src/agent/test-fixtures/invalid-json-script.mjs +0 -1
- package/src/agent/test-fixtures/reply-event-script.mjs +0 -29
- package/src/agent/test-fixtures/reply-event-script.py +0 -17
- package/src/app/account-runtime.ts +0 -276
- package/src/app/bootstrap.ts +0 -29
- package/src/app/index.ts +0 -192
- package/src/capability/agent/delivery-service.ts +0 -87
- package/src/capability/agent/fallback-policy.ts +0 -13
- package/src/capability/agent/ingress-service.ts +0 -38
- package/src/capability/agent/upstream-delivery-service.ts +0 -96
- package/src/capability/bot/dispatch-config.ts +0 -47
- package/src/capability/bot/fallback-delivery.ts +0 -178
- package/src/capability/bot/local-path-delivery.ts +0 -215
- package/src/capability/bot/sandbox-media.test.ts +0 -221
- package/src/capability/bot/sandbox-media.ts +0 -176
- package/src/capability/bot/service.ts +0 -56
- package/src/capability/bot/stream-delivery.ts +0 -379
- package/src/capability/bot/stream-finalizer.ts +0 -120
- package/src/capability/bot/stream-orchestrator.ts +0 -371
- package/src/capability/bot/types.ts +0 -8
- package/src/capability/calendar/SKILLS_CHECKLIST.md +0 -251
- package/src/capability/calendar/tool.ts +0 -417
- package/src/capability/calendar/types.ts +0 -309
- package/src/capability/doc/tool.ts +0 -1629
- package/src/capability/doc/types.ts +0 -792
- package/src/capability/mcp/index.ts +0 -10
- package/src/capability/mcp/schema.ts +0 -107
- package/src/capability/mcp/tool.ts +0 -174
- package/src/capability/mcp/transport.ts +0 -394
- package/src/channel.config.test.ts +0 -180
- package/src/channel.lifecycle.test.ts +0 -255
- package/src/channel.meta.test.ts +0 -26
- package/src/channel.ts +0 -256
- package/src/config/accounts.resolve.test.ts +0 -75
- package/src/config/accounts.ts +0 -312
- package/src/config/derived-paths.test.ts +0 -111
- package/src/config/derived-paths.ts +0 -41
- package/src/config/index.ts +0 -22
- package/src/config/media.test.ts +0 -113
- package/src/config/media.ts +0 -139
- package/src/config/network.ts +0 -20
- package/src/config/routing.test.ts +0 -88
- package/src/config/routing.ts +0 -26
- package/src/config/runtime-config.ts +0 -46
- package/src/config/schema.ts +0 -144
- package/src/context-store.ts +0 -297
- package/src/crypto/index.ts +0 -24
- package/src/crypto.test.ts +0 -32
- package/src/crypto.ts +0 -176
- package/src/domain/models.ts +0 -7
- package/src/domain/policies.ts +0 -36
- package/src/dynamic-agent.account-scope.test.ts +0 -17
- package/src/gateway-monitor.ts +0 -181
- package/src/http.ts +0 -137
- package/src/media.test.ts +0 -82
- package/src/monitor/limits.ts +0 -7
- package/src/monitor/state.queue.test.ts +0 -185
- package/src/monitor/state.ts +0 -34
- package/src/monitor.active.test.ts +0 -245
- package/src/monitor.inbound-filter.test.ts +0 -63
- package/src/monitor.integration.test.ts +0 -208
- package/src/monitor.ts +0 -121
- package/src/monitor.webhook.test.ts +0 -774
- package/src/observability/audit-log.ts +0 -48
- package/src/observability/legacy-operational-event-store.ts +0 -36
- package/src/observability/raw-envelope-log.ts +0 -28
- package/src/observability/status-registry.ts +0 -13
- package/src/observability/transport-session-view.ts +0 -14
- package/src/onboarding.test.ts +0 -336
- package/src/onboarding.ts +0 -704
- package/src/outbound.test.ts +0 -1271
- package/src/outbound.ts +0 -746
- package/src/runtime/dispatcher.ts +0 -71
- package/src/runtime/outbound-intent.ts +0 -4
- package/src/runtime/reply-orchestrator.test.ts +0 -71
- package/src/runtime/reply-orchestrator.ts +0 -67
- package/src/runtime/routing-bridge.test.ts +0 -115
- package/src/runtime/routing-bridge.ts +0 -44
- package/src/runtime/session-manager.test.ts +0 -174
- package/src/runtime/session-manager.ts +0 -139
- package/src/runtime/source-registry.ts +0 -249
- package/src/runtime.ts +0 -14
- package/src/shared/command-auth.ts +0 -87
- package/src/shared/media-asset.ts +0 -78
- package/src/shared/media-service.test.ts +0 -111
- package/src/shared/media-service.ts +0 -84
- package/src/shared/media-types.ts +0 -5
- package/src/shared/xml-parser.test.ts +0 -50
- package/src/store/active-reply-store.ts +0 -42
- package/src/store/interfaces.ts +0 -11
- package/src/store/memory-store.ts +0 -43
- package/src/store/stream-batch-store.ts +0 -350
- package/src/transport/agent-api/client.ts +0 -277
- package/src/transport/agent-api/core.ts +0 -463
- package/src/transport/agent-api/delivery.ts +0 -41
- package/src/transport/agent-api/media-upload.ts +0 -11
- package/src/transport/agent-api/reply.ts +0 -39
- package/src/transport/agent-api/upstream-delivery.ts +0 -45
- package/src/transport/agent-api/upstream-media-upload.ts +0 -70
- package/src/transport/agent-api/upstream-reply.ts +0 -43
- package/src/transport/agent-callback/http-handler.ts +0 -47
- package/src/transport/agent-callback/inbound.ts +0 -5
- package/src/transport/agent-callback/reply.ts +0 -13
- package/src/transport/agent-callback/request-handler.ts +0 -244
- package/src/transport/agent-callback/session.ts +0 -23
- package/src/transport/bot-webhook/active-reply.ts +0 -39
- package/src/transport/bot-webhook/http-handler.ts +0 -48
- package/src/transport/bot-webhook/inbound-normalizer.ts +0 -371
- package/src/transport/bot-webhook/inbound.ts +0 -5
- package/src/transport/bot-webhook/message-shape.ts +0 -89
- package/src/transport/bot-webhook/protocol.ts +0 -148
- package/src/transport/bot-webhook/reply.ts +0 -15
- package/src/transport/bot-webhook/request-handler.ts +0 -394
- package/src/transport/bot-webhook/session.ts +0 -23
- package/src/transport/bot-ws/inbound.test.ts +0 -96
- package/src/transport/bot-ws/inbound.ts +0 -116
- package/src/transport/bot-ws/media.test.ts +0 -44
- package/src/transport/bot-ws/media.ts +0 -321
- package/src/transport/bot-ws/reply.test.ts +0 -450
- package/src/transport/bot-ws/reply.ts +0 -365
- package/src/transport/bot-ws/sdk-adapter.test.ts +0 -187
- package/src/transport/bot-ws/sdk-adapter.ts +0 -314
- package/src/transport/bot-ws/session.ts +0 -28
- package/src/transport/http/common.ts +0 -109
- package/src/transport/http/registry.ts +0 -92
- package/src/transport/http/request-handler.ts +0 -84
- package/src/types/account.ts +0 -72
- package/src/types/config.ts +0 -166
- package/src/types/constants.ts +0 -31
- package/src/types/events.ts +0 -21
- package/src/types/global.d.ts +0 -9
- package/src/types/index.ts +0 -17
- package/src/types/legacy-stream.ts +0 -50
- package/src/types/message.ts +0 -187
- package/src/types/runtime-context.ts +0 -28
- package/src/types/runtime.ts +0 -165
- package/src/types.ts +0 -41
- package/src/upstream/index.ts +0 -150
- package/src/upstream.test.ts +0 -84
- package/src/wecom_msg_adapter/markdown_adapter.ts +0 -331
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -26
- /package/{src/capability/agent/index.ts → dist/src/capability/agent/index.js} +0 -0
- /package/{src/capability/bot/index.ts → dist/src/capability/bot/index.js} +0 -0
- /package/{src/capability/calendar/index.ts → dist/src/capability/calendar/index.js} +0 -0
- /package/{src/capability/index.ts → dist/src/capability/index.js} +0 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将较完整的 Markdown 降级转换为更适合企业微信 markdown_v2 的子集。
|
|
3
|
+
*
|
|
4
|
+
* 保守策略:
|
|
5
|
+
* - 保留:标题、粗体、斜体、引用、链接、行内代码、普通列表、表格
|
|
6
|
+
* - 降级:代码块、图片、任务列表、分隔线、HTML、脚注、复杂语法
|
|
7
|
+
* - 清理:多余空行、非法控制字符、过深嵌套
|
|
8
|
+
*/
|
|
9
|
+
export function toWeComMarkdownV2(markdown, maxLength = 4096) {
|
|
10
|
+
if (!markdown)
|
|
11
|
+
return "";
|
|
12
|
+
let text = String(markdown).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
13
|
+
const extracted = extractInlineCodeSpans(text);
|
|
14
|
+
text = extracted.text;
|
|
15
|
+
const inlineCodeStore = extracted.store;
|
|
16
|
+
text = convertFencedCodeBlocks(text);
|
|
17
|
+
text = convertIndentedCodeBlocks(text);
|
|
18
|
+
text = convertImages(text);
|
|
19
|
+
text = convertTaskLists(text);
|
|
20
|
+
text = convertThematicBreaks(text);
|
|
21
|
+
text = stripHtml(text);
|
|
22
|
+
text = removeFootnotes(text);
|
|
23
|
+
text = removeUnfriendlyExtensions(text);
|
|
24
|
+
text = flattenDeepNesting(text);
|
|
25
|
+
text = normalizeTables(text);
|
|
26
|
+
text = restoreInlineCodeSpans(text, inlineCodeStore);
|
|
27
|
+
text = cleanupWhitespace(text);
|
|
28
|
+
if (maxLength != null && text.length > maxLength) {
|
|
29
|
+
text = truncateSafely(text, maxLength);
|
|
30
|
+
}
|
|
31
|
+
return text;
|
|
32
|
+
}
|
|
33
|
+
const INLINE_CODE_PREFIX = "\uFFF0INLINECODE";
|
|
34
|
+
const INLINE_CODE_SUFFIX = "\uFFF1";
|
|
35
|
+
function extractInlineCodeSpans(text) {
|
|
36
|
+
const store = [];
|
|
37
|
+
const replaced = text.replace(/`([^`\n]+?)`/g, (_, content) => {
|
|
38
|
+
const idx = store.length;
|
|
39
|
+
store.push(content);
|
|
40
|
+
return `${INLINE_CODE_PREFIX}${idx}${INLINE_CODE_SUFFIX}`;
|
|
41
|
+
});
|
|
42
|
+
return { text: replaced, store };
|
|
43
|
+
}
|
|
44
|
+
function restoreInlineCodeSpans(text, store) {
|
|
45
|
+
const re = new RegExp(`${INLINE_CODE_PREFIX}(\\d+)${INLINE_CODE_SUFFIX}`, "g");
|
|
46
|
+
return text.replace(re, (_, idxStr) => {
|
|
47
|
+
const idx = Number(idxStr);
|
|
48
|
+
const content = idx >= 0 && idx < store.length ? store[idx] : "";
|
|
49
|
+
return `\`${content}\``;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function convertFencedCodeBlocks(text) {
|
|
53
|
+
return text.replace(/```([a-zA-Z0-9_+\-]*)\n([\s\S]*?)```/g, (_, lang, code) => {
|
|
54
|
+
const safeLang = (lang || "").trim();
|
|
55
|
+
const safeCode = String(code || "").replace(/^\n+|\n+$/g, "");
|
|
56
|
+
if (!safeCode.trim())
|
|
57
|
+
return "";
|
|
58
|
+
const title = safeLang ? `代码(${safeLang}):` : "代码:";
|
|
59
|
+
return `\n${title}\n${safeCode}\n`;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function convertIndentedCodeBlocks(text) {
|
|
63
|
+
const lines = text.split("\n");
|
|
64
|
+
const out = [];
|
|
65
|
+
let buffer = [];
|
|
66
|
+
const flushBuffer = () => {
|
|
67
|
+
if (!buffer.length)
|
|
68
|
+
return;
|
|
69
|
+
const block = buffer
|
|
70
|
+
.map(line => (line.startsWith(" ") ? line.slice(4) : line))
|
|
71
|
+
.join("\n")
|
|
72
|
+
.replace(/\s+$/g, "");
|
|
73
|
+
if (block) {
|
|
74
|
+
out.push("代码:");
|
|
75
|
+
out.push(...block.split("\n"));
|
|
76
|
+
}
|
|
77
|
+
buffer = [];
|
|
78
|
+
};
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
if (/^ \S/.test(line)) {
|
|
81
|
+
buffer.push(line);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
flushBuffer();
|
|
85
|
+
out.push(line);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
flushBuffer();
|
|
89
|
+
return out.join("\n");
|
|
90
|
+
}
|
|
91
|
+
function convertImages(text) {
|
|
92
|
+
text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_, alt, url) => {
|
|
93
|
+
const safeAlt = (alt || "").trim() || "图片";
|
|
94
|
+
const safeUrl = (url || "").trim();
|
|
95
|
+
return `[图片:${safeAlt}](${safeUrl})`;
|
|
96
|
+
});
|
|
97
|
+
text = text.replace(/!\[([^\]]*)\]\[[^\]]*\]/g, (_, alt) => {
|
|
98
|
+
const safeAlt = (alt || "").trim() || "图片";
|
|
99
|
+
return `图片:${safeAlt}`;
|
|
100
|
+
});
|
|
101
|
+
return text;
|
|
102
|
+
}
|
|
103
|
+
function convertTaskLists(text) {
|
|
104
|
+
text = text.replace(/^(\s*[-*+]\s+)\[x\]\s+/gim, "✅ ");
|
|
105
|
+
text = text.replace(/^(\s*[-*+]\s+)\[\s\]\s+/gm, "⬜ ");
|
|
106
|
+
return text;
|
|
107
|
+
}
|
|
108
|
+
function convertThematicBreaks(text) {
|
|
109
|
+
return text.replace(/^\s*([-*_])(\s*\1){2,}\s*$/gm, "────────");
|
|
110
|
+
}
|
|
111
|
+
function stripHtml(text) {
|
|
112
|
+
text = text.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
113
|
+
text = text.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "");
|
|
114
|
+
text = text.replace(/<br\s*\/?>/gi, "\n");
|
|
115
|
+
text = text.replace(/<\/p\s*>/gi, "\n");
|
|
116
|
+
text = text.replace(/<p\b[^>]*>/gi, "");
|
|
117
|
+
const simpleTags = [
|
|
118
|
+
"div", "span", "b", "strong", "i", "em", "u",
|
|
119
|
+
"font", "small", "big", "section", "article",
|
|
120
|
+
"header", "footer", "main",
|
|
121
|
+
];
|
|
122
|
+
for (const tag of simpleTags) {
|
|
123
|
+
const re = new RegExp(`</?${tag}\\b[^>]*>`, "gi");
|
|
124
|
+
text = text.replace(re, "");
|
|
125
|
+
}
|
|
126
|
+
text = text.replace(/<[^>]+>/g, "");
|
|
127
|
+
text = decodeHtmlEntities(text);
|
|
128
|
+
return text;
|
|
129
|
+
}
|
|
130
|
+
function decodeHtmlEntities(text) {
|
|
131
|
+
const map = {
|
|
132
|
+
"&": "&",
|
|
133
|
+
"<": "<",
|
|
134
|
+
">": ">",
|
|
135
|
+
""": "\"",
|
|
136
|
+
"'": "'",
|
|
137
|
+
" ": " ",
|
|
138
|
+
};
|
|
139
|
+
return text.replace(/&|<|>|"|'| /g, m => map[m] ?? m);
|
|
140
|
+
}
|
|
141
|
+
function removeFootnotes(text) {
|
|
142
|
+
text = text.replace(/^\[\^[^\]]+\]:\s+.*(?:\n(?: {2,}|\t).*)*/gm, "");
|
|
143
|
+
text = text.replace(/\[\^[^\]]+\]/g, "[注]");
|
|
144
|
+
return text;
|
|
145
|
+
}
|
|
146
|
+
function removeUnfriendlyExtensions(text) {
|
|
147
|
+
text = text.replace(/~~(.*?)~~/g, "$1");
|
|
148
|
+
text = text.replace(/==(.*?)==/g, "$1");
|
|
149
|
+
text = text.replace(/(?<!~)~([^~\n]+)~(?!~)/g, "$1");
|
|
150
|
+
text = text.replace(/\^([^^\n]+)\^/g, "$1");
|
|
151
|
+
text = text.replace(/```(?:mermaid|math|latex|tex|graphviz|plantuml)\n([\s\S]*?)```/gi, "\n内容略(不支持的扩展块)\n");
|
|
152
|
+
return text;
|
|
153
|
+
}
|
|
154
|
+
function flattenDeepNesting(text) {
|
|
155
|
+
const lines = text.split("\n");
|
|
156
|
+
const out = [];
|
|
157
|
+
for (let line of lines) {
|
|
158
|
+
if (/^\s{4,}[-*+]\s+/.test(line)) {
|
|
159
|
+
line = line.replace(/^\s+/, " ");
|
|
160
|
+
}
|
|
161
|
+
if (/^\s*(>\s*){2,}/.test(line)) {
|
|
162
|
+
const content = line.replace(/^\s*(>\s*)+/, "");
|
|
163
|
+
line = `> ${content}`;
|
|
164
|
+
}
|
|
165
|
+
out.push(line);
|
|
166
|
+
}
|
|
167
|
+
return out.join("\n");
|
|
168
|
+
}
|
|
169
|
+
function normalizeTables(text) {
|
|
170
|
+
// Pass 1: stitch broken table rows back together.
|
|
171
|
+
// Models may split a single row across multiple lines in several ways:
|
|
172
|
+
// a) first part ends without |, continuation does NOT start with |
|
|
173
|
+
// b) first part ends without |, blank line(s), continuation starts with |
|
|
174
|
+
// c) first part ends without |, blank line(s), lone | on its own line
|
|
175
|
+
// We absorb any blank lines that follow an incomplete row and keep merging
|
|
176
|
+
// until the accumulated row ends with |.
|
|
177
|
+
const rawLines = text.split("\n");
|
|
178
|
+
const stitched = [];
|
|
179
|
+
for (let idx = 0; idx < rawLines.length; idx++) {
|
|
180
|
+
const line = rawLines[idx];
|
|
181
|
+
const trimmed = line.trim();
|
|
182
|
+
const prev = stitched[stitched.length - 1];
|
|
183
|
+
const prevTrim = prev !== undefined ? prev.trim() : "";
|
|
184
|
+
const prevIsIncomplete = prevTrim.startsWith("|") && !prevTrim.endsWith("|");
|
|
185
|
+
if (prevIsIncomplete) {
|
|
186
|
+
if (trimmed === "") {
|
|
187
|
+
// Blank line inside a broken row — absorb it and keep waiting for the rest
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (trimmed.includes("|")) {
|
|
191
|
+
// Continuation (starting with | or not) — stitch into the pending row
|
|
192
|
+
stitched[stitched.length - 1] =
|
|
193
|
+
prev + (trimmed.startsWith("|") ? trimmed : line);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
stitched.push(line);
|
|
198
|
+
}
|
|
199
|
+
// Pass 2: convert each table block to plain text lines.
|
|
200
|
+
const out = [];
|
|
201
|
+
let i = 0;
|
|
202
|
+
while (i < stitched.length) {
|
|
203
|
+
if (looksLikeTableRow(stitched[i])) {
|
|
204
|
+
const tableBlock = [stitched[i]];
|
|
205
|
+
let j = i + 1;
|
|
206
|
+
while (j < stitched.length && looksLikeTableRow(stitched[j])) {
|
|
207
|
+
tableBlock.push(stitched[j]);
|
|
208
|
+
j += 1;
|
|
209
|
+
}
|
|
210
|
+
if (out.length > 0 && out[out.length - 1]?.trim() !== "") {
|
|
211
|
+
out.push("");
|
|
212
|
+
}
|
|
213
|
+
out.push(...tableToPlainText(tableBlock));
|
|
214
|
+
if (j < stitched.length && stitched[j]?.trim() !== "") {
|
|
215
|
+
out.push("");
|
|
216
|
+
}
|
|
217
|
+
i = j;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
out.push(stitched[i]);
|
|
221
|
+
i += 1;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return out.join("\n");
|
|
225
|
+
}
|
|
226
|
+
function looksLikeTableRow(line) {
|
|
227
|
+
const stripped = String(line).trim();
|
|
228
|
+
if (!stripped.startsWith("|"))
|
|
229
|
+
return false;
|
|
230
|
+
return (stripped.match(/\|/g) || []).length >= 2;
|
|
231
|
+
}
|
|
232
|
+
function isTableSeparatorRow(row) {
|
|
233
|
+
const inner = row.replace(/^\|/, "").replace(/\|$/, "");
|
|
234
|
+
return inner.split("|").every(c => /^[\s\-:]+$/.test(c) && c.includes("-"));
|
|
235
|
+
}
|
|
236
|
+
function extractTableCells(line) {
|
|
237
|
+
const raw = line.trim();
|
|
238
|
+
const parts = raw.split("|");
|
|
239
|
+
const inner = raw.startsWith("|") ? parts.slice(1) : parts;
|
|
240
|
+
const cells = (raw.endsWith("|") ? inner.slice(0, -1) : inner).map(p => p.trim());
|
|
241
|
+
return cells.filter(c => c.length > 0);
|
|
242
|
+
}
|
|
243
|
+
function tableToPlainText(lines) {
|
|
244
|
+
const result = [];
|
|
245
|
+
for (const line of lines) {
|
|
246
|
+
if (!line.trim())
|
|
247
|
+
continue;
|
|
248
|
+
if (isTableSeparatorRow(line.trim()))
|
|
249
|
+
continue;
|
|
250
|
+
const cells = extractTableCells(line);
|
|
251
|
+
if (cells.length === 0)
|
|
252
|
+
continue;
|
|
253
|
+
result.push(cells.join(" | "));
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
function cleanupWhitespace(text) {
|
|
258
|
+
const lines = text.split("\n").map(line => {
|
|
259
|
+
let s = line.replace(/[ \t]+$/g, "");
|
|
260
|
+
s = s.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
|
|
261
|
+
return s;
|
|
262
|
+
});
|
|
263
|
+
text = lines.join("\n");
|
|
264
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
265
|
+
return text.trim();
|
|
266
|
+
}
|
|
267
|
+
function truncateSafely(text, maxLength) {
|
|
268
|
+
if (text.length <= maxLength)
|
|
269
|
+
return text;
|
|
270
|
+
const suffix = "\n\n(内容过长,已截断)";
|
|
271
|
+
const allowed = maxLength - suffix.length;
|
|
272
|
+
if (allowed <= 0)
|
|
273
|
+
return text.slice(0, maxLength);
|
|
274
|
+
let truncated = text.slice(0, allowed);
|
|
275
|
+
const cut = truncated.lastIndexOf("\n");
|
|
276
|
+
if (cut > maxLength * 0.7) {
|
|
277
|
+
truncated = truncated.slice(0, cut);
|
|
278
|
+
}
|
|
279
|
+
return truncated.replace(/\s+$/g, "") + suffix;
|
|
280
|
+
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "wecom",
|
|
3
3
|
"channels": ["wecom"],
|
|
4
|
+
"channelConfigs": {
|
|
5
|
+
"wecom": {
|
|
6
|
+
"label": "WeCom (企业微信)",
|
|
7
|
+
"description": "企业微信官方推荐三方插件,默认 Bot WebSocket 配置简单,支持加密媒体解密、Agent 主动发消息与多账号接入。",
|
|
8
|
+
"schema": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"additionalProperties": true,
|
|
11
|
+
"properties": {}
|
|
12
|
+
},
|
|
13
|
+
"commands": {
|
|
14
|
+
"nativeCommandsAutoEnabled": false,
|
|
15
|
+
"nativeSkillsAutoEnabled": false
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
4
19
|
"configSchema": {
|
|
5
20
|
"type": "object",
|
|
6
21
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yanhaidao/wecom",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.110",
|
|
4
4
|
"description": "OpenClaw 企业微信(WeCom)插件,默认 Bot WebSocket,支持加密媒体解密、Agent 主动发消息与多账号接入",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"index.ts",
|
|
9
|
+
"openclaw.plugin.json",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -p tsconfig.json",
|
|
15
|
+
"verify-dist": "node -e \"const fs=require('fs');const f='./dist/index.js';if(!fs.existsSync(f)){console.error('Missing compiled runtime output:',f);process.exit(1)}\"",
|
|
16
|
+
"prepack": "npm run build && npm run verify-dist"
|
|
17
|
+
},
|
|
5
18
|
"license": "ISC",
|
|
6
19
|
"author": "YanHaidao (VX: YanHaidao)",
|
|
7
20
|
"repository": {
|
|
@@ -19,6 +32,7 @@
|
|
|
19
32
|
},
|
|
20
33
|
"devDependencies": {
|
|
21
34
|
"@types/node": "^25.2.0",
|
|
35
|
+
"openclaw": "^2026.3.23-2",
|
|
22
36
|
"typescript": "^5.9.3",
|
|
23
37
|
"vitest": "^2.1.8"
|
|
24
38
|
},
|
|
@@ -29,6 +43,9 @@
|
|
|
29
43
|
"extensions": [
|
|
30
44
|
"./index.ts"
|
|
31
45
|
],
|
|
46
|
+
"runtimeExtensions": [
|
|
47
|
+
"./dist/index.js"
|
|
48
|
+
],
|
|
32
49
|
"channel": {
|
|
33
50
|
"id": "wecom",
|
|
34
51
|
"label": "WeCom (企业微信)",
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
name: Release & Publish
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
7
|
-
- 'wecom-v*'
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
publish:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
# 🌟 必须与 npm 设置的 Environment 一致
|
|
13
|
-
environment: release
|
|
14
|
-
permissions:
|
|
15
|
-
contents: write # 发布 Release
|
|
16
|
-
id-token: write # 获取 OIDC 身份令牌
|
|
17
|
-
steps:
|
|
18
|
-
- name: Checkout Code
|
|
19
|
-
uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- name: Setup Node.js
|
|
22
|
-
uses: actions/setup-node@v4
|
|
23
|
-
with:
|
|
24
|
-
# npm Trusted Publishing (OIDC) requires npm >=11.5.1.
|
|
25
|
-
# Use Node 24 to get modern npm in hosted runners.
|
|
26
|
-
node-version: '24'
|
|
27
|
-
registry-url: 'https://registry.npmjs.org'
|
|
28
|
-
|
|
29
|
-
- name: Show runtime versions
|
|
30
|
-
run: |
|
|
31
|
-
node -v
|
|
32
|
-
npm -v
|
|
33
|
-
|
|
34
|
-
- name: Ensure npm trusted publishing support
|
|
35
|
-
run: |
|
|
36
|
-
npm i -g npm@^11.5.1
|
|
37
|
-
npm -v
|
|
38
|
-
npm config delete always-auth || true
|
|
39
|
-
|
|
40
|
-
- name: Resolve release metadata
|
|
41
|
-
id: meta
|
|
42
|
-
run: |
|
|
43
|
-
set -euo pipefail
|
|
44
|
-
TAG="${GITHUB_REF_NAME}"
|
|
45
|
-
if [[ "${TAG}" == wecom-v* ]]; then
|
|
46
|
-
VERSION="${TAG#wecom-v}"
|
|
47
|
-
elif [[ "${TAG}" == v* ]]; then
|
|
48
|
-
VERSION="${TAG#v}"
|
|
49
|
-
else
|
|
50
|
-
echo "::error::Unsupported tag format: ${TAG}. Use v<version> or wecom-v<version>."
|
|
51
|
-
exit 1
|
|
52
|
-
fi
|
|
53
|
-
PKG_NAME="$(node -p "require('./package.json').name")"
|
|
54
|
-
PKG_VERSION="$(node -p "require('./package.json').version")"
|
|
55
|
-
|
|
56
|
-
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
57
|
-
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
58
|
-
echo "pkg_name=${PKG_NAME}" >> "$GITHUB_OUTPUT"
|
|
59
|
-
echo "pkg_version=${PKG_VERSION}" >> "$GITHUB_OUTPUT"
|
|
60
|
-
|
|
61
|
-
echo "tag=${TAG}"
|
|
62
|
-
echo "version_from_tag=${VERSION}"
|
|
63
|
-
echo "package=${PKG_NAME}@${PKG_VERSION}"
|
|
64
|
-
|
|
65
|
-
if [ "${VERSION}" != "${PKG_VERSION}" ]; then
|
|
66
|
-
echo "::error::Tag version (${VERSION}) does not match package.json version (${PKG_VERSION})."
|
|
67
|
-
exit 1
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
- name: Check npm version already published
|
|
71
|
-
id: npm_check
|
|
72
|
-
run: |
|
|
73
|
-
set -euo pipefail
|
|
74
|
-
PKG="${{ steps.meta.outputs.pkg_name }}"
|
|
75
|
-
VER="${{ steps.meta.outputs.pkg_version }}"
|
|
76
|
-
if npm view "${PKG}@${VER}" version >/dev/null 2>&1; then
|
|
77
|
-
echo "exists=true" >> "$GITHUB_OUTPUT"
|
|
78
|
-
echo "npm version already published: ${PKG}@${VER}"
|
|
79
|
-
else
|
|
80
|
-
echo "exists=false" >> "$GITHUB_OUTPUT"
|
|
81
|
-
echo "npm version not published yet: ${PKG}@${VER}"
|
|
82
|
-
fi
|
|
83
|
-
|
|
84
|
-
- name: Install Dependencies
|
|
85
|
-
run: npm install --legacy-peer-deps || npm install
|
|
86
|
-
|
|
87
|
-
- name: Build Plugin
|
|
88
|
-
run: npm run build --if-present
|
|
89
|
-
|
|
90
|
-
# 🚀 自动发布到 npm (使用 OIDC 自动授权,无需 Token)
|
|
91
|
-
- name: Publish to npm
|
|
92
|
-
if: steps.npm_check.outputs.exists != 'true'
|
|
93
|
-
run: npm publish --access public
|
|
94
|
-
|
|
95
|
-
- name: Prepare release notes body
|
|
96
|
-
id: notes
|
|
97
|
-
run: |
|
|
98
|
-
set -euo pipefail
|
|
99
|
-
VERSION="${{ steps.meta.outputs.version }}"
|
|
100
|
-
CHANGELOG_DIR="changelog"
|
|
101
|
-
CHANGELOG_FILE=""
|
|
102
|
-
CANDIDATES=("v${VERSION}.md")
|
|
103
|
-
|
|
104
|
-
IFS='.' read -r major minor patch <<< "${VERSION}"
|
|
105
|
-
if [[ -n "${major:-}" && -n "${minor:-}" && -n "${patch:-}" && "${patch}" =~ ^[0-9]+$ && ${#patch} -gt 2 ]]; then
|
|
106
|
-
trimmed_patch="${patch%?}"
|
|
107
|
-
CANDIDATES+=("v${major}.${minor}.${trimmed_patch}.md")
|
|
108
|
-
fi
|
|
109
|
-
|
|
110
|
-
echo "Release notes candidates:"
|
|
111
|
-
for candidate in "${CANDIDATES[@]}"; do
|
|
112
|
-
path="${CHANGELOG_DIR}/${candidate}"
|
|
113
|
-
echo " - ${path}"
|
|
114
|
-
if [[ -z "${CHANGELOG_FILE}" && -f "${path}" ]]; then
|
|
115
|
-
CHANGELOG_FILE="${path}"
|
|
116
|
-
fi
|
|
117
|
-
done
|
|
118
|
-
|
|
119
|
-
if [[ -n "${CHANGELOG_FILE}" ]]; then
|
|
120
|
-
echo "Using changelog file: ${CHANGELOG_FILE}"
|
|
121
|
-
cp "${CHANGELOG_FILE}" /tmp/release-body.md
|
|
122
|
-
else
|
|
123
|
-
echo "No matching changelog file found; using fallback notes."
|
|
124
|
-
{
|
|
125
|
-
echo "# @yanhaidao/wecom v${VERSION}"
|
|
126
|
-
echo
|
|
127
|
-
if [ "${{ steps.npm_check.outputs.exists }}" = "true" ]; then
|
|
128
|
-
echo "- npm publish skipped: version already exists."
|
|
129
|
-
else
|
|
130
|
-
echo "- npm publish completed."
|
|
131
|
-
fi
|
|
132
|
-
} > /tmp/release-body.md
|
|
133
|
-
fi
|
|
134
|
-
|
|
135
|
-
# 自动同步发布 GitHub Release
|
|
136
|
-
- name: Create GitHub Release
|
|
137
|
-
uses: softprops/action-gh-release@v2
|
|
138
|
-
with:
|
|
139
|
-
body_path: /tmp/release-body.md
|
|
140
|
-
draft: false
|
|
141
|
-
prerelease: false
|
|
142
|
-
env:
|
|
143
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/GOVERNANCE.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Governance
|
|
2
|
-
|
|
3
|
-
This document clarifies project ownership and collaboration expectations so contributors can work together with fewer ambiguities.
|
|
4
|
-
|
|
5
|
-
## 1. Upstream ownership
|
|
6
|
-
- This repository is the **Upstream / Source of Truth** for the OpenClaw WeCom plugin.
|
|
7
|
-
- **Author & Lead Maintainer:** YanHaidao (GitHub: YanHaidao).
|
|
8
|
-
|
|
9
|
-
## 2. Co-maintenance model
|
|
10
|
-
- Tencent Cloud contributors are welcome as **co-maintainers** for code, docs, testing, and cloud deployment adaptation.
|
|
11
|
-
- Tencent Cloud may host an official mirror repository for sync and downstream integration needs.
|
|
12
|
-
|
|
13
|
-
## 3. Decision-making
|
|
14
|
-
- We prefer discussion and consensus on non-trivial changes.
|
|
15
|
-
- If consensus is not reached in time, the Lead Maintainer makes the final upstream decision for roadmap, architecture, and release direction.
|
|
16
|
-
|
|
17
|
-
## 4. Contribution workflow
|
|
18
|
-
- Non-trivial changes should be proposed via Pull Request.
|
|
19
|
-
- Keep change scope clear, include test notes when relevant, and document behavior changes.
|
|
20
|
-
|
|
21
|
-
## 5. Mirrors and downstream adaptations
|
|
22
|
-
- Mirrors may carry downstream patches (for example deployment integration or cloud templates).
|
|
23
|
-
- Mirrors/downstream repositories should keep attribution in README or NOTICE:
|
|
24
|
-
- Upstream source: this repository
|
|
25
|
-
- Author: YanHaidao
|
|
26
|
-
- Co-maintained with Tencent Cloud contributors
|