ylib-wecom-openclaw-plugin 2026.4.29
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 +596 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +99 -0
- package/dist/src/accounts.d.ts +57 -0
- package/dist/src/accounts.js +247 -0
- package/dist/src/agent/api-client.d.ts +95 -0
- package/dist/src/agent/api-client.js +425 -0
- package/dist/src/agent/handler.d.ts +64 -0
- package/dist/src/agent/handler.js +731 -0
- package/dist/src/agent/index.d.ts +5 -0
- package/dist/src/agent/index.js +21 -0
- package/dist/src/agent/webhook.d.ts +25 -0
- package/dist/src/agent/webhook.js +294 -0
- package/dist/src/agent/xml.d.ts +21 -0
- package/dist/src/agent/xml.js +43 -0
- package/dist/src/channel.d.ts +5 -0
- package/dist/src/channel.js +815 -0
- package/dist/src/chat-queue.d.ts +31 -0
- package/dist/src/chat-queue.js +53 -0
- package/dist/src/config-schema.d.ts +587 -0
- package/dist/src/config-schema.js +146 -0
- package/dist/src/const.d.ts +128 -0
- package/dist/src/const.js +168 -0
- package/dist/src/dm-policy.d.ts +29 -0
- package/dist/src/dm-policy.js +146 -0
- package/dist/src/dynamic-agent.d.ts +37 -0
- package/dist/src/dynamic-agent.js +67 -0
- package/dist/src/dynamic-routing.d.ts +65 -0
- package/dist/src/dynamic-routing.js +62 -0
- package/dist/src/endpoint-dispatch.d.ts +54 -0
- package/dist/src/endpoint-dispatch.js +967 -0
- package/dist/src/endpoint-event-adapter.d.ts +15 -0
- package/dist/src/endpoint-event-adapter.js +427 -0
- package/dist/src/group-policy.d.ts +30 -0
- package/dist/src/group-policy.js +126 -0
- package/dist/src/http.d.ts +27 -0
- package/dist/src/http.js +168 -0
- package/dist/src/im-runtime-telemetry.d.ts +25 -0
- package/dist/src/im-runtime-telemetry.js +68 -0
- package/dist/src/interface.d.ts +192 -0
- package/dist/src/interface.js +5 -0
- package/dist/src/markdown-chunk.d.ts +1 -0
- package/dist/src/markdown-chunk.js +396 -0
- package/dist/src/mcp/index.d.ts +6 -0
- package/dist/src/mcp/index.js +28 -0
- package/dist/src/mcp/interceptors/biz-error.d.ts +11 -0
- package/dist/src/mcp/interceptors/biz-error.js +73 -0
- package/dist/src/mcp/interceptors/doc-auth-error.d.ts +10 -0
- package/dist/src/mcp/interceptors/doc-auth-error.js +235 -0
- package/dist/src/mcp/interceptors/index.d.ts +35 -0
- package/dist/src/mcp/interceptors/index.js +143 -0
- package/dist/src/mcp/interceptors/msg-media.d.ts +11 -0
- package/dist/src/mcp/interceptors/msg-media.js +201 -0
- package/dist/src/mcp/interceptors/smartpage-create.d.ts +30 -0
- package/dist/src/mcp/interceptors/smartpage-create.js +252 -0
- package/dist/src/mcp/interceptors/smartpage-export.d.ts +17 -0
- package/dist/src/mcp/interceptors/smartpage-export.js +135 -0
- package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +22 -0
- package/dist/src/mcp/interceptors/smartsheet-upload.js +388 -0
- package/dist/src/mcp/interceptors/types.d.ts +64 -0
- package/dist/src/mcp/interceptors/types.js +8 -0
- package/dist/src/mcp/schema.d.ts +11 -0
- package/dist/src/mcp/schema.js +115 -0
- package/dist/src/mcp/tool.d.ts +63 -0
- package/dist/src/mcp/tool.js +318 -0
- package/dist/src/mcp/transport.d.ts +94 -0
- package/dist/src/mcp/transport.js +702 -0
- package/dist/src/media-handler.d.ts +55 -0
- package/dist/src/media-handler.js +306 -0
- package/dist/src/media-uploader.d.ts +142 -0
- package/dist/src/media-uploader.js +446 -0
- package/dist/src/message-parser.d.ts +104 -0
- package/dist/src/message-parser.js +232 -0
- package/dist/src/message-sender.d.ts +54 -0
- package/dist/src/message-sender.js +210 -0
- package/dist/src/monitor.d.ts +69 -0
- package/dist/src/monitor.js +1846 -0
- package/dist/src/onboarding.d.ts +8 -0
- package/dist/src/onboarding.js +248 -0
- package/dist/src/openclaw-compat.d.ts +148 -0
- package/dist/src/openclaw-compat.js +839 -0
- package/dist/src/proactive-markdown-send.d.ts +14 -0
- package/dist/src/proactive-markdown-send.js +205 -0
- package/dist/src/reqid-store.d.ts +23 -0
- package/dist/src/reqid-store.js +136 -0
- package/dist/src/runtime.d.ts +2 -0
- package/dist/src/runtime.js +7 -0
- package/dist/src/shared/command-auth.d.ts +23 -0
- package/dist/src/shared/command-auth.js +112 -0
- package/dist/src/shared/xml-parser.d.ts +46 -0
- package/dist/src/shared/xml-parser.js +228 -0
- package/dist/src/state-dir-resolve.d.ts +2 -0
- package/dist/src/state-dir-resolve.js +33 -0
- package/dist/src/state-manager.d.ts +115 -0
- package/dist/src/state-manager.js +413 -0
- package/dist/src/target.d.ts +35 -0
- package/dist/src/target.js +71 -0
- package/dist/src/template-card-manager.d.ts +55 -0
- package/dist/src/template-card-manager.js +316 -0
- package/dist/src/template-card-parser.d.ts +37 -0
- package/dist/src/template-card-parser.js +672 -0
- package/dist/src/timeout.d.ts +20 -0
- package/dist/src/timeout.js +57 -0
- package/dist/src/types/account.d.ts +29 -0
- package/dist/src/types/account.js +5 -0
- package/dist/src/types/config.d.ts +98 -0
- package/dist/src/types/config.js +8 -0
- package/dist/src/types/constants.d.ts +42 -0
- package/dist/src/types/constants.js +45 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.js +17 -0
- package/dist/src/types/message.d.ts +238 -0
- package/dist/src/types/message.js +6 -0
- package/dist/src/utils.d.ts +148 -0
- package/dist/src/utils.js +92 -0
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.js +28 -0
- package/dist/src/webhook/command-auth.d.ts +47 -0
- package/dist/src/webhook/command-auth.js +137 -0
- package/dist/src/webhook/gateway.d.ts +36 -0
- package/dist/src/webhook/gateway.js +297 -0
- package/dist/src/webhook/handler.d.ts +19 -0
- package/dist/src/webhook/handler.js +481 -0
- package/dist/src/webhook/helpers.d.ts +157 -0
- package/dist/src/webhook/helpers.js +936 -0
- package/dist/src/webhook/http.d.ts +27 -0
- package/dist/src/webhook/http.js +168 -0
- package/dist/src/webhook/index.d.ts +11 -0
- package/dist/src/webhook/index.js +43 -0
- package/dist/src/webhook/media.d.ts +30 -0
- package/dist/src/webhook/media.js +152 -0
- package/dist/src/webhook/monitor.d.ts +59 -0
- package/dist/src/webhook/monitor.js +1672 -0
- package/dist/src/webhook/state.d.ts +220 -0
- package/dist/src/webhook/state.js +568 -0
- package/dist/src/webhook/target.d.ts +41 -0
- package/dist/src/webhook/target.js +165 -0
- package/dist/src/webhook/types.d.ts +348 -0
- package/dist/src/webhook/types.js +36 -0
- package/dist/src/webhook/video-frame.d.ts +13 -0
- package/dist/src/webhook/video-frame.js +108 -0
- package/openclaw.plugin.json +19 -0
- package/package.json +96 -0
- package/schema.json +534 -0
- package/scripts/generate-schema.mjs +33 -0
- package/skills/wecom-contact/SKILL.md +162 -0
- package/skills/wecom-doc/SKILL.md +162 -0
- package/skills/wecom-doc/references/create-doc.md +56 -0
- package/skills/wecom-doc/references/edit-doc-content.md +68 -0
- package/skills/wecom-doc/references/get-doc-content.md +88 -0
- package/skills/wecom-doc/references/smartpage-create.md +125 -0
- package/skills/wecom-doc/references/smartpage-export.md +160 -0
- package/skills/wecom-meeting/SKILL.md +441 -0
- package/skills/wecom-meeting/references/example-full.md +30 -0
- package/skills/wecom-meeting/references/example-reminder.md +46 -0
- package/skills/wecom-meeting/references/example-security.md +22 -0
- package/skills/wecom-meeting/references/response-get-meeting-info.md +148 -0
- package/skills/wecom-msg/SKILL.md +157 -0
- package/skills/wecom-msg/references/api-get-messages.md +93 -0
- package/skills/wecom-msg/references/api-get-msg-chat-list.md +58 -0
- package/skills/wecom-msg/references/api-get-msg-media.md +44 -0
- package/skills/wecom-msg/references/api-send-message.md +39 -0
- package/skills/wecom-preflight/SKILL.md +141 -0
- package/skills/wecom-schedule/SKILL.md +161 -0
- package/skills/wecom-schedule/references/api-check-availability.md +56 -0
- package/skills/wecom-schedule/references/api-create-schedule.md +38 -0
- package/skills/wecom-schedule/references/api-get-schedule-detail.md +81 -0
- package/skills/wecom-schedule/references/api-update-schedule.md +32 -0
- package/skills/wecom-schedule/references/ref-reminders.md +24 -0
- package/skills/wecom-send-media/SKILL.md +68 -0
- package/skills/wecom-send-template-card/SKILL.md +157 -0
- package/skills/wecom-send-template-card/references/api-template-card-types.md +358 -0
- package/skills/wecom-smartsheet/SKILL.md +164 -0
- package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +163 -0
- package/skills/wecom-smartsheet/references/smartsheet-field-types.md +44 -0
- package/skills/wecom-smartsheet/references/smartsheet-get-records.md +96 -0
- package/skills/wecom-smartsheet/references/webhook-examples.md +185 -0
- package/skills/wecom-smartsheet/references/webhook-fallback.md +184 -0
- package/skills/wecom-todo/SKILL.md +392 -0
- package/skills/wecom-todo/examples/workflows.md +163 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare type AdaptedEvent = {
|
|
2
|
+
parsed: boolean;
|
|
3
|
+
eventType: string;
|
|
4
|
+
subAgentStartLine?: string;
|
|
5
|
+
subAgentRunId?: string;
|
|
6
|
+
finalAnswerText?: string;
|
|
7
|
+
errorText?: string;
|
|
8
|
+
confirmationText?: string;
|
|
9
|
+
confirmationDedupKey?: string;
|
|
10
|
+
ignoreAsNoise?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare function adaptEndpointEvent(params: {
|
|
13
|
+
rawText: string;
|
|
14
|
+
currentEventType?: string;
|
|
15
|
+
}): AdaptedEvent;
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.adaptEndpointEvent = void 0;
|
|
4
|
+
function asObj(value) {
|
|
5
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
function toText(value) {
|
|
11
|
+
if (value == null)
|
|
12
|
+
return "";
|
|
13
|
+
if (typeof value === "string")
|
|
14
|
+
return value.trim();
|
|
15
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
16
|
+
return String(value);
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
function parseJsonObjectSafely(raw) {
|
|
20
|
+
try {
|
|
21
|
+
var parsed = JSON.parse(raw);
|
|
22
|
+
return asObj(parsed);
|
|
23
|
+
}
|
|
24
|
+
catch (_a) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function parseEventContentObject(payload) {
|
|
29
|
+
var raw = payload.eventContent;
|
|
30
|
+
if (typeof raw === "string")
|
|
31
|
+
return parseJsonObjectSafely(raw);
|
|
32
|
+
return asObj(raw);
|
|
33
|
+
}
|
|
34
|
+
function getContentTypeFromObject(value) {
|
|
35
|
+
// Python IM 端点的 content_type 可能在 eventContent 或 data 内,并存在 snake/camel 两种写法。
|
|
36
|
+
return (toText(value === null || value === void 0 ? void 0 : value.content_type) || toText(value === null || value === void 0 ? void 0 : value.contentType)).toLowerCase();
|
|
37
|
+
}
|
|
38
|
+
function extractContentTextFromPayload(payload) {
|
|
39
|
+
var eventContentObj = parseEventContentObject(payload);
|
|
40
|
+
var rawEventContent = eventContentObj === null || eventContentObj === void 0 ? void 0 : eventContentObj.content;
|
|
41
|
+
if (typeof rawEventContent === "string")
|
|
42
|
+
return rawEventContent;
|
|
43
|
+
var fromEvent = toText(rawEventContent);
|
|
44
|
+
if (fromEvent)
|
|
45
|
+
return fromEvent;
|
|
46
|
+
var dataObj = asObj(payload.data);
|
|
47
|
+
var rawDataContent = dataObj === null || dataObj === void 0 ? void 0 : dataObj.content;
|
|
48
|
+
if (typeof rawDataContent === "string")
|
|
49
|
+
return rawDataContent;
|
|
50
|
+
return toText(rawDataContent);
|
|
51
|
+
}
|
|
52
|
+
function isFinalAnswerPayload(payload) {
|
|
53
|
+
// final_answer 只按结构化 content_type 判断,不用文本内容或 responseId 猜测。
|
|
54
|
+
var eventContentObj = parseEventContentObject(payload);
|
|
55
|
+
if (getContentTypeFromObject(eventContentObj) === "final_answer")
|
|
56
|
+
return true;
|
|
57
|
+
return getContentTypeFromObject(asObj(payload.data)) === "final_answer";
|
|
58
|
+
}
|
|
59
|
+
function extractFinalAnswerTextFromNestedMessage(item) {
|
|
60
|
+
var dataObj = asObj(item.data) || parseEventContentObject(item);
|
|
61
|
+
if (getContentTypeFromObject(dataObj) !== "final_answer")
|
|
62
|
+
return "";
|
|
63
|
+
var rawContent = dataObj === null || dataObj === void 0 ? void 0 : dataObj.content;
|
|
64
|
+
if (typeof rawContent === "string")
|
|
65
|
+
return rawContent;
|
|
66
|
+
return toText(rawContent);
|
|
67
|
+
}
|
|
68
|
+
function extractFinalAnswerTextFromUpsertRecord(payload) {
|
|
69
|
+
var _a;
|
|
70
|
+
// 前端同款流中 final_answer 可能只存在于 upsert_record 的嵌套 messages,
|
|
71
|
+
// monitor 开启“只显示结论”时需要这个字段补齐最终答案。
|
|
72
|
+
var eventContentObj = parseEventContentObject(payload);
|
|
73
|
+
var messageObj = asObj((_a = asObj(eventContentObj === null || eventContentObj === void 0 ? void 0 : eventContentObj.extParams)) === null || _a === void 0 ? void 0 : _a.message);
|
|
74
|
+
var externalObj = asObj(messageObj === null || messageObj === void 0 ? void 0 : messageObj.external);
|
|
75
|
+
var messages = Array.isArray(externalObj === null || externalObj === void 0 ? void 0 : externalObj.messages) ? externalObj.messages : [];
|
|
76
|
+
// 从后往前取最新 final_answer,避免输出历史中间态。
|
|
77
|
+
for (var i = messages.length - 1; i >= 0; i -= 1) {
|
|
78
|
+
var item = asObj(messages[i]);
|
|
79
|
+
if (!item)
|
|
80
|
+
continue;
|
|
81
|
+
var text = extractFinalAnswerTextFromNestedMessage(item);
|
|
82
|
+
if (text)
|
|
83
|
+
return text;
|
|
84
|
+
}
|
|
85
|
+
return "";
|
|
86
|
+
}
|
|
87
|
+
function extractErrorTextFromPayload(payload) {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
var eventContentObj = parseEventContentObject(payload);
|
|
90
|
+
var source = eventContentObj || payload;
|
|
91
|
+
var message = toText(source.msg) ||
|
|
92
|
+
toText(source.message) ||
|
|
93
|
+
toText(source.error) ||
|
|
94
|
+
toText((_a = asObj(source.error)) === null || _a === void 0 ? void 0 : _a.message);
|
|
95
|
+
var solution = toText((_b = asObj(source.extraInfo)) === null || _b === void 0 ? void 0 : _b.solution);
|
|
96
|
+
var code = toText(source.code);
|
|
97
|
+
var lines = [];
|
|
98
|
+
if (message)
|
|
99
|
+
lines.push(message);
|
|
100
|
+
if (solution && solution !== message)
|
|
101
|
+
lines.push(solution);
|
|
102
|
+
if (!lines.length && code)
|
|
103
|
+
lines.push("\u9519\u8BEF\u7801\uFF1A" + code);
|
|
104
|
+
return lines.join("\n").trim();
|
|
105
|
+
}
|
|
106
|
+
function resolveEventType(currentEventType, payload) {
|
|
107
|
+
var current = String(currentEventType || "").trim().toLowerCase();
|
|
108
|
+
var fromPayload = toText(payload.eventType).toLowerCase();
|
|
109
|
+
if ((!current || current === "message") && fromPayload)
|
|
110
|
+
return fromPayload;
|
|
111
|
+
return current || fromPayload;
|
|
112
|
+
}
|
|
113
|
+
function getResponseId(payload) {
|
|
114
|
+
return toText(payload.responseId) || toText(payload.response_id);
|
|
115
|
+
}
|
|
116
|
+
function getAgentRunId(payload) {
|
|
117
|
+
var fromRoot = toText(payload.agent_run_id) || toText(payload.agentRunId);
|
|
118
|
+
if (fromRoot)
|
|
119
|
+
return fromRoot;
|
|
120
|
+
var dataObj = asObj(payload.data);
|
|
121
|
+
var dataAgent = asObj(dataObj === null || dataObj === void 0 ? void 0 : dataObj.agent);
|
|
122
|
+
var fromData = toText(dataAgent === null || dataAgent === void 0 ? void 0 : dataAgent.agent_run_id) || toText(dataAgent === null || dataAgent === void 0 ? void 0 : dataAgent.agentRunId);
|
|
123
|
+
if (fromData)
|
|
124
|
+
return fromData;
|
|
125
|
+
var eventObj = parseEventContentObject(payload);
|
|
126
|
+
var eventAgent = asObj(eventObj === null || eventObj === void 0 ? void 0 : eventObj.agent);
|
|
127
|
+
return toText(eventAgent === null || eventAgent === void 0 ? void 0 : eventAgent.agent_run_id) || toText(eventAgent === null || eventAgent === void 0 ? void 0 : eventAgent.agentRunId);
|
|
128
|
+
}
|
|
129
|
+
function toReadableActionStatus(rawStatus) {
|
|
130
|
+
var status = toText(rawStatus).toLowerCase();
|
|
131
|
+
if (!status)
|
|
132
|
+
return "未知";
|
|
133
|
+
if (status === "running")
|
|
134
|
+
return "进行中";
|
|
135
|
+
if (status === "pending")
|
|
136
|
+
return "待确认";
|
|
137
|
+
if (status === "completed")
|
|
138
|
+
return "已完成";
|
|
139
|
+
if (status === "failed")
|
|
140
|
+
return "失败";
|
|
141
|
+
if (status === "cancelled")
|
|
142
|
+
return "已取消";
|
|
143
|
+
return status;
|
|
144
|
+
}
|
|
145
|
+
function toReadableConfirmationType(rawType) {
|
|
146
|
+
var type = toText(rawType).toLowerCase();
|
|
147
|
+
if (!type)
|
|
148
|
+
return "未知";
|
|
149
|
+
if (type === "single_choice" || type === "single-choice" || type === "radio")
|
|
150
|
+
return "单选";
|
|
151
|
+
if (type === "multiple_choice" ||
|
|
152
|
+
type === "multi_choice" ||
|
|
153
|
+
type === "multiple-choice" ||
|
|
154
|
+
type === "checkbox") {
|
|
155
|
+
return "多选";
|
|
156
|
+
}
|
|
157
|
+
return type;
|
|
158
|
+
}
|
|
159
|
+
function normalizeConfirmationStatus(rawStatus) {
|
|
160
|
+
return toText(rawStatus).toLowerCase();
|
|
161
|
+
}
|
|
162
|
+
function isPendingConfirmationStatus(rawStatus) {
|
|
163
|
+
return normalizeConfirmationStatus(rawStatus) === "pending";
|
|
164
|
+
}
|
|
165
|
+
function buildReadableConfirmationRequests(metadata) {
|
|
166
|
+
var lines = [];
|
|
167
|
+
var requestsRaw = metadata === null || metadata === void 0 ? void 0 : metadata.requests;
|
|
168
|
+
if (!Array.isArray(requestsRaw) || requestsRaw.length === 0)
|
|
169
|
+
return lines;
|
|
170
|
+
lines.push("确认请求列表:", "");
|
|
171
|
+
requestsRaw.forEach(function (requestItem, index) {
|
|
172
|
+
var request = asObj(requestItem);
|
|
173
|
+
if (!request)
|
|
174
|
+
return;
|
|
175
|
+
var type = toText(request.type);
|
|
176
|
+
var title = toText(request.title) || "\u786E\u8BA4\u8BF7\u6C42 " + (index + 1);
|
|
177
|
+
var question = toText(request.question);
|
|
178
|
+
lines.push("\u95EE\u9898 " + (index + 1) + "\uFF1A" + title, "");
|
|
179
|
+
if (type)
|
|
180
|
+
lines.push("\u7C7B\u578B\uFF1A" + toReadableConfirmationType(type), "");
|
|
181
|
+
if (question)
|
|
182
|
+
lines.push("\u95EE\u9898\u5185\u5BB9\uFF1A" + question, "");
|
|
183
|
+
var optionsRaw = request.options;
|
|
184
|
+
if (Array.isArray(optionsRaw) && optionsRaw.length > 0) {
|
|
185
|
+
lines.push("选项:", "");
|
|
186
|
+
optionsRaw.forEach(function (optionItem, optionIndex) {
|
|
187
|
+
var option = asObj(optionItem);
|
|
188
|
+
var optionLabel = toText(option === null || option === void 0 ? void 0 : option.label) || toText(option === null || option === void 0 ? void 0 : option.value) || toText(optionItem);
|
|
189
|
+
lines.push(optionIndex + 1 + ". " + (optionLabel || "\u9009\u9879" + (optionIndex + 1)));
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
lines.push("选项:无");
|
|
194
|
+
}
|
|
195
|
+
lines.push("");
|
|
196
|
+
});
|
|
197
|
+
return lines;
|
|
198
|
+
}
|
|
199
|
+
function extractConfirmationActionPlainText(payload, eventType) {
|
|
200
|
+
var _a;
|
|
201
|
+
if (eventType !== "action")
|
|
202
|
+
return null;
|
|
203
|
+
var actionPayload = (_a = parseEventContentObject(payload)) !== null && _a !== void 0 ? _a : payload;
|
|
204
|
+
var toolName = toText(actionPayload.toolName).toLowerCase();
|
|
205
|
+
var actionType = toText(actionPayload.actionType).toLowerCase();
|
|
206
|
+
if (toolName !== "request_confirmation" && actionType !== "request_confirmation")
|
|
207
|
+
return null;
|
|
208
|
+
if (!isPendingConfirmationStatus(actionPayload.status))
|
|
209
|
+
return null;
|
|
210
|
+
var title = toText(actionPayload.title);
|
|
211
|
+
var description = toText(actionPayload.description);
|
|
212
|
+
var toolCallId = toText(actionPayload.toolCallId);
|
|
213
|
+
var responseId = getResponseId(payload);
|
|
214
|
+
var requestId = toText(payload.requestId);
|
|
215
|
+
var metadata = asObj(actionPayload.metadata);
|
|
216
|
+
var lines = ["【用户确认请求】", "", "\u72B6\u6001\uFF1A" + toReadableActionStatus(actionPayload.status), ""];
|
|
217
|
+
if (title)
|
|
218
|
+
lines.push("\u6807\u9898\uFF1A" + title);
|
|
219
|
+
if (description)
|
|
220
|
+
lines.push("\u8BF4\u660E\uFF1A" + description);
|
|
221
|
+
if (toolCallId || responseId || requestId)
|
|
222
|
+
lines.push("");
|
|
223
|
+
var reqLines = buildReadableConfirmationRequests(metadata);
|
|
224
|
+
if (reqLines.length > 0)
|
|
225
|
+
lines.push.apply(lines, reqLines);
|
|
226
|
+
return lines.join("\n").trim();
|
|
227
|
+
}
|
|
228
|
+
function extractConfirmationRequestPlainText(payload, eventType) {
|
|
229
|
+
var _a;
|
|
230
|
+
if (eventType !== "confirmation_request")
|
|
231
|
+
return null;
|
|
232
|
+
var eventContent = (_a = parseEventContentObject(payload)) !== null && _a !== void 0 ? _a : asObj(payload);
|
|
233
|
+
if (!eventContent || !isPendingConfirmationStatus(eventContent.status))
|
|
234
|
+
return null;
|
|
235
|
+
var requests = Array.isArray(eventContent.requests) ? eventContent.requests : [];
|
|
236
|
+
var responseId = getResponseId(payload);
|
|
237
|
+
var requestId = toText(payload.requestId);
|
|
238
|
+
var lines = ["【用户确认请求】", "\u72B6\u6001\uFF1A" + toReadableActionStatus(eventContent.status), ""];
|
|
239
|
+
if (responseId || requestId)
|
|
240
|
+
lines.push("");
|
|
241
|
+
var reqLines = buildReadableConfirmationRequests({ requests: requests });
|
|
242
|
+
if (reqLines.length > 0)
|
|
243
|
+
lines.push.apply(lines, reqLines);
|
|
244
|
+
lines.push("\u786E\u8BA4\u95EE\u9898\u6570\uFF1A" + requests.length);
|
|
245
|
+
return lines.join("\n").trim();
|
|
246
|
+
}
|
|
247
|
+
function isLikelyConfirmationPayload(payload) {
|
|
248
|
+
if (!isPendingConfirmationStatus(payload.status))
|
|
249
|
+
return false;
|
|
250
|
+
var merged = (toText(payload.title) + "\n" + toText(payload.content)).trim();
|
|
251
|
+
return merged.includes("确认") && merged.includes("选项");
|
|
252
|
+
}
|
|
253
|
+
function buildConfirmationSummaryFromLooseText(text) {
|
|
254
|
+
var _a;
|
|
255
|
+
var normalized = String(text || "").replace(/\r/g, "\n").trim();
|
|
256
|
+
if (!normalized)
|
|
257
|
+
return null;
|
|
258
|
+
var question = normalized;
|
|
259
|
+
var optionsPart = "";
|
|
260
|
+
var optionAnchor = normalized.match(/选项(?:分别)?(?:为|是)\s*[::]\s*([\s\S]+)/) ||
|
|
261
|
+
normalized.match(/选项\s*[::]\s*([\s\S]+)/);
|
|
262
|
+
if (optionAnchor) {
|
|
263
|
+
optionsPart = String(optionAnchor[1] || "").trim();
|
|
264
|
+
question = normalized.slice(0, (_a = optionAnchor.index) !== null && _a !== void 0 ? _a : normalized.length).trim();
|
|
265
|
+
}
|
|
266
|
+
var rawOptions = optionsPart
|
|
267
|
+
? optionsPart
|
|
268
|
+
.split(/[、,,;;\n]+/)
|
|
269
|
+
.map(function (item) { return item.trim(); })
|
|
270
|
+
.filter(Boolean)
|
|
271
|
+
: [];
|
|
272
|
+
var uniqueOptions = Array.from(new Set(rawOptions));
|
|
273
|
+
var choiceType = /多选/.test(normalized) || /multiple/.test(normalized.toLowerCase()) ? "多选" : "单选";
|
|
274
|
+
var lines = ["【用户确认请求】", "状态:待确认", "", "确认请求列表:", ""];
|
|
275
|
+
lines.push("\u95EE\u9898 1\uFF1A" + (question || "确认请求"));
|
|
276
|
+
lines.push("\u7C7B\u578B\uFF1A" + choiceType);
|
|
277
|
+
if (question)
|
|
278
|
+
lines.push("\u95EE\u9898\u5185\u5BB9\uFF1A" + question);
|
|
279
|
+
if (uniqueOptions.length > 0) {
|
|
280
|
+
lines.push("选项:");
|
|
281
|
+
uniqueOptions.forEach(function (opt, idx) { return lines.push(idx + 1 + ". " + opt); });
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
lines.push("选项:无");
|
|
285
|
+
}
|
|
286
|
+
lines.push("", "确认问题数:1");
|
|
287
|
+
return lines.join("\n").trim();
|
|
288
|
+
}
|
|
289
|
+
function extractConfirmationDedupKey(payload, eventType) {
|
|
290
|
+
var _a, _b;
|
|
291
|
+
var responseId = getResponseId(payload);
|
|
292
|
+
if (!responseId)
|
|
293
|
+
return null;
|
|
294
|
+
if (eventType === "confirmation_request") {
|
|
295
|
+
var eventContent = (_a = parseEventContentObject(payload)) !== null && _a !== void 0 ? _a : payload;
|
|
296
|
+
if (!isPendingConfirmationStatus(eventContent.status))
|
|
297
|
+
return null;
|
|
298
|
+
return "confirmation_request:" + responseId;
|
|
299
|
+
}
|
|
300
|
+
if (eventType === "action") {
|
|
301
|
+
var actionPayload = (_b = parseEventContentObject(payload)) !== null && _b !== void 0 ? _b : payload;
|
|
302
|
+
var toolName = toText(actionPayload.toolName).toLowerCase();
|
|
303
|
+
var actionType = toText(actionPayload.actionType).toLowerCase();
|
|
304
|
+
if (!isPendingConfirmationStatus(actionPayload.status))
|
|
305
|
+
return null;
|
|
306
|
+
if (toolName === "request_confirmation" || actionType === "request_confirmation") {
|
|
307
|
+
return "action_confirmation:" + responseId;
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
if ((eventType === "title" || eventType === "tool_wait") && isLikelyConfirmationPayload(payload)) {
|
|
312
|
+
return "loose_confirmation:" + responseId;
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
function hasEventMarkers(payload) {
|
|
317
|
+
return Boolean(toText(payload.eventType) ||
|
|
318
|
+
toText(payload.type) ||
|
|
319
|
+
payload.eventContent !== undefined ||
|
|
320
|
+
payload.responseId !== undefined ||
|
|
321
|
+
payload.response_id !== undefined ||
|
|
322
|
+
payload.agent_run_id !== undefined ||
|
|
323
|
+
payload.agentRunId !== undefined);
|
|
324
|
+
}
|
|
325
|
+
function adaptEndpointEvent(params) {
|
|
326
|
+
var rawText = String(params.rawText || "");
|
|
327
|
+
var parsed = parseJsonObjectSafely(rawText.trim());
|
|
328
|
+
if (!parsed || !hasEventMarkers(parsed)) {
|
|
329
|
+
return { parsed: false, eventType: "" };
|
|
330
|
+
}
|
|
331
|
+
var eventType = resolveEventType(params.currentEventType || "", parsed);
|
|
332
|
+
var payloadEventType = toText(parsed.eventType).toLowerCase();
|
|
333
|
+
var explicitType = toText(parsed.type).toLowerCase();
|
|
334
|
+
// call_sub_agent 是子代理边界的起点,返回提示文本和 run_id 给调用方做去重与后续过滤。
|
|
335
|
+
if (eventType === "call_sub_agent" ||
|
|
336
|
+
payloadEventType === "call_sub_agent" ||
|
|
337
|
+
explicitType === "call_sub_agent") {
|
|
338
|
+
var dataObj = asObj(parsed.data) || parseEventContentObject(parsed);
|
|
339
|
+
var agentObj = asObj(dataObj === null || dataObj === void 0 ? void 0 : dataObj.agent);
|
|
340
|
+
var agentName = toText(agentObj === null || agentObj === void 0 ? void 0 : agentObj.name) || toText(agentObj === null || agentObj === void 0 ? void 0 : agentObj.agent_id) || toText(parsed.name) || "未知子代理";
|
|
341
|
+
var agentRunId_1 = toText(agentObj === null || agentObj === void 0 ? void 0 : agentObj.agent_run_id) || getAgentRunId(parsed);
|
|
342
|
+
return {
|
|
343
|
+
parsed: true,
|
|
344
|
+
eventType: eventType,
|
|
345
|
+
subAgentStartLine: "\n\u8C03\u7528 sub agent\uFF1A" + agentName + "\n\n",
|
|
346
|
+
subAgentRunId: agentRunId_1 || undefined
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
var agentRunId = getAgentRunId(parsed);
|
|
350
|
+
if (eventType === "content" && isFinalAnswerPayload(parsed)) {
|
|
351
|
+
// content 事件携带 final_answer 时,adapter 只提取语义化文本,不直接决定是否输出。
|
|
352
|
+
return {
|
|
353
|
+
parsed: true,
|
|
354
|
+
eventType: eventType,
|
|
355
|
+
subAgentRunId: agentRunId || undefined,
|
|
356
|
+
finalAnswerText: extractContentTextFromPayload(parsed)
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
if (eventType === "upsert_record") {
|
|
360
|
+
// upsert_record 自身不应作为普通文本透出,只在其中补取 final_answer。
|
|
361
|
+
return {
|
|
362
|
+
parsed: true,
|
|
363
|
+
eventType: eventType,
|
|
364
|
+
subAgentRunId: agentRunId || undefined,
|
|
365
|
+
finalAnswerText: extractFinalAnswerTextFromUpsertRecord(parsed),
|
|
366
|
+
ignoreAsNoise: true
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
if (eventType === "error") {
|
|
370
|
+
// error 必须语义化透出,调用方会保证它不受 sub-agent 隐藏和 final-only 限制。
|
|
371
|
+
return {
|
|
372
|
+
parsed: true,
|
|
373
|
+
eventType: eventType,
|
|
374
|
+
subAgentRunId: agentRunId || undefined,
|
|
375
|
+
errorText: extractErrorTextFromPayload(parsed)
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
var dedupKey = extractConfirmationDedupKey(parsed, eventType);
|
|
379
|
+
var actionText = extractConfirmationActionPlainText(parsed, eventType);
|
|
380
|
+
if (actionText) {
|
|
381
|
+
return {
|
|
382
|
+
parsed: true,
|
|
383
|
+
eventType: eventType,
|
|
384
|
+
subAgentRunId: agentRunId || undefined,
|
|
385
|
+
confirmationText: actionText,
|
|
386
|
+
confirmationDedupKey: dedupKey || undefined
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
var requestText = extractConfirmationRequestPlainText(parsed, eventType);
|
|
390
|
+
if (requestText) {
|
|
391
|
+
return {
|
|
392
|
+
parsed: true,
|
|
393
|
+
eventType: eventType,
|
|
394
|
+
subAgentRunId: agentRunId || undefined,
|
|
395
|
+
confirmationText: requestText,
|
|
396
|
+
confirmationDedupKey: dedupKey || undefined
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
if ((eventType === "title" || eventType === "tool_wait") && isLikelyConfirmationPayload(parsed)) {
|
|
400
|
+
var eventContent = parseEventContentObject(parsed);
|
|
401
|
+
var looseText = toText(parsed.content) || toText(parsed.title) || toText(eventContent) || "";
|
|
402
|
+
var summary = buildConfirmationSummaryFromLooseText(looseText);
|
|
403
|
+
if (summary) {
|
|
404
|
+
return {
|
|
405
|
+
parsed: true,
|
|
406
|
+
eventType: eventType,
|
|
407
|
+
subAgentRunId: agentRunId || undefined,
|
|
408
|
+
confirmationText: summary,
|
|
409
|
+
confirmationDedupKey: dedupKey || undefined
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (eventType &&
|
|
414
|
+
eventType !== "message" &&
|
|
415
|
+
eventType !== "content" &&
|
|
416
|
+
eventType !== "resource" &&
|
|
417
|
+
eventType !== "error") {
|
|
418
|
+
return {
|
|
419
|
+
parsed: true,
|
|
420
|
+
eventType: eventType,
|
|
421
|
+
subAgentRunId: agentRunId || undefined,
|
|
422
|
+
ignoreAsNoise: true
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
return { parsed: true, eventType: eventType, subAgentRunId: agentRunId || undefined };
|
|
426
|
+
}
|
|
427
|
+
exports.adaptEndpointEvent = adaptEndpointEvent;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 企业微信群组访问控制模块
|
|
3
|
+
*
|
|
4
|
+
* 负责群组策略检查(groupPolicy、群组白名单、群内发送者白名单)
|
|
5
|
+
*/
|
|
6
|
+
import type { OpenClawConfig } from "ylib-openclaw/plugin-sdk";
|
|
7
|
+
import type { RuntimeEnv } from "ylib-openclaw/plugin-sdk";
|
|
8
|
+
import type { ResolvedWeComAccount } from "./utils.js";
|
|
9
|
+
/**
|
|
10
|
+
* 群组策略检查结果
|
|
11
|
+
*/
|
|
12
|
+
export interface GroupPolicyCheckResult {
|
|
13
|
+
/** 是否允许继续处理消息 */
|
|
14
|
+
allowed: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 检查群组策略访问控制
|
|
18
|
+
* @returns 检查结果,包含是否允许继续处理
|
|
19
|
+
*/
|
|
20
|
+
export declare function checkGroupPolicy(params: {
|
|
21
|
+
chatId: string;
|
|
22
|
+
senderId: string;
|
|
23
|
+
account: ResolvedWeComAccount;
|
|
24
|
+
config: OpenClawConfig;
|
|
25
|
+
runtime: RuntimeEnv;
|
|
26
|
+
}): GroupPolicyCheckResult;
|
|
27
|
+
/**
|
|
28
|
+
* 检查发送者是否在允许列表中(通用)
|
|
29
|
+
*/
|
|
30
|
+
export declare function isSenderAllowed(senderId: string, allowFrom: string[]): boolean;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 企业微信群组访问控制模块
|
|
4
|
+
*
|
|
5
|
+
* 负责群组策略检查(groupPolicy、群组白名单、群内发送者白名单)
|
|
6
|
+
*/
|
|
7
|
+
exports.__esModule = true;
|
|
8
|
+
exports.isSenderAllowed = exports.checkGroupPolicy = void 0;
|
|
9
|
+
var const_js_1 = require("./const.js");
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// 内部辅助函数
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* 解析企业微信群组配置
|
|
15
|
+
*/
|
|
16
|
+
function resolveWeComGroupConfig(params) {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
var groups = (_b = (_a = params.cfg) === null || _a === void 0 ? void 0 : _a.groups) !== null && _b !== void 0 ? _b : {};
|
|
19
|
+
var wildcard = groups["*"];
|
|
20
|
+
var groupId = (_c = params.groupId) === null || _c === void 0 ? void 0 : _c.trim();
|
|
21
|
+
if (!groupId) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
var direct = groups[groupId];
|
|
25
|
+
if (direct) {
|
|
26
|
+
return direct;
|
|
27
|
+
}
|
|
28
|
+
var lowered = groupId.toLowerCase();
|
|
29
|
+
var matchKey = Object.keys(groups).find(function (key) { return key.toLowerCase() === lowered; });
|
|
30
|
+
if (matchKey) {
|
|
31
|
+
return groups[matchKey];
|
|
32
|
+
}
|
|
33
|
+
return wildcard;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 检查群组是否在允许列表中
|
|
37
|
+
*/
|
|
38
|
+
function isWeComGroupAllowed(params) {
|
|
39
|
+
var groupPolicy = params.groupPolicy;
|
|
40
|
+
if (groupPolicy === "disabled") {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (groupPolicy === "open") {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
// allowlist 模式:检查群组是否在允许列表中
|
|
47
|
+
var normalizedAllowFrom = params.allowFrom.map(function (entry) {
|
|
48
|
+
return String(entry).replace(new RegExp("^" + const_js_1.CHANNEL_ID + ":", "i"), "").trim();
|
|
49
|
+
});
|
|
50
|
+
if (normalizedAllowFrom.includes("*")) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
var normalizedGroupId = params.groupId.trim();
|
|
54
|
+
return normalizedAllowFrom.some(function (entry) { return entry === normalizedGroupId || entry.toLowerCase() === normalizedGroupId.toLowerCase(); });
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 检查群组内发送者是否在允许列表中
|
|
58
|
+
*/
|
|
59
|
+
function isGroupSenderAllowed(params) {
|
|
60
|
+
var _a;
|
|
61
|
+
var senderId = params.senderId, groupId = params.groupId, wecomConfig = params.wecomConfig;
|
|
62
|
+
var groupConfig = resolveWeComGroupConfig({
|
|
63
|
+
cfg: wecomConfig,
|
|
64
|
+
groupId: groupId
|
|
65
|
+
});
|
|
66
|
+
var perGroupSenderAllowFrom = ((_a = groupConfig === null || groupConfig === void 0 ? void 0 : groupConfig.allowFrom) !== null && _a !== void 0 ? _a : []).map(function (v) { return String(v); });
|
|
67
|
+
if (perGroupSenderAllowFrom.length === 0) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
if (perGroupSenderAllowFrom.includes("*")) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return perGroupSenderAllowFrom.some(function (entry) {
|
|
74
|
+
var normalized = entry.replace(new RegExp("^" + const_js_1.CHANNEL_ID + ":", "i"), "").trim();
|
|
75
|
+
return normalized === senderId || normalized === "user:" + senderId;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// 公开 API
|
|
80
|
+
// ============================================================================
|
|
81
|
+
/**
|
|
82
|
+
* 检查群组策略访问控制
|
|
83
|
+
* @returns 检查结果,包含是否允许继续处理
|
|
84
|
+
*/
|
|
85
|
+
function checkGroupPolicy(params) {
|
|
86
|
+
var _a, _b, _c, _d;
|
|
87
|
+
var chatId = params.chatId, senderId = params.senderId, account = params.account, runtime = params.runtime;
|
|
88
|
+
// 使用 account.config(已经过多账号合并),而非顶层 config.channels.wecom
|
|
89
|
+
// 避免多账户模式下 groupAllowFrom / groups 等字段取不到账号级配置
|
|
90
|
+
var wecomConfig = account.config;
|
|
91
|
+
var groupPolicy = (_a = wecomConfig.groupPolicy) !== null && _a !== void 0 ? _a : "open";
|
|
92
|
+
var groupAllowFrom = (_b = wecomConfig.groupAllowFrom) !== null && _b !== void 0 ? _b : [];
|
|
93
|
+
var groupAllowed = isWeComGroupAllowed({
|
|
94
|
+
groupPolicy: groupPolicy,
|
|
95
|
+
allowFrom: groupAllowFrom,
|
|
96
|
+
groupId: chatId
|
|
97
|
+
});
|
|
98
|
+
if (!groupAllowed) {
|
|
99
|
+
(_c = runtime.log) === null || _c === void 0 ? void 0 : _c.call(runtime, "[WeCom] Group " + chatId + " not allowed (groupPolicy=" + groupPolicy + ")");
|
|
100
|
+
return { allowed: false };
|
|
101
|
+
}
|
|
102
|
+
var senderAllowed = isGroupSenderAllowed({
|
|
103
|
+
senderId: senderId,
|
|
104
|
+
groupId: chatId,
|
|
105
|
+
wecomConfig: wecomConfig
|
|
106
|
+
});
|
|
107
|
+
if (!senderAllowed) {
|
|
108
|
+
(_d = runtime.log) === null || _d === void 0 ? void 0 : _d.call(runtime, "[WeCom] Sender " + senderId + " not in group " + chatId + " sender allowlist");
|
|
109
|
+
return { allowed: false };
|
|
110
|
+
}
|
|
111
|
+
return { allowed: true };
|
|
112
|
+
}
|
|
113
|
+
exports.checkGroupPolicy = checkGroupPolicy;
|
|
114
|
+
/**
|
|
115
|
+
* 检查发送者是否在允许列表中(通用)
|
|
116
|
+
*/
|
|
117
|
+
function isSenderAllowed(senderId, allowFrom) {
|
|
118
|
+
if (allowFrom.includes("*")) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return allowFrom.some(function (entry) {
|
|
122
|
+
var normalized = entry.replace(new RegExp("^" + const_js_1.CHANNEL_ID + ":", "i"), "").trim();
|
|
123
|
+
return normalized === senderId || normalized === "user:" + senderId;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
exports.isSenderAllowed = isSenderAllowed;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/**
|
|
3
|
+
* **WecomHttpOptions (HTTP 选项)**
|
|
4
|
+
*
|
|
5
|
+
* @property proxyUrl 代理服务器地址
|
|
6
|
+
* @property timeoutMs 请求超时时间 (毫秒)
|
|
7
|
+
* @property signal AbortSignal 信号
|
|
8
|
+
*/
|
|
9
|
+
export declare type WecomHttpOptions = {
|
|
10
|
+
proxyUrl?: string;
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* **wecomFetch (统一 HTTP 请求)**
|
|
16
|
+
*
|
|
17
|
+
* 基于 `undici` 的 fetch 封装,自动处理 ProxyAgent 和 Timeout。
|
|
18
|
+
* 所有对企业微信 API 的调用都应经过此函数。
|
|
19
|
+
*/
|
|
20
|
+
export declare function wecomFetch(input: string | URL, init?: RequestInit, opts?: WecomHttpOptions): Promise<Response>;
|
|
21
|
+
/**
|
|
22
|
+
* **readResponseBodyAsBuffer (读取响应 Body)**
|
|
23
|
+
*
|
|
24
|
+
* 将 Response Body 读取为 Buffer,支持最大字节限制以防止内存溢出。
|
|
25
|
+
* 适用于下载媒体文件等场景。
|
|
26
|
+
*/
|
|
27
|
+
export declare function readResponseBodyAsBuffer(res: Response, maxBytes?: number): Promise<Buffer>;
|