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.
Files changed (180) hide show
  1. package/README.md +596 -0
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.js +99 -0
  4. package/dist/src/accounts.d.ts +57 -0
  5. package/dist/src/accounts.js +247 -0
  6. package/dist/src/agent/api-client.d.ts +95 -0
  7. package/dist/src/agent/api-client.js +425 -0
  8. package/dist/src/agent/handler.d.ts +64 -0
  9. package/dist/src/agent/handler.js +731 -0
  10. package/dist/src/agent/index.d.ts +5 -0
  11. package/dist/src/agent/index.js +21 -0
  12. package/dist/src/agent/webhook.d.ts +25 -0
  13. package/dist/src/agent/webhook.js +294 -0
  14. package/dist/src/agent/xml.d.ts +21 -0
  15. package/dist/src/agent/xml.js +43 -0
  16. package/dist/src/channel.d.ts +5 -0
  17. package/dist/src/channel.js +815 -0
  18. package/dist/src/chat-queue.d.ts +31 -0
  19. package/dist/src/chat-queue.js +53 -0
  20. package/dist/src/config-schema.d.ts +587 -0
  21. package/dist/src/config-schema.js +146 -0
  22. package/dist/src/const.d.ts +128 -0
  23. package/dist/src/const.js +168 -0
  24. package/dist/src/dm-policy.d.ts +29 -0
  25. package/dist/src/dm-policy.js +146 -0
  26. package/dist/src/dynamic-agent.d.ts +37 -0
  27. package/dist/src/dynamic-agent.js +67 -0
  28. package/dist/src/dynamic-routing.d.ts +65 -0
  29. package/dist/src/dynamic-routing.js +62 -0
  30. package/dist/src/endpoint-dispatch.d.ts +54 -0
  31. package/dist/src/endpoint-dispatch.js +967 -0
  32. package/dist/src/endpoint-event-adapter.d.ts +15 -0
  33. package/dist/src/endpoint-event-adapter.js +427 -0
  34. package/dist/src/group-policy.d.ts +30 -0
  35. package/dist/src/group-policy.js +126 -0
  36. package/dist/src/http.d.ts +27 -0
  37. package/dist/src/http.js +168 -0
  38. package/dist/src/im-runtime-telemetry.d.ts +25 -0
  39. package/dist/src/im-runtime-telemetry.js +68 -0
  40. package/dist/src/interface.d.ts +192 -0
  41. package/dist/src/interface.js +5 -0
  42. package/dist/src/markdown-chunk.d.ts +1 -0
  43. package/dist/src/markdown-chunk.js +396 -0
  44. package/dist/src/mcp/index.d.ts +6 -0
  45. package/dist/src/mcp/index.js +28 -0
  46. package/dist/src/mcp/interceptors/biz-error.d.ts +11 -0
  47. package/dist/src/mcp/interceptors/biz-error.js +73 -0
  48. package/dist/src/mcp/interceptors/doc-auth-error.d.ts +10 -0
  49. package/dist/src/mcp/interceptors/doc-auth-error.js +235 -0
  50. package/dist/src/mcp/interceptors/index.d.ts +35 -0
  51. package/dist/src/mcp/interceptors/index.js +143 -0
  52. package/dist/src/mcp/interceptors/msg-media.d.ts +11 -0
  53. package/dist/src/mcp/interceptors/msg-media.js +201 -0
  54. package/dist/src/mcp/interceptors/smartpage-create.d.ts +30 -0
  55. package/dist/src/mcp/interceptors/smartpage-create.js +252 -0
  56. package/dist/src/mcp/interceptors/smartpage-export.d.ts +17 -0
  57. package/dist/src/mcp/interceptors/smartpage-export.js +135 -0
  58. package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +22 -0
  59. package/dist/src/mcp/interceptors/smartsheet-upload.js +388 -0
  60. package/dist/src/mcp/interceptors/types.d.ts +64 -0
  61. package/dist/src/mcp/interceptors/types.js +8 -0
  62. package/dist/src/mcp/schema.d.ts +11 -0
  63. package/dist/src/mcp/schema.js +115 -0
  64. package/dist/src/mcp/tool.d.ts +63 -0
  65. package/dist/src/mcp/tool.js +318 -0
  66. package/dist/src/mcp/transport.d.ts +94 -0
  67. package/dist/src/mcp/transport.js +702 -0
  68. package/dist/src/media-handler.d.ts +55 -0
  69. package/dist/src/media-handler.js +306 -0
  70. package/dist/src/media-uploader.d.ts +142 -0
  71. package/dist/src/media-uploader.js +446 -0
  72. package/dist/src/message-parser.d.ts +104 -0
  73. package/dist/src/message-parser.js +232 -0
  74. package/dist/src/message-sender.d.ts +54 -0
  75. package/dist/src/message-sender.js +210 -0
  76. package/dist/src/monitor.d.ts +69 -0
  77. package/dist/src/monitor.js +1846 -0
  78. package/dist/src/onboarding.d.ts +8 -0
  79. package/dist/src/onboarding.js +248 -0
  80. package/dist/src/openclaw-compat.d.ts +148 -0
  81. package/dist/src/openclaw-compat.js +839 -0
  82. package/dist/src/proactive-markdown-send.d.ts +14 -0
  83. package/dist/src/proactive-markdown-send.js +205 -0
  84. package/dist/src/reqid-store.d.ts +23 -0
  85. package/dist/src/reqid-store.js +136 -0
  86. package/dist/src/runtime.d.ts +2 -0
  87. package/dist/src/runtime.js +7 -0
  88. package/dist/src/shared/command-auth.d.ts +23 -0
  89. package/dist/src/shared/command-auth.js +112 -0
  90. package/dist/src/shared/xml-parser.d.ts +46 -0
  91. package/dist/src/shared/xml-parser.js +228 -0
  92. package/dist/src/state-dir-resolve.d.ts +2 -0
  93. package/dist/src/state-dir-resolve.js +33 -0
  94. package/dist/src/state-manager.d.ts +115 -0
  95. package/dist/src/state-manager.js +413 -0
  96. package/dist/src/target.d.ts +35 -0
  97. package/dist/src/target.js +71 -0
  98. package/dist/src/template-card-manager.d.ts +55 -0
  99. package/dist/src/template-card-manager.js +316 -0
  100. package/dist/src/template-card-parser.d.ts +37 -0
  101. package/dist/src/template-card-parser.js +672 -0
  102. package/dist/src/timeout.d.ts +20 -0
  103. package/dist/src/timeout.js +57 -0
  104. package/dist/src/types/account.d.ts +29 -0
  105. package/dist/src/types/account.js +5 -0
  106. package/dist/src/types/config.d.ts +98 -0
  107. package/dist/src/types/config.js +8 -0
  108. package/dist/src/types/constants.d.ts +42 -0
  109. package/dist/src/types/constants.js +45 -0
  110. package/dist/src/types/index.d.ts +7 -0
  111. package/dist/src/types/index.js +17 -0
  112. package/dist/src/types/message.d.ts +238 -0
  113. package/dist/src/types/message.js +6 -0
  114. package/dist/src/utils.d.ts +148 -0
  115. package/dist/src/utils.js +92 -0
  116. package/dist/src/version.d.ts +2 -0
  117. package/dist/src/version.js +28 -0
  118. package/dist/src/webhook/command-auth.d.ts +47 -0
  119. package/dist/src/webhook/command-auth.js +137 -0
  120. package/dist/src/webhook/gateway.d.ts +36 -0
  121. package/dist/src/webhook/gateway.js +297 -0
  122. package/dist/src/webhook/handler.d.ts +19 -0
  123. package/dist/src/webhook/handler.js +481 -0
  124. package/dist/src/webhook/helpers.d.ts +157 -0
  125. package/dist/src/webhook/helpers.js +936 -0
  126. package/dist/src/webhook/http.d.ts +27 -0
  127. package/dist/src/webhook/http.js +168 -0
  128. package/dist/src/webhook/index.d.ts +11 -0
  129. package/dist/src/webhook/index.js +43 -0
  130. package/dist/src/webhook/media.d.ts +30 -0
  131. package/dist/src/webhook/media.js +152 -0
  132. package/dist/src/webhook/monitor.d.ts +59 -0
  133. package/dist/src/webhook/monitor.js +1672 -0
  134. package/dist/src/webhook/state.d.ts +220 -0
  135. package/dist/src/webhook/state.js +568 -0
  136. package/dist/src/webhook/target.d.ts +41 -0
  137. package/dist/src/webhook/target.js +165 -0
  138. package/dist/src/webhook/types.d.ts +348 -0
  139. package/dist/src/webhook/types.js +36 -0
  140. package/dist/src/webhook/video-frame.d.ts +13 -0
  141. package/dist/src/webhook/video-frame.js +108 -0
  142. package/openclaw.plugin.json +19 -0
  143. package/package.json +96 -0
  144. package/schema.json +534 -0
  145. package/scripts/generate-schema.mjs +33 -0
  146. package/skills/wecom-contact/SKILL.md +162 -0
  147. package/skills/wecom-doc/SKILL.md +162 -0
  148. package/skills/wecom-doc/references/create-doc.md +56 -0
  149. package/skills/wecom-doc/references/edit-doc-content.md +68 -0
  150. package/skills/wecom-doc/references/get-doc-content.md +88 -0
  151. package/skills/wecom-doc/references/smartpage-create.md +125 -0
  152. package/skills/wecom-doc/references/smartpage-export.md +160 -0
  153. package/skills/wecom-meeting/SKILL.md +441 -0
  154. package/skills/wecom-meeting/references/example-full.md +30 -0
  155. package/skills/wecom-meeting/references/example-reminder.md +46 -0
  156. package/skills/wecom-meeting/references/example-security.md +22 -0
  157. package/skills/wecom-meeting/references/response-get-meeting-info.md +148 -0
  158. package/skills/wecom-msg/SKILL.md +157 -0
  159. package/skills/wecom-msg/references/api-get-messages.md +93 -0
  160. package/skills/wecom-msg/references/api-get-msg-chat-list.md +58 -0
  161. package/skills/wecom-msg/references/api-get-msg-media.md +44 -0
  162. package/skills/wecom-msg/references/api-send-message.md +39 -0
  163. package/skills/wecom-preflight/SKILL.md +141 -0
  164. package/skills/wecom-schedule/SKILL.md +161 -0
  165. package/skills/wecom-schedule/references/api-check-availability.md +56 -0
  166. package/skills/wecom-schedule/references/api-create-schedule.md +38 -0
  167. package/skills/wecom-schedule/references/api-get-schedule-detail.md +81 -0
  168. package/skills/wecom-schedule/references/api-update-schedule.md +32 -0
  169. package/skills/wecom-schedule/references/ref-reminders.md +24 -0
  170. package/skills/wecom-send-media/SKILL.md +68 -0
  171. package/skills/wecom-send-template-card/SKILL.md +157 -0
  172. package/skills/wecom-send-template-card/references/api-template-card-types.md +358 -0
  173. package/skills/wecom-smartsheet/SKILL.md +164 -0
  174. package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +163 -0
  175. package/skills/wecom-smartsheet/references/smartsheet-field-types.md +44 -0
  176. package/skills/wecom-smartsheet/references/smartsheet-get-records.md +96 -0
  177. package/skills/wecom-smartsheet/references/webhook-examples.md +185 -0
  178. package/skills/wecom-smartsheet/references/webhook-fallback.md +184 -0
  179. package/skills/wecom-todo/SKILL.md +392 -0
  180. package/skills/wecom-todo/examples/workflows.md +163 -0
