@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
package/src/types.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Backward-compatible type bridge.
|
|
3
|
-
* Canonical definitions live in `src/types/*`.
|
|
4
|
-
*/
|
|
5
|
-
export type {
|
|
6
|
-
WecomDmConfig,
|
|
7
|
-
WecomAccountConfig,
|
|
8
|
-
WecomConfig,
|
|
9
|
-
ResolvedWecomAccount,
|
|
10
|
-
WecomInboundQuote,
|
|
11
|
-
WecomTemplateCard,
|
|
12
|
-
WecomOutboundMessage,
|
|
13
|
-
} from "./types/index.js";
|
|
14
|
-
|
|
15
|
-
import type {
|
|
16
|
-
WecomBotInboundBase,
|
|
17
|
-
WecomBotInboundText,
|
|
18
|
-
WecomBotInboundVoice,
|
|
19
|
-
WecomBotInboundStreamRefresh,
|
|
20
|
-
WecomBotInboundEvent,
|
|
21
|
-
WecomBotInboundMessage,
|
|
22
|
-
} from "./types/index.js";
|
|
23
|
-
|
|
24
|
-
export type WecomInboundBase = WecomBotInboundBase;
|
|
25
|
-
export type WecomInboundText = WecomBotInboundText;
|
|
26
|
-
export type WecomInboundVoice = WecomBotInboundVoice;
|
|
27
|
-
export type WecomInboundStreamRefresh = WecomBotInboundStreamRefresh;
|
|
28
|
-
export type WecomInboundEvent = WecomBotInboundEvent;
|
|
29
|
-
export type WecomInboundMessage = WecomBotInboundMessage;
|
|
30
|
-
|
|
31
|
-
export type WecomInboundTemplateCardEvent = WecomBotInboundEvent;
|
|
32
|
-
export type WecomTemplateCardEventPayload = {
|
|
33
|
-
card_type: string;
|
|
34
|
-
event_key: string;
|
|
35
|
-
task_id: string;
|
|
36
|
-
response_code?: string;
|
|
37
|
-
selected_items?: {
|
|
38
|
-
question_key?: string;
|
|
39
|
-
option_ids?: string[];
|
|
40
|
-
};
|
|
41
|
-
};
|
package/src/upstream/index.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 上下游企业支持模块
|
|
3
|
-
*
|
|
4
|
-
* 根据企业微信文档:https://developer.work.weixin.qq.com/document/path/97213
|
|
5
|
-
*
|
|
6
|
-
* 关键逻辑:
|
|
7
|
-
* 1. 上下游企业消息中的 ToUserName 是下游企业的 CorpID
|
|
8
|
-
* 2. 需要使用下游企业的 access_token 来发送消息
|
|
9
|
-
* 3. 获取下游企业 access_token 的接口:
|
|
10
|
-
* POST https://qyapi.weixin.qq.com/cgi-bin/corpgroup/corp/gettoken?access_token=ACCESS_TOKEN
|
|
11
|
-
* {
|
|
12
|
-
* "corpid": "下游企业corpid",
|
|
13
|
-
* "business_type": 1, // 1 表示上下游企业
|
|
14
|
-
* "agentid": 下游企业应用ID
|
|
15
|
-
* }
|
|
16
|
-
* 4. 需要使用上游企业的 access_token 作为调用凭证
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import type { ResolvedAgentAccount } from "../types/index.js";
|
|
20
|
-
|
|
21
|
-
export type UpstreamCorpConfig = {
|
|
22
|
-
corpId: string;
|
|
23
|
-
agentId: number;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 从消息中检测是否是上下游用户
|
|
28
|
-
* 通过比较消息中的 ToUserName(CorpID)与配置的 CorpID
|
|
29
|
-
*/
|
|
30
|
-
export function detectUpstreamUser(params: {
|
|
31
|
-
messageToUserName: string;
|
|
32
|
-
primaryCorpId: string;
|
|
33
|
-
}): boolean {
|
|
34
|
-
const { messageToUserName, primaryCorpId } = params;
|
|
35
|
-
if (!messageToUserName?.trim() || !primaryCorpId?.trim()) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
const normalizedMessageCorpId = messageToUserName.trim().toLowerCase();
|
|
39
|
-
const normalizedPrimaryCorpId = primaryCorpId.trim().toLowerCase();
|
|
40
|
-
|
|
41
|
-
// 如果消息中的 CorpID 与主 CorpID 不同,则是上下游用户
|
|
42
|
-
return normalizedMessageCorpId !== normalizedPrimaryCorpId;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* 为上下游用户创建临时的 Agent 配置
|
|
47
|
-
* 使用下游企业的 CorpID 和 AgentID,但保持主企业的 corpSecret
|
|
48
|
-
*
|
|
49
|
-
* 注意:这个配置用于发送消息,但获取 access_token 时需要使用专门的
|
|
50
|
-
* corpgroup/corp/gettoken 接口
|
|
51
|
-
*/
|
|
52
|
-
export function createUpstreamAgentConfig(params: {
|
|
53
|
-
baseAgent: ResolvedAgentAccount;
|
|
54
|
-
upstreamCorpId: string;
|
|
55
|
-
upstreamAgentId: number;
|
|
56
|
-
}): ResolvedAgentAccount {
|
|
57
|
-
const { baseAgent, upstreamCorpId, upstreamAgentId } = params;
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
...baseAgent,
|
|
61
|
-
corpId: upstreamCorpId,
|
|
62
|
-
agentId: upstreamAgentId,
|
|
63
|
-
// corpSecret 保持主企业的,用于获取下游企业的 access_token
|
|
64
|
-
// token 和 encodingAESKey 保持主企业的,用于回调验证
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 从配置中解析上下游企业映射
|
|
70
|
-
* 支持在 agent 配置中添加 upstreamCorps 字段
|
|
71
|
-
*/
|
|
72
|
-
export function resolveUpstreamCorpConfig(params: {
|
|
73
|
-
upstreamCorpId: string;
|
|
74
|
-
upstreamCorps?: Record<string, UpstreamCorpConfig> | UpstreamCorpConfig[];
|
|
75
|
-
}): UpstreamCorpConfig | undefined {
|
|
76
|
-
const { upstreamCorpId, upstreamCorps } = params;
|
|
77
|
-
|
|
78
|
-
if (!upstreamCorps) {
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Normalize to array format (support both Record<string, ...> and array)
|
|
83
|
-
const entries: Array<[string, UpstreamCorpConfig]> = Array.isArray(upstreamCorps)
|
|
84
|
-
? upstreamCorps.map((item, i) => [String(i), item])
|
|
85
|
-
: Object.entries(upstreamCorps);
|
|
86
|
-
|
|
87
|
-
// Find matching upstream config
|
|
88
|
-
const normalizedTargetCorpId = upstreamCorpId.trim().toLowerCase();
|
|
89
|
-
|
|
90
|
-
for (const [key, config] of entries) {
|
|
91
|
-
const normalizedConfigCorpId = config.corpId.trim().toLowerCase();
|
|
92
|
-
|
|
93
|
-
if (normalizedConfigCorpId === normalizedTargetCorpId) {
|
|
94
|
-
return config;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return undefined;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* 构建上下游用户的回复目标
|
|
103
|
-
* 格式: wecom-agent-upstream:{accountId}:{corpId}:{userId}
|
|
104
|
-
*/
|
|
105
|
-
export function buildUpstreamAgentSessionTarget(
|
|
106
|
-
userId: string,
|
|
107
|
-
accountId: string,
|
|
108
|
-
upstreamCorpId: string,
|
|
109
|
-
): string {
|
|
110
|
-
return `wecom-agent-upstream:${accountId}:${upstreamCorpId}:${userId}`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* 解析上下游用户的回复目标
|
|
115
|
-
*/
|
|
116
|
-
export function parseUpstreamAgentSessionTarget(
|
|
117
|
-
target: string,
|
|
118
|
-
): { accountId: string; upstreamCorpId: string; userId: string } | undefined {
|
|
119
|
-
const prefix = "wecom-agent-upstream:";
|
|
120
|
-
if (target.startsWith(prefix)) {
|
|
121
|
-
const parts = target.slice(prefix.length).split(":");
|
|
122
|
-
if (parts.length !== 3) {
|
|
123
|
-
return undefined;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
accountId: parts[0]!,
|
|
128
|
-
upstreamCorpId: parts[1]!,
|
|
129
|
-
userId: parts[2]!,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// 兼容当前工作区里尚未持久化的新格式,避免旧会话目标失效。
|
|
134
|
-
const queryIndex = target.indexOf("?upstream_corp=");
|
|
135
|
-
if (queryIndex < 0 || !target.startsWith("wecom-agent:")) {
|
|
136
|
-
return undefined;
|
|
137
|
-
}
|
|
138
|
-
const pathPart = target.slice(0, queryIndex);
|
|
139
|
-
const upstreamCorpId = target.slice(queryIndex + "?upstream_corp=".length).trim();
|
|
140
|
-
const match = pathPart.match(/^wecom-agent:([^:]+):user:(.+)$/i);
|
|
141
|
-
if (!match || !upstreamCorpId) {
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
accountId: match[1]!.trim(),
|
|
147
|
-
upstreamCorpId,
|
|
148
|
-
userId: match[2]!.trim(),
|
|
149
|
-
};
|
|
150
|
-
}
|
package/src/upstream.test.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
|
|
3
|
-
import { resolveScopedWecomTarget } from "./target.js";
|
|
4
|
-
import {
|
|
5
|
-
buildUpstreamAgentSessionTarget,
|
|
6
|
-
parseUpstreamAgentSessionTarget,
|
|
7
|
-
} from "./upstream/index.js";
|
|
8
|
-
|
|
9
|
-
describe("upstream target helpers", () => {
|
|
10
|
-
it("builds and parses the canonical upstream agent target", () => {
|
|
11
|
-
const target = buildUpstreamAgentSessionTarget("zhangsan", "acct-a", "corp-up");
|
|
12
|
-
|
|
13
|
-
expect(target).toBe("wecom-agent-upstream:acct-a:corp-up:zhangsan");
|
|
14
|
-
expect(parseUpstreamAgentSessionTarget(target)).toEqual({
|
|
15
|
-
accountId: "acct-a",
|
|
16
|
-
upstreamCorpId: "corp-up",
|
|
17
|
-
userId: "zhangsan",
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("keeps compatibility with legacy upstream-prefixed targets", () => {
|
|
22
|
-
expect(
|
|
23
|
-
parseUpstreamAgentSessionTarget("wecom-agent-upstream:acct-a:corp-up:zhangsan"),
|
|
24
|
-
).toEqual({
|
|
25
|
-
accountId: "acct-a",
|
|
26
|
-
upstreamCorpId: "corp-up",
|
|
27
|
-
userId: "zhangsan",
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("keeps compatibility with query-style upstream targets", () => {
|
|
32
|
-
expect(
|
|
33
|
-
parseUpstreamAgentSessionTarget(
|
|
34
|
-
"wecom-agent:acct-a:user:zhangsan?upstream_corp=corp-up",
|
|
35
|
-
),
|
|
36
|
-
).toEqual({
|
|
37
|
-
accountId: "acct-a",
|
|
38
|
-
upstreamCorpId: "corp-up",
|
|
39
|
-
userId: "zhangsan",
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("resolves upstream-scoped targets to the real touser without leaking corp metadata", () => {
|
|
44
|
-
expect(
|
|
45
|
-
resolveScopedWecomTarget("wecom-agent-upstream:acct-a:corp-up:zhangsan", "default"),
|
|
46
|
-
).toEqual({
|
|
47
|
-
accountId: "acct-a",
|
|
48
|
-
target: { touser: "zhangsan" },
|
|
49
|
-
rawTarget: "zhangsan",
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
expect(
|
|
53
|
-
resolveScopedWecomTarget(
|
|
54
|
-
"wecom-agent:acct-a:user:zhangsan?upstream_corp=corp-up",
|
|
55
|
-
"default",
|
|
56
|
-
),
|
|
57
|
-
).toEqual({
|
|
58
|
-
accountId: "acct-a",
|
|
59
|
-
target: { touser: "zhangsan" },
|
|
60
|
-
rawTarget: "zhangsan",
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("keeps normal users and upstream users distinguishable", () => {
|
|
65
|
-
// 普通用户目标:不带 upstream 标识,应按普通 agent target 解析
|
|
66
|
-
expect(resolveScopedWecomTarget("wecom-agent:acct-a:user:zhangsan", "default")).toEqual({
|
|
67
|
-
accountId: "acct-a",
|
|
68
|
-
target: { touser: "zhangsan" },
|
|
69
|
-
rawTarget: "user:zhangsan",
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// 上下游用户目标:带 upstream_corp,应走 upstream 解析
|
|
73
|
-
expect(
|
|
74
|
-
resolveScopedWecomTarget(
|
|
75
|
-
"wecom-agent:acct-a:user:zhangsan?upstream_corp=corp-up",
|
|
76
|
-
"default",
|
|
77
|
-
),
|
|
78
|
-
).toEqual({
|
|
79
|
-
accountId: "acct-a",
|
|
80
|
-
target: { touser: "zhangsan" },
|
|
81
|
-
rawTarget: "zhangsan",
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 将较完整的 Markdown 降级转换为更适合企业微信 markdown_v2 的子集。
|
|
3
|
-
*
|
|
4
|
-
* 保守策略:
|
|
5
|
-
* - 保留:标题、粗体、斜体、引用、链接、行内代码、普通列表、表格
|
|
6
|
-
* - 降级:代码块、图片、任务列表、分隔线、HTML、脚注、复杂语法
|
|
7
|
-
* - 清理:多余空行、非法控制字符、过深嵌套
|
|
8
|
-
*/
|
|
9
|
-
export function toWeComMarkdownV2(markdown: unknown, maxLength = 4096): string {
|
|
10
|
-
if (!markdown) return "";
|
|
11
|
-
|
|
12
|
-
let text = String(markdown).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
13
|
-
|
|
14
|
-
const extracted = extractInlineCodeSpans(text);
|
|
15
|
-
text = extracted.text;
|
|
16
|
-
const inlineCodeStore = extracted.store;
|
|
17
|
-
|
|
18
|
-
text = convertFencedCodeBlocks(text);
|
|
19
|
-
text = convertIndentedCodeBlocks(text);
|
|
20
|
-
text = convertImages(text);
|
|
21
|
-
text = convertTaskLists(text);
|
|
22
|
-
text = convertThematicBreaks(text);
|
|
23
|
-
text = stripHtml(text);
|
|
24
|
-
text = removeFootnotes(text);
|
|
25
|
-
text = removeUnfriendlyExtensions(text);
|
|
26
|
-
text = flattenDeepNesting(text);
|
|
27
|
-
text = normalizeTables(text);
|
|
28
|
-
text = restoreInlineCodeSpans(text, inlineCodeStore);
|
|
29
|
-
text = cleanupWhitespace(text);
|
|
30
|
-
|
|
31
|
-
if (maxLength != null && text.length > maxLength) {
|
|
32
|
-
text = truncateSafely(text, maxLength);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return text;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const INLINE_CODE_PREFIX = "\uFFF0INLINECODE";
|
|
39
|
-
const INLINE_CODE_SUFFIX = "\uFFF1";
|
|
40
|
-
|
|
41
|
-
function extractInlineCodeSpans(text: string): { text: string; store: string[] } {
|
|
42
|
-
const store: string[] = [];
|
|
43
|
-
const replaced = text.replace(/`([^`\n]+?)`/g, (_, content: string) => {
|
|
44
|
-
const idx = store.length;
|
|
45
|
-
store.push(content);
|
|
46
|
-
return `${INLINE_CODE_PREFIX}${idx}${INLINE_CODE_SUFFIX}`;
|
|
47
|
-
});
|
|
48
|
-
return { text: replaced, store };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function restoreInlineCodeSpans(text: string, store: string[]): string {
|
|
52
|
-
const re = new RegExp(`${INLINE_CODE_PREFIX}(\\d+)${INLINE_CODE_SUFFIX}`, "g");
|
|
53
|
-
return text.replace(re, (_, idxStr: string) => {
|
|
54
|
-
const idx = Number(idxStr);
|
|
55
|
-
const content = idx >= 0 && idx < store.length ? store[idx] : "";
|
|
56
|
-
return `\`${content}\``;
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function convertFencedCodeBlocks(text: string): string {
|
|
61
|
-
return text.replace(/```([a-zA-Z0-9_+\-]*)\n([\s\S]*?)```/g, (_, lang: string, code: string) => {
|
|
62
|
-
const safeLang = (lang || "").trim();
|
|
63
|
-
const safeCode = String(code || "").replace(/^\n+|\n+$/g, "");
|
|
64
|
-
if (!safeCode.trim()) return "";
|
|
65
|
-
|
|
66
|
-
const title = safeLang ? `代码(${safeLang}):` : "代码:";
|
|
67
|
-
return `\n${title}\n${safeCode}\n`;
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function convertIndentedCodeBlocks(text: string): string {
|
|
72
|
-
const lines = text.split("\n");
|
|
73
|
-
const out: string[] = [];
|
|
74
|
-
let buffer: string[] = [];
|
|
75
|
-
|
|
76
|
-
const flushBuffer = () => {
|
|
77
|
-
if (!buffer.length) return;
|
|
78
|
-
const block = buffer
|
|
79
|
-
.map(line => (line.startsWith(" ") ? line.slice(4) : line))
|
|
80
|
-
.join("\n")
|
|
81
|
-
.replace(/\s+$/g, "");
|
|
82
|
-
|
|
83
|
-
if (block) {
|
|
84
|
-
out.push("代码:");
|
|
85
|
-
out.push(...block.split("\n"));
|
|
86
|
-
}
|
|
87
|
-
buffer = [];
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
for (const line of lines) {
|
|
91
|
-
if (/^ \S/.test(line)) {
|
|
92
|
-
buffer.push(line);
|
|
93
|
-
} else {
|
|
94
|
-
flushBuffer();
|
|
95
|
-
out.push(line);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
flushBuffer();
|
|
100
|
-
return out.join("\n");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function convertImages(text: string): string {
|
|
104
|
-
text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_, alt: string, url: string) => {
|
|
105
|
-
const safeAlt = (alt || "").trim() || "图片";
|
|
106
|
-
const safeUrl = (url || "").trim();
|
|
107
|
-
return `[图片:${safeAlt}](${safeUrl})`;
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
text = text.replace(/!\[([^\]]*)\]\[[^\]]*\]/g, (_, alt: string) => {
|
|
111
|
-
const safeAlt = (alt || "").trim() || "图片";
|
|
112
|
-
return `图片:${safeAlt}`;
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
return text;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function convertTaskLists(text: string): string {
|
|
119
|
-
text = text.replace(/^(\s*[-*+]\s+)\[x\]\s+/gim, "✅ ");
|
|
120
|
-
text = text.replace(/^(\s*[-*+]\s+)\[\s\]\s+/gm, "⬜ ");
|
|
121
|
-
return text;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function convertThematicBreaks(text: string): string {
|
|
125
|
-
return text.replace(/^\s*([-*_])(\s*\1){2,}\s*$/gm, "────────");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function stripHtml(text: string): string {
|
|
129
|
-
text = text.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
130
|
-
text = text.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "");
|
|
131
|
-
|
|
132
|
-
text = text.replace(/<br\s*\/?>/gi, "\n");
|
|
133
|
-
text = text.replace(/<\/p\s*>/gi, "\n");
|
|
134
|
-
text = text.replace(/<p\b[^>]*>/gi, "");
|
|
135
|
-
|
|
136
|
-
const simpleTags = [
|
|
137
|
-
"div", "span", "b", "strong", "i", "em", "u",
|
|
138
|
-
"font", "small", "big", "section", "article",
|
|
139
|
-
"header", "footer", "main",
|
|
140
|
-
];
|
|
141
|
-
|
|
142
|
-
for (const tag of simpleTags) {
|
|
143
|
-
const re = new RegExp(`</?${tag}\\b[^>]*>`, "gi");
|
|
144
|
-
text = text.replace(re, "");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
text = text.replace(/<[^>]+>/g, "");
|
|
148
|
-
text = decodeHtmlEntities(text);
|
|
149
|
-
|
|
150
|
-
return text;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function decodeHtmlEntities(text: string): string {
|
|
154
|
-
const map: Record<string, string> = {
|
|
155
|
-
"&": "&",
|
|
156
|
-
"<": "<",
|
|
157
|
-
">": ">",
|
|
158
|
-
""": "\"",
|
|
159
|
-
"'": "'",
|
|
160
|
-
" ": " ",
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
return text.replace(/&|<|>|"|'| /g, m => map[m] ?? m);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function removeFootnotes(text: string): string {
|
|
167
|
-
text = text.replace(/^\[\^[^\]]+\]:\s+.*(?:\n(?: {2,}|\t).*)*/gm, "");
|
|
168
|
-
text = text.replace(/\[\^[^\]]+\]/g, "[注]");
|
|
169
|
-
return text;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function removeUnfriendlyExtensions(text: string): string {
|
|
173
|
-
text = text.replace(/~~(.*?)~~/g, "$1");
|
|
174
|
-
text = text.replace(/==(.*?)==/g, "$1");
|
|
175
|
-
text = text.replace(/(?<!~)~([^~\n]+)~(?!~)/g, "$1");
|
|
176
|
-
text = text.replace(/\^([^^\n]+)\^/g, "$1");
|
|
177
|
-
|
|
178
|
-
text = text.replace(
|
|
179
|
-
/```(?:mermaid|math|latex|tex|graphviz|plantuml)\n([\s\S]*?)```/gi,
|
|
180
|
-
"\n内容略(不支持的扩展块)\n",
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
return text;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function flattenDeepNesting(text: string): string {
|
|
187
|
-
const lines = text.split("\n");
|
|
188
|
-
const out: string[] = [];
|
|
189
|
-
|
|
190
|
-
for (let line of lines) {
|
|
191
|
-
if (/^\s{4,}[-*+]\s+/.test(line)) {
|
|
192
|
-
line = line.replace(/^\s+/, " ");
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (/^\s*(>\s*){2,}/.test(line)) {
|
|
196
|
-
const content = line.replace(/^\s*(>\s*)+/, "");
|
|
197
|
-
line = `> ${content}`;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
out.push(line);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return out.join("\n");
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function normalizeTables(text: string): string {
|
|
207
|
-
// Pass 1: stitch broken table rows back together.
|
|
208
|
-
// Models may split a single row across multiple lines in several ways:
|
|
209
|
-
// a) first part ends without |, continuation does NOT start with |
|
|
210
|
-
// b) first part ends without |, blank line(s), continuation starts with |
|
|
211
|
-
// c) first part ends without |, blank line(s), lone | on its own line
|
|
212
|
-
// We absorb any blank lines that follow an incomplete row and keep merging
|
|
213
|
-
// until the accumulated row ends with |.
|
|
214
|
-
const rawLines = text.split("\n");
|
|
215
|
-
const stitched: string[] = [];
|
|
216
|
-
|
|
217
|
-
for (let idx = 0; idx < rawLines.length; idx++) {
|
|
218
|
-
const line = rawLines[idx]!;
|
|
219
|
-
const trimmed = line.trim();
|
|
220
|
-
const prev = stitched[stitched.length - 1];
|
|
221
|
-
const prevTrim = prev !== undefined ? prev.trim() : "";
|
|
222
|
-
const prevIsIncomplete = prevTrim.startsWith("|") && !prevTrim.endsWith("|");
|
|
223
|
-
|
|
224
|
-
if (prevIsIncomplete) {
|
|
225
|
-
if (trimmed === "") {
|
|
226
|
-
// Blank line inside a broken row — absorb it and keep waiting for the rest
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
if (trimmed.includes("|")) {
|
|
230
|
-
// Continuation (starting with | or not) — stitch into the pending row
|
|
231
|
-
stitched[stitched.length - 1] =
|
|
232
|
-
prev! + (trimmed.startsWith("|") ? trimmed : line);
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
stitched.push(line);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Pass 2: convert each table block to plain text lines.
|
|
241
|
-
const out: string[] = [];
|
|
242
|
-
let i = 0;
|
|
243
|
-
|
|
244
|
-
while (i < stitched.length) {
|
|
245
|
-
if (looksLikeTableRow(stitched[i]!)) {
|
|
246
|
-
const tableBlock: string[] = [stitched[i]!];
|
|
247
|
-
let j = i + 1;
|
|
248
|
-
|
|
249
|
-
while (j < stitched.length && looksLikeTableRow(stitched[j]!)) {
|
|
250
|
-
tableBlock.push(stitched[j]!);
|
|
251
|
-
j += 1;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (out.length > 0 && out[out.length - 1]?.trim() !== "") {
|
|
255
|
-
out.push("");
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
out.push(...tableToPlainText(tableBlock));
|
|
259
|
-
|
|
260
|
-
if (j < stitched.length && stitched[j]?.trim() !== "") {
|
|
261
|
-
out.push("");
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
i = j;
|
|
265
|
-
} else {
|
|
266
|
-
out.push(stitched[i]!);
|
|
267
|
-
i += 1;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return out.join("\n");
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function looksLikeTableRow(line: string): boolean {
|
|
275
|
-
const stripped = String(line).trim();
|
|
276
|
-
if (!stripped.startsWith("|")) return false;
|
|
277
|
-
return (stripped.match(/\|/g) || []).length >= 2;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function isTableSeparatorRow(row: string): boolean {
|
|
281
|
-
const inner = row.replace(/^\|/, "").replace(/\|$/, "");
|
|
282
|
-
return inner.split("|").every(c => /^[\s\-:]+$/.test(c) && c.includes("-"));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function extractTableCells(line: string): string[] {
|
|
286
|
-
const raw = line.trim();
|
|
287
|
-
const parts = raw.split("|");
|
|
288
|
-
const inner = raw.startsWith("|") ? parts.slice(1) : parts;
|
|
289
|
-
const cells = (raw.endsWith("|") ? inner.slice(0, -1) : inner).map(p => p.trim());
|
|
290
|
-
return cells.filter(c => c.length > 0);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function tableToPlainText(lines: string[]): string[] {
|
|
294
|
-
const result: string[] = [];
|
|
295
|
-
for (const line of lines) {
|
|
296
|
-
if (!line.trim()) continue;
|
|
297
|
-
if (isTableSeparatorRow(line.trim())) continue;
|
|
298
|
-
const cells = extractTableCells(line);
|
|
299
|
-
if (cells.length === 0) continue;
|
|
300
|
-
result.push(cells.join(" | "));
|
|
301
|
-
}
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
function cleanupWhitespace(text: string): string {
|
|
306
|
-
const lines = text.split("\n").map(line => {
|
|
307
|
-
let s = line.replace(/[ \t]+$/g, "");
|
|
308
|
-
s = s.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
|
|
309
|
-
return s;
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
text = lines.join("\n");
|
|
313
|
-
text = text.replace(/\n{3,}/g, "\n\n");
|
|
314
|
-
return text.trim();
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function truncateSafely(text: string, maxLength: number): string {
|
|
318
|
-
if (text.length <= maxLength) return text;
|
|
319
|
-
|
|
320
|
-
const suffix = "\n\n(内容过长,已截断)";
|
|
321
|
-
const allowed = maxLength - suffix.length;
|
|
322
|
-
if (allowed <= 0) return text.slice(0, maxLength);
|
|
323
|
-
|
|
324
|
-
let truncated = text.slice(0, allowed);
|
|
325
|
-
const cut = truncated.lastIndexOf("\n");
|
|
326
|
-
if (cut > maxLength * 0.7) {
|
|
327
|
-
truncated = truncated.slice(0, cut);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
return truncated.replace(/\s+$/g, "") + suffix;
|
|
331
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"outDir": "dist",
|
|
7
|
-
"rootDir": ".",
|
|
8
|
-
"declaration": false,
|
|
9
|
-
"sourceMap": false,
|
|
10
|
-
"strict": true,
|
|
11
|
-
"skipLibCheck": true
|
|
12
|
-
},
|
|
13
|
-
"include": [
|
|
14
|
-
"index.ts",
|
|
15
|
-
"src/**/*.ts"
|
|
16
|
-
],
|
|
17
|
-
"exclude": [
|
|
18
|
-
"dist",
|
|
19
|
-
"node_modules",
|
|
20
|
-
"**/*.test.ts"
|
|
21
|
-
]
|
|
22
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
|
|
5
|
-
import { defineConfig } from "vitest/config";
|
|
6
|
-
|
|
7
|
-
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const sharedConfigPath = path.resolve(currentDir, "../../vitest.config.ts");
|
|
9
|
-
const sharedConfigModule = existsSync(sharedConfigPath)
|
|
10
|
-
? await import(sharedConfigPath)
|
|
11
|
-
: undefined;
|
|
12
|
-
const baseConfig = (sharedConfigModule?.default ?? {}) as { test?: { exclude?: string[] } };
|
|
13
|
-
const baseTest = baseConfig.test ?? {};
|
|
14
|
-
const exclude = baseTest.exclude ?? [];
|
|
15
|
-
const include = sharedConfigModule
|
|
16
|
-
? ["extensions/wecom/src/**/*.test.ts"]
|
|
17
|
-
: ["src/**/*.test.ts", "index.test.ts"];
|
|
18
|
-
|
|
19
|
-
export default defineConfig({
|
|
20
|
-
...baseConfig,
|
|
21
|
-
test: {
|
|
22
|
-
...baseTest,
|
|
23
|
-
include,
|
|
24
|
-
exclude,
|
|
25
|
-
},
|
|
26
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|