@@ -0,0 +1,702 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Streamable HTTP 传输层模块
4
+ *
5
+ * 负责:
6
+ * - MCP JSON-RPC over HTTP 通信(发送请求、解析响应)
7
+ * - Streamable HTTP session 生命周期管理(initialize 握手 → Mcp-Session-Id 维护 → 失效重建)
8
+ * - 自动检测无状态 Server:如果 initialize 响应未返回 Mcp-Session-Id,
9
+ * 则标记为无状态模式,后续请求跳过握手和 session 管理
10
+ * - SSE 流式响应解析
11
+ * - MCP 配置运行时缓存(通过 WSClient 拉取 URL 并缓存在内存中)
12
+ */
13
+ var __extends = (this && this.__extends) || (function () {
14
+ var extendStatics = function (d, b) {
15
+ extendStatics = Object.setPrototypeOf ||
16
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
17
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
18
+ return extendStatics(d, b);
19
+ };
20
+ return function (d, b) {
21
+ extendStatics(d, b);
22
+ function __() { this.constructor = d; }
23
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
24
+ };
25
+ })();
26
+ var __assign = (this && this.__assign) || function () {
27
+ __assign = Object.assign || function(t) {
28
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
29
+ s = arguments[i];
30
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
31
+ t[p] = s[p];
32
+ }
33
+ return t;
34
+ };
35
+ return __assign.apply(this, arguments);
36
+ };
37
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
38
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
39
+ return new (P || (P = Promise))(function (resolve, reject) {
40
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
41
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
42
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
43
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
44
+ });
45
+ };
46
+ var __generator = (this && this.__generator) || function (thisArg, body) {
47
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
48
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
49
+ function verb(n) { return function (v) { return step([n, v]); }; }
50
+ function step(op) {
51
+ if (f) throw new TypeError("Generator is already executing.");
52
+ while (_) try {
53
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
54
+ if (y = 0, t) op = [op[0] & 2, t.value];
55
+ switch (op[0]) {
56
+ case 0: case 1: t = op; break;
57
+ case 4: _.label++; return { value: op[1], done: false };
58
+ case 5: _.label++; y = op[1]; op = [0]; continue;
59
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
60
+ default:
61
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
62
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
63
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
64
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
65
+ if (t[2]) _.ops.pop();
66
+ _.trys.pop(); continue;
67
+ }
68
+ op = body.call(thisArg, _);
69
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
70
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
71
+ }
72
+ };
73
+ exports.__esModule = true;
74
+ exports.sendJsonRpc = exports.clearAccountCache = exports.clearCategoryCache = exports.resolveCurrentAccountId = exports.McpHttpError = exports.McpRpcError = exports.WECOM_USERID_HEADER = exports.MEDIA_DOWNLOAD_TIMEOUT_MS = void 0;
75
+ var aibot_node_sdk_1 = require("@wecom/aibot-node-sdk");
76
+ var undici_1 = require("undici");
77
+ var openclaw_compat_js_1 = require("../openclaw-compat.js");
78
+ var state_manager_js_1 = require("../state-manager.js");
79
+ var const_js_1 = require("../const.js");
80
+ var timeout_js_1 = require("../timeout.js");
81
+ var version_js_1 = require("../version.js");
82
+ var runtime_js_1 = require("../runtime.js");
83
+ var accounts_js_1 = require("../accounts.js");
84
+ // ============================================================================
85
+ // 内部状态
86
+ // ============================================================================
87
+ /** HTTP 请求超时时间(毫秒) */
88
+ var HTTP_REQUEST_TIMEOUT_MS = 30000;
89
+ /** 媒体下载请求超时时间(毫秒),base64 编码的媒体文件最大可达 ~27MB */
90
+ exports.MEDIA_DOWNLOAD_TIMEOUT_MS = 120000;
91
+ /** 日志前缀 */
92
+ var LOG_TAG = "[mcp]";
93
+ /** 请求 MCP Server 时透传可信企业微信 userid 的 header 名 */
94
+ exports.WECOM_USERID_HEADER = "x-openclaw-wecom-userid";
95
+ /**
96
+ * 构造 MCP 请求使用的 User-Agent
97
+ *
98
+ * 格式:`OpenClawPlugin/<version> <platform>/<arch>`
99
+ * 例如:`OpenClawPlugin/0.1.3 linux/x86_64`
100
+ *
101
+ * 说明:
102
+ * - version: 取自 package.json 的 PLUGIN_VERSION
103
+ * - platform: process.platform(linux / darwin / win32 ...)
104
+ * - arch: 将 Node 的 `x64` 归一化为传统 Unix 风格 `x86_64`,其他架构原样返回
105
+ */
106
+ function buildUserAgent() {
107
+ var _a;
108
+ var archMap = {
109
+ x64: "x86_64",
110
+ ia32: "i386"
111
+ };
112
+ var arch = (_a = archMap[process.arch]) !== null && _a !== void 0 ? _a : process.arch;
113
+ return "OpenClawPlugin/" + version_js_1.PLUGIN_VERSION + " " + process.platform + "/" + arch;
114
+ }
115
+ var MCP_USER_AGENT = buildUserAgent();
116
+ /**
117
+ * MCP JSON-RPC 错误
118
+ *
119
+ * 携带服务端返回的 JSON-RPC error.code,
120
+ * 用于上层按错误码进行差异化处理(如特定错误码触发缓存清理)。
121
+ */
122
+ var McpRpcError = /** @class */ (function (_super) {
123
+ __extends(McpRpcError, _super);
124
+ function McpRpcError(code, message, data) {
125
+ var _this = _super.call(this, message) || this;
126
+ _this.code = code;
127
+ _this.data = data;
128
+ _this.name = "McpRpcError";
129
+ return _this;
130
+ }
131
+ return McpRpcError;
132
+ }(Error));
133
+ exports.McpRpcError = McpRpcError;
134
+ /**
135
+ * MCP HTTP 错误
136
+ *
137
+ * 携带 HTTP 状态码,用于精确判断 session 失效(404)等场景,
138
+ * 避免通过字符串匹配 "404" 导致的误判。
139
+ */
140
+ var McpHttpError = /** @class */ (function (_super) {
141
+ __extends(McpHttpError, _super);
142
+ function McpHttpError(statusCode, message) {
143
+ var _this = _super.call(this, message) || this;
144
+ _this.statusCode = statusCode;
145
+ _this.name = "McpHttpError";
146
+ return _this;
147
+ }
148
+ return McpHttpError;
149
+ }(Error));
150
+ exports.McpHttpError = McpHttpError;
151
+ /**
152
+ * 需要清理缓存的 JSON-RPC 错误码集合
153
+ *
154
+ * 当 MCP Server 返回以下错误码时,说明服务端状态已发生变化(如配置变更、
155
+ * 服务重启等),需要清理对应 category 的全部缓存,确保下次请求重新
156
+ * 拉取配置并重建会话。
157
+ *
158
+ * - -32001: 服务不可用(Server Unavailable)
159
+ * - -32002: 配置已变更(Config Changed)
160
+ * - -32003: 认证失败(Auth Failed)
161
+ */
162
+ var CACHE_CLEAR_ERROR_CODES = new Set([-32001, -32002, -32003]);
163
+ /**
164
+ * 生成多账号感知的缓存 key
165
+ *
166
+ * 不同账号的同一 category 对应不同的 MCP Server(URL、凭据均不同),
167
+ * 必须用 accountId:category 的复合键隔离,避免跨账号缓存污染。
168
+ */
169
+ function cacheKey(accountId, category) {
170
+ return accountId + ":" + category;
171
+ }
172
+ /** MCP 配置缓存:accountId:category → response.body(完整配置) */
173
+ var mcpConfigCache = new Map();
174
+ /** Streamable HTTP 会话缓存:accountId:category → session */
175
+ var mcpSessionCache = new Map();
176
+ /** 已确认为无状态的 MCP Server 集合(跳过后续握手),key 为 accountId:category */
177
+ var statelessCategories = new Set();
178
+ /** 正在进行中的 initialize 请求(防止并发重复初始化),key 为 accountId:category */
179
+ var inflightInitRequests = new Map();
180
+ // ============================================================================
181
+ // MCP 配置拉取与缓存
182
+ // ============================================================================
183
+ /**
184
+ * 判断账户是否为长连接机器人(通过 botId + secret 配置)
185
+ */
186
+ function isWebSocketBot(cfg, accountId) {
187
+ var _a, _b;
188
+ var resolved = accounts_js_1.resolveWeComAccountMulti({ cfg: cfg, accountId: accountId });
189
+ return Boolean(((_a = resolved.botId) === null || _a === void 0 ? void 0 : _a.trim()) && ((_b = resolved.secret) === null || _b === void 0 ? void 0 : _b.trim()));
190
+ }
191
+ /**
192
+ * 解析用于 MCP 调用的账户 ID
193
+ *
194
+ * 优先级:
195
+ * 1. 默认账户(如果是长连接机器人)
196
+ * 2. 第一个长连接机器人账户
197
+ * 3. 无可用账户时返回 null
198
+ */
199
+ function resolveMcpAccountId(cfg) {
200
+ var defaultAccountId = accounts_js_1.resolveDefaultWeComAccountId(cfg);
201
+ // 优先使用默认账户
202
+ if (isWebSocketBot(cfg, defaultAccountId)) {
203
+ return defaultAccountId;
204
+ }
205
+ // 默认账户非长连接,查找第一个长连接账户
206
+ var allIds = accounts_js_1.listWeComAccountIds(cfg);
207
+ for (var _i = 0, allIds_1 = allIds; _i < allIds_1.length; _i++) {
208
+ var id = allIds_1[_i];
209
+ if (id !== defaultAccountId && isWebSocketBot(cfg, id)) {
210
+ console.log(LOG_TAG + " \u9ED8\u8BA4\u8D26\u6237 \"" + defaultAccountId + "\" \u975E\u957F\u8FDE\u63A5\u6A21\u5F0F\uFF0C\u4F7F\u7528\u8D26\u6237 \"" + id + "\" \u83B7\u53D6 MCP \u914D\u7F6E");
211
+ return id;
212
+ }
213
+ }
214
+ return null;
215
+ }
216
+ /**
217
+ * 根据配置解析当前用于 MCP 的账户 ID
218
+ *
219
+ * 通过 PluginRuntime 读取全局配置,按以下优先级选择账户:
220
+ * 1. 默认账户(如果配置了 botId + secret)
221
+ * 2. 第一个配置了 botId + secret 的长连接账户
222
+ * 3. 无可用长连接账户时回退到默认账户(会导致后续 WSClient 获取失败)
223
+ */
224
+ function resolveCurrentAccountId() {
225
+ try {
226
+ var core = runtime_js_1.getWeComRuntime();
227
+ var cfg = core.config.loadConfig();
228
+ var mcpAccountId = resolveMcpAccountId(cfg);
229
+ if (mcpAccountId) {
230
+ return mcpAccountId;
231
+ }
232
+ // 无长连接账户,给出友好提示
233
+ console.warn(LOG_TAG + " \u672A\u627E\u5230\u957F\u8FDE\u63A5\u6A21\u5F0F\u7684\u673A\u5668\u4EBA\u8D26\u6237\uFF08\u9700\u914D\u7F6E botId + secret\uFF09\uFF0CMCP \u529F\u80FD\u4E0D\u53EF\u7528");
234
+ return accounts_js_1.resolveDefaultWeComAccountId(cfg);
235
+ }
236
+ catch (_a) {
237
+ // runtime 未初始化时回退到 "default"
238
+ return openclaw_compat_js_1.DEFAULT_ACCOUNT_ID;
239
+ }
240
+ }
241
+ exports.resolveCurrentAccountId = resolveCurrentAccountId;
242
+ /**
243
+ * 通过 WSClient 拉取指定 category 的 MCP 完整配置
244
+ *
245
+ * @param accountId - 账户 ID,决定使用哪个 WSClient
246
+ * @param category - MCP 品类名称,如 doc、contact
247
+ * @returns 完整的 response.body 配置对象(至少包含 url 字段)
248
+ */
249
+ function fetchMcpConfig(accountId, category) {
250
+ var _a;
251
+ return __awaiter(this, void 0, void 0, function () {
252
+ var wsClient, reqId, response, errMsg, body;
253
+ return __generator(this, function (_b) {
254
+ switch (_b.label) {
255
+ case 0:
256
+ wsClient = state_manager_js_1.getWeComWebSocket(accountId);
257
+ if (!wsClient) {
258
+ throw new Error("WSClient \u672A\u8FDE\u63A5 (accountId=\"" + accountId + "\")\uFF0C\u65E0\u6CD5\u62C9\u53D6 MCP \u914D\u7F6E");
259
+ }
260
+ reqId = aibot_node_sdk_1.generateReqId("mcp_config");
261
+ return [4 /*yield*/, timeout_js_1.withTimeout(wsClient.reply({ headers: { req_id: reqId } }, { biz_type: category, plugin_version: version_js_1.PLUGIN_VERSION }, const_js_1.MCP_GET_CONFIG_CMD), const_js_1.MCP_CONFIG_FETCH_TIMEOUT_MS, "MCP config fetch for \"" + category + "\" timed out after " + const_js_1.MCP_CONFIG_FETCH_TIMEOUT_MS + "ms")];
262
+ case 1:
263
+ response = _b.sent();
264
+ if (response.errcode !== undefined && response.errcode !== 0) {
265
+ errMsg = "MCP \u914D\u7F6E\u8BF7\u6C42\u5931\u8D25: errcode=" + response.errcode + ", errmsg=" + ((_a = response.errmsg) !== null && _a !== void 0 ? _a : "unknown");
266
+ console.error(LOG_TAG + " " + errMsg);
267
+ throw new Error(errMsg);
268
+ }
269
+ body = response.body;
270
+ if (!(body === null || body === void 0 ? void 0 : body.url)) {
271
+ throw new Error("MCP \u914D\u7F6E\u54CD\u5E94\u7F3A\u5C11 url \u5B57\u6BB5 (category=\"" + category + "\")");
272
+ }
273
+ console.log(LOG_TAG + " \u914D\u7F6E\u62C9\u53D6\u6210\u529F (accountId=\"" + accountId + "\", category=\"" + category + "\")");
274
+ return [2 /*return*/, body];
275
+ }
276
+ });
277
+ });
278
+ }
279
+ /**
280
+ * 获取指定品类的 MCP Server URL
281
+ *
282
+ * 优先从内存缓存中读取,未命中时通过 WSClient 拉取并缓存。
283
+ *
284
+ * @param accountId - 账户 ID
285
+ * @param category - MCP 品类名称
286
+ * @returns MCP Server URL
287
+ */
288
+ function getMcpUrl(accountId, category) {
289
+ return __awaiter(this, void 0, void 0, function () {
290
+ var key, cached, body;
291
+ return __generator(this, function (_a) {
292
+ switch (_a.label) {
293
+ case 0:
294
+ key = cacheKey(accountId, category);
295
+ cached = mcpConfigCache.get(key);
296
+ if (cached)
297
+ return [2 /*return*/, cached.url];
298
+ return [4 /*yield*/, fetchMcpConfig(accountId, category)];
299
+ case 1:
300
+ body = _a.sent();
301
+ // 写入缓存
302
+ mcpConfigCache.set(key, body);
303
+ console.log(LOG_TAG + " getMcpUrl " + accountId + "/" + category + ": " + body.url);
304
+ return [2 /*return*/, body.url];
305
+ }
306
+ });
307
+ });
308
+ }
309
+ // ============================================================================
310
+ // HTTP 底层通信
311
+ // ============================================================================
312
+ /**
313
+ * 发送原始 HTTP 请求到 MCP Server(底层方法)
314
+ *
315
+ * 自动携带 Mcp-Session-Id 请求头(如果有),
316
+ * 并从响应头中更新 sessionId。
317
+ */
318
+ function sendRawJsonRpc(url, session, body, timeoutMs, requesterUserId) {
319
+ var _a, _b;
320
+ if (timeoutMs === void 0) { timeoutMs = HTTP_REQUEST_TIMEOUT_MS; }
321
+ return __awaiter(this, void 0, void 0, function () {
322
+ var controller, timeoutId, headers, normalizedRequesterUserId, response, err_1, newSessionId, contentLength, contentType, _c, text, rpc;
323
+ return __generator(this, function (_d) {
324
+ switch (_d.label) {
325
+ case 0:
326
+ controller = new AbortController();
327
+ timeoutId = setTimeout(function () { return controller.abort(); }, timeoutMs);
328
+ headers = {
329
+ "Content-Type": "application/json",
330
+ Accept: "application/json, text/event-stream",
331
+ "User-Agent": MCP_USER_AGENT
332
+ };
333
+ // Streamable HTTP:携带会话 ID
334
+ if (session.sessionId) {
335
+ headers["Mcp-Session-Id"] = session.sessionId;
336
+ }
337
+ normalizedRequesterUserId = requesterUserId === null || requesterUserId === void 0 ? void 0 : requesterUserId.trim();
338
+ if (normalizedRequesterUserId) {
339
+ headers[exports.WECOM_USERID_HEADER] = normalizedRequesterUserId;
340
+ }
341
+ console.log(LOG_TAG + " sendRawJsonRpc \u2192 " + body.method + " | " + exports.WECOM_USERID_HEADER + ": " + ((_a = headers[exports.WECOM_USERID_HEADER]) !== null && _a !== void 0 ? _a : "(not set)"));
342
+ _d.label = 1;
343
+ case 1:
344
+ _d.trys.push([1, 3, 4, 5]);
345
+ return [4 /*yield*/, undici_1.fetch(url, {
346
+ method: "POST",
347
+ headers: headers,
348
+ body: JSON.stringify(body),
349
+ signal: controller.signal
350
+ })];
351
+ case 2:
352
+ // 使用 undici 提供的 fetch,规避 Node 18.0–18.17 原生 fetch 无法自定义 User-Agent 的 bug;
353
+ // undici 是项目已有依赖,且在所有支持的 Node 版本上行为一致。
354
+ response = (_d.sent());
355
+ return [3 /*break*/, 5];
356
+ case 3:
357
+ err_1 = _d.sent();
358
+ if (err_1 instanceof DOMException && err_1.name === "AbortError") {
359
+ throw new Error("MCP \u8BF7\u6C42\u8D85\u65F6 (" + timeoutMs + "ms)");
360
+ }
361
+ throw new Error("MCP \u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25: " + (err_1 instanceof Error ? err_1.message : String(err_1)));
362
+ case 4:
363
+ clearTimeout(timeoutId);
364
+ return [7 /*endfinally*/];
365
+ case 5:
366
+ newSessionId = response.headers.get("mcp-session-id");
367
+ if (!response.ok) {
368
+ throw new McpHttpError(response.status, "MCP HTTP \u8BF7\u6C42\u5931\u8D25: " + response.status + " " + response.statusText);
369
+ }
370
+ contentLength = response.headers.get("content-length");
371
+ if (response.status === 204 || contentLength === "0") {
372
+ return [2 /*return*/, { response: response, rpcResult: undefined, newSessionId: newSessionId }];
373
+ }
374
+ contentType = (_b = response.headers.get("content-type")) !== null && _b !== void 0 ? _b : "";
375
+ if (!contentType.includes("text/event-stream")) return [3 /*break*/, 7];
376
+ _c = { response: response };
377
+ return [4 /*yield*/, parseSseResponse(response)];
378
+ case 6: return [2 /*return*/, (_c.rpcResult = _d.sent(), _c.newSessionId = newSessionId, _c)];
379
+ case 7: return [4 /*yield*/, response.text()];
380
+ case 8:
381
+ text = _d.sent();
382
+ if (!text.trim()) {
383
+ return [2 /*return*/, { response: response, rpcResult: undefined, newSessionId: newSessionId }];
384
+ }
385
+ rpc = JSON.parse(text);
386
+ if (rpc.error) {
387
+ throw new McpRpcError(rpc.error.code, "MCP \u8C03\u7528\u9519\u8BEF [" + rpc.error.code + "]: " + rpc.error.message, rpc.error.data);
388
+ }
389
+ return [2 /*return*/, { response: response, rpcResult: rpc.result, newSessionId: newSessionId }];
390
+ }
391
+ });
392
+ });
393
+ }
394
+ // ============================================================================
395
+ // Session 管理
396
+ // ============================================================================
397
+ /**
398
+ * 对指定 URL 执行 Streamable HTTP 的 initialize 握手
399
+ *
400
+ * 发送 initialize → 接收 serverInfo → 发送 initialized 通知。
401
+ * 如果服务端未返回 Mcp-Session-Id,则标记为无状态模式,后续请求跳过 session 管理。
402
+ */
403
+ function initializeSession(url, accountId, category, requesterUserId) {
404
+ return __awaiter(this, void 0, void 0, function () {
405
+ var key, session, initBody, initSessionId, notifyBody, notifySessionId;
406
+ return __generator(this, function (_a) {
407
+ switch (_a.label) {
408
+ case 0:
409
+ key = cacheKey(accountId, category);
410
+ session = { sessionId: null, initialized: false, stateless: false };
411
+ console.log(LOG_TAG + " \u5F00\u59CB initialize \u63E1\u624B (accountId=\"" + accountId + "\", category=\"" + category + "\")");
412
+ initBody = {
413
+ jsonrpc: "2.0",
414
+ id: aibot_node_sdk_1.generateReqId("mcp_init"),
415
+ method: "initialize",
416
+ params: {
417
+ protocolVersion: "2025-03-26",
418
+ capabilities: {},
419
+ clientInfo: { name: "wecom_mcp", version: "1.0.0" }
420
+ }
421
+ };
422
+ return [4 /*yield*/, sendRawJsonRpc(url, session, initBody, HTTP_REQUEST_TIMEOUT_MS, requesterUserId)];
423
+ case 1:
424
+ initSessionId = (_a.sent()).newSessionId;
425
+ // 用返回的 newSessionId 更新 session(不再依赖副作用修改)
426
+ if (initSessionId) {
427
+ session.sessionId = initSessionId;
428
+ }
429
+ // 检查服务端是否返回了 Mcp-Session-Id
430
+ // 如果没有返回,说明该 Server 是无状态实现,无需维护 session
431
+ if (!session.sessionId) {
432
+ session.stateless = true;
433
+ session.initialized = true;
434
+ statelessCategories.add(key);
435
+ mcpSessionCache.set(key, session);
436
+ console.log(LOG_TAG + " \u65E0\u72B6\u6001 Server \u786E\u8BA4 (accountId=\"" + accountId + "\", category=\"" + category + "\")");
437
+ return [2 /*return*/, session];
438
+ }
439
+ notifyBody = {
440
+ jsonrpc: "2.0",
441
+ method: "notifications/initialized"
442
+ };
443
+ return [4 /*yield*/, sendRawJsonRpc(url, session, notifyBody, HTTP_REQUEST_TIMEOUT_MS, requesterUserId)];
444
+ case 2:
445
+ notifySessionId = (_a.sent()).newSessionId;
446
+ // 如果 initialized 通知的响应也携带了 sessionId,以最新的为准
447
+ if (notifySessionId) {
448
+ session.sessionId = notifySessionId;
449
+ }
450
+ session.initialized = true;
451
+ mcpSessionCache.set(key, session);
452
+ console.log(LOG_TAG + " \u6709\u72B6\u6001 Session \u5EFA\u7ACB\u6210\u529F (accountId=\"" + accountId + "\", category=\"" + category + "\", sessionId=\"" + session.sessionId + "\")");
453
+ return [2 /*return*/, session];
454
+ }
455
+ });
456
+ });
457
+ }
458
+ /**
459
+ * 获取或创建指定 URL 的 MCP 会话
460
+ *
461
+ * - 已确认无状态的 category:直接返回空 session,跳过握手
462
+ * - 已有可用有状态会话:直接返回缓存
463
+ * - 其他情况:执行 initialize 握手,并发请求会被合并
464
+ */
465
+ function getOrCreateSession(url, accountId, category, requesterUserId) {
466
+ return __awaiter(this, void 0, void 0, function () {
467
+ var key, cached_1, cached, inflight, promise;
468
+ return __generator(this, function (_a) {
469
+ key = cacheKey(accountId, category);
470
+ // 已确认为无状态的 Server,直接返回空 session 跳过握手
471
+ if (statelessCategories.has(key)) {
472
+ cached_1 = mcpSessionCache.get(key);
473
+ if (cached_1)
474
+ return [2 /*return*/, cached_1];
475
+ // 首次发现被清除(理论上不会走到这里),重新走握手探测
476
+ }
477
+ cached = mcpSessionCache.get(key);
478
+ if (cached === null || cached === void 0 ? void 0 : cached.initialized)
479
+ return [2 /*return*/, cached];
480
+ inflight = inflightInitRequests.get(key);
481
+ if (inflight)
482
+ return [2 /*return*/, inflight];
483
+ promise = initializeSession(url, accountId, category, requesterUserId)["finally"](function () {
484
+ inflightInitRequests["delete"](key);
485
+ });
486
+ inflightInitRequests.set(key, promise);
487
+ return [2 /*return*/, promise];
488
+ });
489
+ });
490
+ }
491
+ // ============================================================================
492
+ // SSE 解析
493
+ // ============================================================================
494
+ /**
495
+ * 解析 SSE 流式响应,提取最终的 JSON-RPC result
496
+ *
497
+ * 按照 SSE 规范,同一事件中的多个 `data:` 行会用换行符拼接。
498
+ * 空行分隔不同事件,取最后一个完整事件的数据。
499
+ */
500
+ function parseSseResponse(response) {
501
+ return __awaiter(this, void 0, void 0, function () {
502
+ var text, lines, currentDataParts, lastEventData, _i, lines_1, line, rpc;
503
+ return __generator(this, function (_a) {
504
+ switch (_a.label) {
505
+ case 0: return [4 /*yield*/, response.text()];
506
+ case 1:
507
+ text = _a.sent();
508
+ lines = text.split("\n");
509
+ currentDataParts = [];
510
+ lastEventData = "";
511
+ for (_i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
512
+ line = lines_1[_i];
513
+ if (line.startsWith("data: ")) {
514
+ currentDataParts.push(line.slice(6));
515
+ }
516
+ else if (line.startsWith("data:")) {
517
+ // data: 后无空格时,值为空字符串
518
+ currentDataParts.push(line.slice(5));
519
+ }
520
+ else if (line.trim() === "" && currentDataParts.length > 0) {
521
+ // 空行表示事件结束,拼接所有 data 行
522
+ lastEventData = currentDataParts.join("\n").trim();
523
+ currentDataParts = [];
524
+ }
525
+ }
526
+ // 处理最后一个未以空行结尾的事件
527
+ if (currentDataParts.length > 0) {
528
+ lastEventData = currentDataParts.join("\n").trim();
529
+ }
530
+ if (!lastEventData) {
531
+ throw new Error("SSE 响应中未包含有效数据");
532
+ }
533
+ try {
534
+ rpc = JSON.parse(lastEventData);
535
+ if (rpc.error) {
536
+ throw new McpRpcError(rpc.error.code, "MCP \u8C03\u7528\u9519\u8BEF [" + rpc.error.code + "]: " + rpc.error.message, rpc.error.data);
537
+ }
538
+ return [2 /*return*/, rpc.result];
539
+ }
540
+ catch (err) {
541
+ if (err instanceof SyntaxError) {
542
+ throw new Error("SSE \u54CD\u5E94\u89E3\u6790\u5931\u8D25: " + lastEventData.slice(0, 200));
543
+ }
544
+ throw err;
545
+ }
546
+ return [2 /*return*/];
547
+ }
548
+ });
549
+ });
550
+ }
551
+ // ============================================================================
552
+ // 公共 API
553
+ // ============================================================================
554
+ /**
555
+ * 清理指定账户+品类的所有 MCP 缓存(配置、会话、无状态标记)
556
+ *
557
+ * 当 MCP Server 返回特定错误码时调用,确保下次请求重新拉取配置并重建会话。
558
+ *
559
+ * @param accountId - 账户 ID
560
+ * @param category - MCP 品类名称
561
+ */
562
+ function clearCategoryCache(accountId, category) {
563
+ var key = cacheKey(accountId, category);
564
+ console.log(LOG_TAG + " \u6E05\u7406\u7F13\u5B58 (accountId=\"" + accountId + "\", category=\"" + category + "\")");
565
+ mcpConfigCache["delete"](key);
566
+ mcpSessionCache["delete"](key);
567
+ statelessCategories["delete"](key);
568
+ inflightInitRequests["delete"](key);
569
+ }
570
+ exports.clearCategoryCache = clearCategoryCache;
571
+ /**
572
+ * 清理指定账户下所有品类的 MCP 缓存
573
+ *
574
+ * 适用于账户掉线、凭据变更等需要整体清理的场景。
575
+ *
576
+ * @param accountId - 账户 ID
577
+ */
578
+ function clearAccountCache(accountId) {
579
+ var prefix = accountId + ":";
580
+ console.log(LOG_TAG + " \u6E05\u7406\u8D26\u6237\u6240\u6709\u7F13\u5B58 (accountId=\"" + accountId + "\")");
581
+ for (var _i = 0, _a = mcpConfigCache.keys(); _i < _a.length; _i++) {
582
+ var key = _a[_i];
583
+ if (key.startsWith(prefix))
584
+ mcpConfigCache["delete"](key);
585
+ }
586
+ for (var _b = 0, _c = mcpSessionCache.keys(); _b < _c.length; _b++) {
587
+ var key = _c[_b];
588
+ if (key.startsWith(prefix))
589
+ mcpSessionCache["delete"](key);
590
+ }
591
+ for (var _d = 0, statelessCategories_1 = statelessCategories; _d < statelessCategories_1.length; _d++) {
592
+ var key = statelessCategories_1[_d];
593
+ if (key.startsWith(prefix))
594
+ statelessCategories["delete"](key);
595
+ }
596
+ for (var _e = 0, _f = inflightInitRequests.keys(); _e < _f.length; _e++) {
597
+ var key = _f[_e];
598
+ if (key.startsWith(prefix))
599
+ inflightInitRequests["delete"](key);
600
+ }
601
+ }
602
+ exports.clearAccountCache = clearAccountCache;
603
+ /**
604
+ * 发送 JSON-RPC 请求到 MCP Server(Streamable HTTP 协议)
605
+ *
606
+ * 自动管理 session 生命周期:
607
+ * - 无状态 Server:跳过 session 管理,直接发送请求
608
+ * - 有状态 Server:首次调用先执行 initialize 握手,session 失效(404)时自动重建并重试
609
+ *
610
+ * accountId 优先使用 options.accountId(由工具工厂从 ctx.agentAccountId 传入),
611
+ * 未提供时 fallback 到 resolveCurrentAccountId()。解析结果贯穿整条调用链,避免跨账号污染。
612
+ *
613
+ * @param category - MCP 品类名称
614
+ * @param method - JSON-RPC 方法名
615
+ * @param params - JSON-RPC 参数
616
+ * @param options - 可选配置(如自定义超时、指定账户)
617
+ * @returns JSON-RPC result
618
+ */
619
+ function sendJsonRpc(category, method, params, options) {
620
+ var _a;
621
+ return __awaiter(this, void 0, void 0, function () {
622
+ var accountId, key, url, timeoutMs, requesterUserId, body, session, _b, rpcResult, newSessionId, err_2, _c, rpcResult, newSessionId;
623
+ return __generator(this, function (_d) {
624
+ switch (_d.label) {
625
+ case 0:
626
+ accountId = ((_a = options === null || options === void 0 ? void 0 : options.accountId) === null || _a === void 0 ? void 0 : _a.trim()) || resolveCurrentAccountId();
627
+ key = cacheKey(accountId, category);
628
+ return [4 /*yield*/, getMcpUrl(accountId, category)];
629
+ case 1:
630
+ url = _d.sent();
631
+ timeoutMs = options === null || options === void 0 ? void 0 : options.timeoutMs;
632
+ requesterUserId = options === null || options === void 0 ? void 0 : options.requesterUserId;
633
+ body = __assign({ jsonrpc: "2.0", id: aibot_node_sdk_1.generateReqId("mcp_rpc"), method: method }, (params !== undefined ? { params: params } : {}));
634
+ return [4 /*yield*/, getOrCreateSession(url, accountId, category, requesterUserId)];
635
+ case 2:
636
+ session = _d.sent();
637
+ _d.label = 3;
638
+ case 3:
639
+ _d.trys.push([3, 5, , 9]);
640
+ return [4 /*yield*/, sendRawJsonRpc(url, session, body, timeoutMs, requesterUserId)];
641
+ case 4:
642
+ _b = _d.sent(), rpcResult = _b.rpcResult, newSessionId = _b.newSessionId;
643
+ // 用最新的 sessionId 更新 session
644
+ if (newSessionId) {
645
+ session.sessionId = newSessionId;
646
+ }
647
+ return [2 /*return*/, rpcResult];
648
+ case 5:
649
+ err_2 = _d.sent();
650
+ // 特定 JSON-RPC 错误码触发缓存清理(统一在传输层处理,上层无需关心)
651
+ if (err_2 instanceof McpRpcError && CACHE_CLEAR_ERROR_CODES.has(err_2.code)) {
652
+ clearCategoryCache(accountId, category);
653
+ }
654
+ // 无状态 Server 不存在 session 失效问题,直接抛出错误
655
+ if (session.stateless)
656
+ throw err_2;
657
+ if (!(err_2 instanceof McpHttpError && err_2.statusCode === 404)) return [3 /*break*/, 8];
658
+ console.log(LOG_TAG + " Session \u5931\u6548 (accountId=\"" + accountId + "\", category=\"" + category + "\")\uFF0C\u5F00\u59CB\u91CD\u5EFA...");
659
+ mcpSessionCache["delete"](key);
660
+ return [4 /*yield*/, rebuildSession(url, accountId, category, requesterUserId)];
661
+ case 6:
662
+ // 使用 rebuildSession 合并并发的 session 重建请求,避免竞态条件
663
+ session = _d.sent();
664
+ return [4 /*yield*/, sendRawJsonRpc(url, session, body, timeoutMs, requesterUserId)];
665
+ case 7:
666
+ _c = _d.sent(), rpcResult = _c.rpcResult, newSessionId = _c.newSessionId;
667
+ if (newSessionId) {
668
+ session.sessionId = newSessionId;
669
+ }
670
+ return [2 /*return*/, rpcResult];
671
+ case 8:
672
+ // 其他错误记录日志后抛出
673
+ console.error(LOG_TAG + " RPC \u8BF7\u6C42\u5931\u8D25 (accountId=\"" + accountId + "\", category=\"" + category + "\", method=\"" + method + "\"): " + (err_2 instanceof Error ? err_2.message : String(err_2)));
674
+ throw err_2;
675
+ case 9: return [2 /*return*/];
676
+ }
677
+ });
678
+ });
679
+ }
680
+ exports.sendJsonRpc = sendJsonRpc;
681
+ /**
682
+ * 合并并发的 session 重建请求
683
+ *
684
+ * 与 getOrCreateSession 类似,使用 inflightInitRequests 防止
685
+ * 多个并发请求同时遇到 404 时重复执行 initialize 握手。
686
+ */
687
+ function rebuildSession(url, accountId, category, requesterUserId) {
688
+ return __awaiter(this, void 0, void 0, function () {
689
+ var key, inflight, promise;
690
+ return __generator(this, function (_a) {
691
+ key = cacheKey(accountId, category);
692
+ inflight = inflightInitRequests.get(key);
693
+ if (inflight)
694
+ return [2 /*return*/, inflight];
695
+ promise = initializeSession(url, accountId, category, requesterUserId)["finally"](function () {
696
+ inflightInitRequests["delete"](key);
697
+ });
698
+ inflightInitRequests.set(key, promise);
699
+ return [2 /*return*/, promise];
700
+ });
701
+ });
702
+ }