@wecom/wecom-openclaw-plugin 2026.4.2 → 2026.4.3-beta.0
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 +395 -10
- package/dist/index.d.ts +2 -4
- package/dist/index.js +58 -0
- package/dist/src/accounts.d.ts +57 -0
- package/dist/src/accounts.js +222 -0
- package/dist/src/agent/api-client.d.ts +94 -0
- package/dist/src/agent/api-client.js +292 -0
- package/dist/src/agent/handler.d.ts +63 -0
- package/dist/src/agent/handler.js +551 -0
- package/dist/src/agent/index.d.ts +5 -0
- package/dist/src/agent/index.js +5 -0
- package/dist/src/agent/webhook.d.ts +24 -0
- package/dist/src/agent/webhook.js +228 -0
- package/dist/src/agent/xml.d.ts +21 -0
- package/dist/src/agent/xml.js +41 -0
- package/dist/src/channel.js +579 -0
- package/dist/src/chat-queue.d.ts +31 -0
- package/dist/src/chat-queue.js +45 -0
- package/dist/{esm/types/src → src}/const.d.ts +46 -0
- package/dist/{esm/src → src}/const.js +77 -30
- package/dist/{esm/src → src}/dm-policy.js +6 -9
- package/dist/src/dynamic-agent.d.ts +37 -0
- package/dist/src/dynamic-agent.js +60 -0
- package/dist/src/dynamic-routing.d.ts +65 -0
- package/dist/src/dynamic-routing.js +58 -0
- package/dist/{esm/src → src}/group-policy.js +8 -22
- package/dist/src/http.d.ts +26 -0
- package/dist/src/http.js +93 -0
- package/dist/{esm/types/src → src}/interface.d.ts +0 -2
- package/dist/src/interface.js +4 -0
- package/dist/src/mcp/index.js +6 -0
- package/dist/{esm/src → src}/mcp/interceptors/biz-error.js +2 -6
- package/dist/{esm/src → src}/mcp/interceptors/index.js +6 -10
- package/dist/{esm/src → src}/mcp/interceptors/msg-media.js +6 -10
- package/dist/{esm/src → src}/mcp/interceptors/smartpage-create.js +2 -6
- package/dist/{esm/src → src}/mcp/interceptors/smartpage-export.js +2 -6
- package/dist/src/mcp/interceptors/types.js +7 -0
- package/dist/{esm/src → src}/mcp/schema.js +1 -4
- package/dist/{esm/src → src}/mcp/tool.js +4 -8
- package/dist/{esm/src → src}/mcp/transport.js +15 -16
- package/dist/{esm/src → src}/media-handler.js +6 -10
- package/dist/{esm/src → src}/media-uploader.js +64 -10
- package/dist/{esm/src → src}/message-parser.js +1 -4
- package/dist/{esm/types/src → src}/message-sender.d.ts +18 -0
- package/dist/{esm/src → src}/message-sender.js +45 -11
- package/dist/{esm/src → src}/monitor.js +145 -292
- package/dist/{esm/src → src}/onboarding.js +22 -26
- package/dist/{esm/types/src → src}/openclaw-compat.d.ts +49 -0
- package/dist/{esm/src → src}/openclaw-compat.js +133 -27
- package/dist/{esm/src → src}/reqid-store.js +4 -7
- package/dist/{esm/src → src}/runtime.js +2 -5
- package/dist/src/shared/command-auth.d.ts +23 -0
- package/dist/src/shared/command-auth.js +73 -0
- package/dist/src/shared/xml-parser.d.ts +46 -0
- package/dist/src/shared/xml-parser.js +210 -0
- package/dist/{esm/src → src}/state-dir-resolve.js +3 -7
- package/dist/{esm/src → src}/state-manager.js +84 -16
- package/dist/src/target.d.ts +35 -0
- package/dist/src/target.js +67 -0
- package/dist/src/template-card-manager.d.ts +55 -0
- package/dist/src/template-card-manager.js +205 -0
- package/dist/{esm/src → src}/template-card-parser.js +17 -8
- package/dist/{esm/src → src}/timeout.js +2 -5
- package/dist/src/types/account.d.ts +29 -0
- package/dist/src/types/account.js +4 -0
- package/dist/src/types/config.d.ts +91 -0
- package/dist/src/types/config.js +7 -0
- package/dist/src/types/constants.d.ts +42 -0
- package/dist/src/types/constants.js +42 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.js +5 -0
- package/dist/src/types/message.d.ts +238 -0
- package/dist/src/types/message.js +5 -0
- package/dist/{esm/types/src → src}/utils.d.ts +41 -0
- package/dist/{esm/src → src}/utils.js +24 -10
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.js +24 -0
- package/dist/src/webhook/command-auth.d.ts +47 -0
- package/dist/src/webhook/command-auth.js +96 -0
- package/dist/src/webhook/gateway.d.ts +36 -0
- package/dist/src/webhook/gateway.js +235 -0
- package/dist/src/webhook/handler.d.ts +18 -0
- package/dist/src/webhook/handler.js +420 -0
- package/dist/src/webhook/helpers.d.ts +156 -0
- package/dist/src/webhook/helpers.js +833 -0
- package/dist/src/webhook/http.d.ts +26 -0
- package/dist/src/webhook/http.js +94 -0
- package/dist/src/webhook/index.d.ts +11 -0
- package/dist/src/webhook/index.js +14 -0
- package/dist/src/webhook/media.d.ts +29 -0
- package/dist/src/webhook/media.js +88 -0
- package/dist/src/webhook/monitor.d.ts +59 -0
- package/dist/src/webhook/monitor.js +1161 -0
- package/dist/src/webhook/state.d.ts +220 -0
- package/dist/src/webhook/state.js +491 -0
- package/dist/src/webhook/target.d.ts +41 -0
- package/dist/src/webhook/target.js +132 -0
- package/dist/src/webhook/types.d.ts +347 -0
- package/dist/src/webhook/types.js +33 -0
- package/dist/src/webhook/video-frame.d.ts +13 -0
- package/dist/src/webhook/video-frame.js +30 -0
- package/package.json +15 -7
- package/dist/cjs/index.js +0 -45
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/src/channel.js +0 -339
- package/dist/cjs/src/channel.js.map +0 -1
- package/dist/cjs/src/const.js +0 -137
- package/dist/cjs/src/const.js.map +0 -1
- package/dist/cjs/src/dm-policy.js +0 -89
- package/dist/cjs/src/dm-policy.js.map +0 -1
- package/dist/cjs/src/group-policy.js +0 -133
- package/dist/cjs/src/group-policy.js.map +0 -1
- package/dist/cjs/src/mcp/interceptors/biz-error.js +0 -70
- package/dist/cjs/src/mcp/interceptors/biz-error.js.map +0 -1
- package/dist/cjs/src/mcp/interceptors/index.js +0 -73
- package/dist/cjs/src/mcp/interceptors/index.js.map +0 -1
- package/dist/cjs/src/mcp/interceptors/msg-media.js +0 -159
- package/dist/cjs/src/mcp/interceptors/msg-media.js.map +0 -1
- package/dist/cjs/src/mcp/interceptors/smartpage-create.js +0 -157
- package/dist/cjs/src/mcp/interceptors/smartpage-create.js.map +0 -1
- package/dist/cjs/src/mcp/interceptors/smartpage-export.js +0 -93
- package/dist/cjs/src/mcp/interceptors/smartpage-export.js.map +0 -1
- package/dist/cjs/src/mcp/schema.js +0 -104
- package/dist/cjs/src/mcp/schema.js.map +0 -1
- package/dist/cjs/src/mcp/tool.js +0 -208
- package/dist/cjs/src/mcp/tool.js.map +0 -1
- package/dist/cjs/src/mcp/transport.js +0 -417
- package/dist/cjs/src/mcp/transport.js.map +0 -1
- package/dist/cjs/src/media-handler.js +0 -129
- package/dist/cjs/src/media-handler.js.map +0 -1
- package/dist/cjs/src/media-uploader.js +0 -284
- package/dist/cjs/src/media-uploader.js.map +0 -1
- package/dist/cjs/src/message-parser.js +0 -134
- package/dist/cjs/src/message-parser.js.map +0 -1
- package/dist/cjs/src/message-sender.js +0 -89
- package/dist/cjs/src/message-sender.js.map +0 -1
- package/dist/cjs/src/monitor.js +0 -991
- package/dist/cjs/src/monitor.js.map +0 -1
- package/dist/cjs/src/onboarding.js +0 -182
- package/dist/cjs/src/onboarding.js.map +0 -1
- package/dist/cjs/src/openclaw-compat.js +0 -400
- package/dist/cjs/src/openclaw-compat.js.map +0 -1
- package/dist/cjs/src/reqid-store.js +0 -88
- package/dist/cjs/src/reqid-store.js.map +0 -1
- package/dist/cjs/src/runtime.js +0 -16
- package/dist/cjs/src/runtime.js.map +0 -1
- package/dist/cjs/src/state-dir-resolve.js +0 -35
- package/dist/cjs/src/state-dir-resolve.js.map +0 -1
- package/dist/cjs/src/state-manager.js +0 -158
- package/dist/cjs/src/state-manager.js.map +0 -1
- package/dist/cjs/src/template-card-parser.js +0 -641
- package/dist/cjs/src/template-card-parser.js.map +0 -1
- package/dist/cjs/src/timeout.js +0 -42
- package/dist/cjs/src/timeout.js.map +0 -1
- package/dist/cjs/src/utils.js +0 -60
- package/dist/cjs/src/utils.js.map +0 -1
- package/dist/cjs/src/version.js +0 -26
- package/dist/cjs/src/version.js.map +0 -1
- package/dist/esm/index.js +0 -41
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/src/channel.js +0 -337
- package/dist/esm/src/channel.js.map +0 -1
- package/dist/esm/src/const.js.map +0 -1
- package/dist/esm/src/dm-policy.js.map +0 -1
- package/dist/esm/src/group-policy.js.map +0 -1
- package/dist/esm/src/mcp/interceptors/biz-error.js.map +0 -1
- package/dist/esm/src/mcp/interceptors/index.js.map +0 -1
- package/dist/esm/src/mcp/interceptors/msg-media.js.map +0 -1
- package/dist/esm/src/mcp/interceptors/smartpage-create.js.map +0 -1
- package/dist/esm/src/mcp/interceptors/smartpage-export.js.map +0 -1
- package/dist/esm/src/mcp/schema.js.map +0 -1
- package/dist/esm/src/mcp/tool.js.map +0 -1
- package/dist/esm/src/mcp/transport.js.map +0 -1
- package/dist/esm/src/media-handler.js.map +0 -1
- package/dist/esm/src/media-uploader.js.map +0 -1
- package/dist/esm/src/message-parser.js.map +0 -1
- package/dist/esm/src/message-sender.js.map +0 -1
- package/dist/esm/src/monitor.js.map +0 -1
- package/dist/esm/src/onboarding.js.map +0 -1
- package/dist/esm/src/openclaw-compat.js.map +0 -1
- package/dist/esm/src/reqid-store.js.map +0 -1
- package/dist/esm/src/runtime.js.map +0 -1
- package/dist/esm/src/state-dir-resolve.js.map +0 -1
- package/dist/esm/src/state-manager.js.map +0 -1
- package/dist/esm/src/template-card-parser.js.map +0 -1
- package/dist/esm/src/timeout.js.map +0 -1
- package/dist/esm/src/utils.js.map +0 -1
- package/dist/esm/src/version.js +0 -23
- package/dist/esm/src/version.js.map +0 -1
- package/dist/esm/types/index.d.ts +0 -9
- package/dist/esm/types/src/version.d.ts +0 -2
- /package/dist/{esm/types/src → src}/channel.d.ts +0 -0
- /package/dist/{esm/types/src → src}/dm-policy.d.ts +0 -0
- /package/dist/{esm/types/src → src}/group-policy.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/index.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/interceptors/biz-error.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/interceptors/index.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/interceptors/msg-media.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/interceptors/smartpage-create.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/interceptors/smartpage-export.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/interceptors/types.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/schema.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/tool.d.ts +0 -0
- /package/dist/{esm/types/src → src}/mcp/transport.d.ts +0 -0
- /package/dist/{esm/types/src → src}/media-handler.d.ts +0 -0
- /package/dist/{esm/types/src → src}/media-uploader.d.ts +0 -0
- /package/dist/{esm/types/src → src}/message-parser.d.ts +0 -0
- /package/dist/{esm/types/src → src}/monitor.d.ts +0 -0
- /package/dist/{esm/types/src → src}/onboarding.d.ts +0 -0
- /package/dist/{esm/types/src → src}/reqid-store.d.ts +0 -0
- /package/dist/{esm/types/src → src}/runtime.d.ts +0 -0
- /package/dist/{esm/types/src → src}/state-dir-resolve.d.ts +0 -0
- /package/dist/{esm/types/src → src}/state-manager.d.ts +0 -0
- /package/dist/{esm/types/src → src}/template-card-parser.d.ts +0 -0
- /package/dist/{esm/types/src → src}/timeout.d.ts +0 -0
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var fs = require('node:fs/promises');
|
|
4
|
-
var path = require('node:path');
|
|
5
|
-
var os = require('node:os');
|
|
6
|
-
var node_url = require('node:url');
|
|
7
|
-
var stateDirResolve = require('./state-dir-resolve.js');
|
|
8
|
-
|
|
9
|
-
function _interopNamespaceDefault(e) {
|
|
10
|
-
var n = Object.create(null);
|
|
11
|
-
if (e) {
|
|
12
|
-
Object.keys(e).forEach(function (k) {
|
|
13
|
-
if (k !== 'default') {
|
|
14
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return e[k]; }
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
n.default = e;
|
|
23
|
-
return Object.freeze(n);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
27
|
-
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
28
|
-
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* openclaw plugin-sdk 高版本方法兼容层
|
|
32
|
-
*
|
|
33
|
-
* 部分方法(如 loadOutboundMediaFromUrl、detectMime、getDefaultMediaLocalRoots)
|
|
34
|
-
* 仅在较新版本的 openclaw plugin-sdk 中才导出。
|
|
35
|
-
*
|
|
36
|
-
* 本模块在加载时一次性探测 SDK 导出,存在则直接 re-export SDK 版本,
|
|
37
|
-
* 不存在则导出 fallback 实现。其他模块统一从本文件导入,无需关心底层兼容细节。
|
|
38
|
-
*/
|
|
39
|
-
const DEFAULT_ACCOUNT_ID = "default";
|
|
40
|
-
const _sdkReady = import('openclaw/plugin-sdk/core')
|
|
41
|
-
.then((sdk) => {
|
|
42
|
-
const exports$1 = {};
|
|
43
|
-
if (typeof sdk.loadOutboundMediaFromUrl === "function") {
|
|
44
|
-
exports$1.loadOutboundMediaFromUrl = sdk.loadOutboundMediaFromUrl;
|
|
45
|
-
}
|
|
46
|
-
if (typeof sdk.detectMime === "function") {
|
|
47
|
-
exports$1.detectMime = sdk.detectMime;
|
|
48
|
-
}
|
|
49
|
-
if (typeof sdk.getDefaultMediaLocalRoots === "function") {
|
|
50
|
-
exports$1.getDefaultMediaLocalRoots = sdk.getDefaultMediaLocalRoots;
|
|
51
|
-
}
|
|
52
|
-
if (typeof sdk.addWildcardAllowFrom === "function") {
|
|
53
|
-
exports$1.addWildcardAllowFrom = sdk.addWildcardAllowFrom;
|
|
54
|
-
}
|
|
55
|
-
return exports$1;
|
|
56
|
-
})
|
|
57
|
-
.catch(() => {
|
|
58
|
-
// openclaw/plugin-sdk 不可用或版本过低,全部使用 fallback
|
|
59
|
-
return {};
|
|
60
|
-
});
|
|
61
|
-
// 同时尝试从 plugin-sdk/setup 模块探测(缓存同步可用的引用)
|
|
62
|
-
let _cachedAddWildcardAllowFrom;
|
|
63
|
-
import('openclaw/plugin-sdk/setup')
|
|
64
|
-
.then((sdk) => {
|
|
65
|
-
if (typeof sdk.addWildcardAllowFrom === "function") {
|
|
66
|
-
_cachedAddWildcardAllowFrom = sdk.addWildcardAllowFrom;
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
.catch(() => { });
|
|
70
|
-
// 同时也从 core 模块的结果中缓存
|
|
71
|
-
_sdkReady.then((sdk) => {
|
|
72
|
-
if (!_cachedAddWildcardAllowFrom && sdk.addWildcardAllowFrom) {
|
|
73
|
-
_cachedAddWildcardAllowFrom = sdk.addWildcardAllowFrom;
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
// ============================================================================
|
|
77
|
-
// detectMime —— 检测 MIME 类型
|
|
78
|
-
// ============================================================================
|
|
79
|
-
const MIME_BY_EXT = {
|
|
80
|
-
".heic": "image/heic",
|
|
81
|
-
".heif": "image/heif",
|
|
82
|
-
".jpg": "image/jpeg",
|
|
83
|
-
".jpeg": "image/jpeg",
|
|
84
|
-
".png": "image/png",
|
|
85
|
-
".webp": "image/webp",
|
|
86
|
-
".gif": "image/gif",
|
|
87
|
-
".ogg": "audio/ogg",
|
|
88
|
-
".mp3": "audio/mpeg",
|
|
89
|
-
".m4a": "audio/x-m4a",
|
|
90
|
-
".mp4": "video/mp4",
|
|
91
|
-
".mov": "video/quicktime",
|
|
92
|
-
".pdf": "application/pdf",
|
|
93
|
-
".json": "application/json",
|
|
94
|
-
".zip": "application/zip",
|
|
95
|
-
".gz": "application/gzip",
|
|
96
|
-
".tar": "application/x-tar",
|
|
97
|
-
".7z": "application/x-7z-compressed",
|
|
98
|
-
".rar": "application/vnd.rar",
|
|
99
|
-
".doc": "application/msword",
|
|
100
|
-
".xls": "application/vnd.ms-excel",
|
|
101
|
-
".ppt": "application/vnd.ms-powerpoint",
|
|
102
|
-
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
103
|
-
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
104
|
-
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
105
|
-
".csv": "text/csv",
|
|
106
|
-
".txt": "text/plain",
|
|
107
|
-
".md": "text/markdown",
|
|
108
|
-
".amr": "audio/amr",
|
|
109
|
-
".aac": "audio/aac",
|
|
110
|
-
".wav": "audio/wav",
|
|
111
|
-
".webm": "video/webm",
|
|
112
|
-
".avi": "video/x-msvideo",
|
|
113
|
-
".bmp": "image/bmp",
|
|
114
|
-
".svg": "image/svg+xml",
|
|
115
|
-
};
|
|
116
|
-
/** 通过 buffer 魔术字节嗅探 MIME 类型(动态导入 file-type,不强依赖) */
|
|
117
|
-
async function sniffMimeFromBuffer(buffer) {
|
|
118
|
-
try {
|
|
119
|
-
const { fileTypeFromBuffer } = await import('file-type');
|
|
120
|
-
const type = await fileTypeFromBuffer(buffer);
|
|
121
|
-
return type?.mime ?? undefined;
|
|
122
|
-
}
|
|
123
|
-
catch {
|
|
124
|
-
return undefined;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/** fallback 版 detectMime,参考 weclaw/src/media/mime.ts */
|
|
128
|
-
async function detectMimeFallback(opts) {
|
|
129
|
-
const ext = opts.filePath ? path__namespace.extname(opts.filePath).toLowerCase() : undefined;
|
|
130
|
-
const extMime = ext ? MIME_BY_EXT[ext] : undefined;
|
|
131
|
-
const sniffed = opts.buffer ? await sniffMimeFromBuffer(opts.buffer) : undefined;
|
|
132
|
-
const isGeneric = (m) => !m || m === "application/octet-stream" || m === "application/zip";
|
|
133
|
-
if (sniffed && (!isGeneric(sniffed) || !extMime)) {
|
|
134
|
-
return sniffed;
|
|
135
|
-
}
|
|
136
|
-
if (extMime) {
|
|
137
|
-
return extMime;
|
|
138
|
-
}
|
|
139
|
-
const headerMime = opts.headerMime?.split(";")?.[0]?.trim().toLowerCase();
|
|
140
|
-
if (headerMime && !isGeneric(headerMime)) {
|
|
141
|
-
return headerMime;
|
|
142
|
-
}
|
|
143
|
-
if (sniffed) {
|
|
144
|
-
return sniffed;
|
|
145
|
-
}
|
|
146
|
-
if (headerMime) {
|
|
147
|
-
return headerMime;
|
|
148
|
-
}
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* 检测 MIME 类型(兼容入口)
|
|
153
|
-
*
|
|
154
|
-
* 支持两种调用签名以兼容不同使用场景:
|
|
155
|
-
* - detectMime(buffer) → 旧式调用
|
|
156
|
-
* - detectMime({ buffer, headerMime, filePath }) → 完整参数
|
|
157
|
-
*
|
|
158
|
-
* 优先使用 SDK 版本,不可用时使用 fallback。
|
|
159
|
-
*/
|
|
160
|
-
async function detectMime(bufferOrOpts) {
|
|
161
|
-
const sdk = await _sdkReady;
|
|
162
|
-
const opts = Buffer.isBuffer(bufferOrOpts)
|
|
163
|
-
? { buffer: bufferOrOpts }
|
|
164
|
-
: bufferOrOpts;
|
|
165
|
-
if (sdk.detectMime) {
|
|
166
|
-
try {
|
|
167
|
-
return await sdk.detectMime(opts);
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
// SDK detectMime 异常,降级到 fallback
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return detectMimeFallback(opts);
|
|
174
|
-
}
|
|
175
|
-
// ============================================================================
|
|
176
|
-
// loadOutboundMediaFromUrl —— 从 URL/路径加载媒体文件
|
|
177
|
-
// ============================================================================
|
|
178
|
-
/** 安全的本地文件路径校验,参考 weclaw/src/web/media.ts */
|
|
179
|
-
async function assertLocalMediaAllowed(mediaPath, localRoots) {
|
|
180
|
-
if (!localRoots || localRoots.length === 0) {
|
|
181
|
-
throw new Error(`Local media path is not under an allowed directory: ${mediaPath}`);
|
|
182
|
-
}
|
|
183
|
-
let resolved;
|
|
184
|
-
try {
|
|
185
|
-
resolved = await fs__namespace.realpath(mediaPath);
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
resolved = path__namespace.resolve(mediaPath);
|
|
189
|
-
}
|
|
190
|
-
for (const root of localRoots) {
|
|
191
|
-
let resolvedRoot;
|
|
192
|
-
try {
|
|
193
|
-
resolvedRoot = await fs__namespace.realpath(root);
|
|
194
|
-
}
|
|
195
|
-
catch {
|
|
196
|
-
resolvedRoot = path__namespace.resolve(root);
|
|
197
|
-
}
|
|
198
|
-
if (resolvedRoot === path__namespace.parse(resolvedRoot).root) {
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
if (resolved === resolvedRoot || resolved.startsWith(resolvedRoot + path__namespace.sep)) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
throw new Error(`Local media path is not under an allowed directory: ${mediaPath}`);
|
|
206
|
-
}
|
|
207
|
-
/** 从远程 URL 获取媒体 */
|
|
208
|
-
async function fetchRemoteMedia(url, maxBytes) {
|
|
209
|
-
const res = await fetch(url, { redirect: "follow" });
|
|
210
|
-
if (!res.ok) {
|
|
211
|
-
throw new Error(`Failed to fetch media from ${url}: HTTP ${res.status} ${res.statusText}`);
|
|
212
|
-
}
|
|
213
|
-
const buffer = Buffer.from(await res.arrayBuffer());
|
|
214
|
-
if (maxBytes && buffer.length > maxBytes) {
|
|
215
|
-
throw new Error(`Media from ${url} exceeds max size (${buffer.length} > ${maxBytes})`);
|
|
216
|
-
}
|
|
217
|
-
const headerMime = res.headers.get("content-type")?.split(";")?.[0]?.trim();
|
|
218
|
-
let fileName;
|
|
219
|
-
const disposition = res.headers.get("content-disposition");
|
|
220
|
-
if (disposition) {
|
|
221
|
-
const match = /filename\*?\s*=\s*(?:UTF-8''|")?([^";]+)/i.exec(disposition);
|
|
222
|
-
if (match?.[1]) {
|
|
223
|
-
try {
|
|
224
|
-
fileName = path__namespace.basename(decodeURIComponent(match[1].replace(/["']/g, "").trim()));
|
|
225
|
-
}
|
|
226
|
-
catch {
|
|
227
|
-
fileName = path__namespace.basename(match[1].replace(/["']/g, "").trim());
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
if (!fileName) {
|
|
232
|
-
try {
|
|
233
|
-
const parsed = new URL(url);
|
|
234
|
-
const base = path__namespace.basename(parsed.pathname);
|
|
235
|
-
if (base && base.includes("."))
|
|
236
|
-
fileName = base;
|
|
237
|
-
}
|
|
238
|
-
catch { /* ignore */ }
|
|
239
|
-
}
|
|
240
|
-
const contentType = await detectMimeFallback({ buffer, headerMime, filePath: fileName ?? url });
|
|
241
|
-
return { buffer, contentType, fileName };
|
|
242
|
-
}
|
|
243
|
-
/** 展开 ~ 为用户主目录 */
|
|
244
|
-
function resolveUserPath(p) {
|
|
245
|
-
if (p.startsWith("~")) {
|
|
246
|
-
return path__namespace.join(os__namespace.homedir(), p.slice(1));
|
|
247
|
-
}
|
|
248
|
-
return p;
|
|
249
|
-
}
|
|
250
|
-
/** fallback 版 loadOutboundMediaFromUrl,参考 weclaw/src/web/media.ts */
|
|
251
|
-
async function loadOutboundMediaFromUrlFallback(mediaUrl, options = {}) {
|
|
252
|
-
const { maxBytes, mediaLocalRoots } = options;
|
|
253
|
-
// 去除 MEDIA: 前缀
|
|
254
|
-
mediaUrl = mediaUrl.replace(/^\s*MEDIA\s*:\s*/i, "");
|
|
255
|
-
// 处理 file:// URL
|
|
256
|
-
if (mediaUrl.startsWith("file://")) {
|
|
257
|
-
try {
|
|
258
|
-
mediaUrl = node_url.fileURLToPath(mediaUrl);
|
|
259
|
-
}
|
|
260
|
-
catch {
|
|
261
|
-
throw new Error(`Invalid file:// URL: ${mediaUrl}`);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
// 远程 URL
|
|
265
|
-
if (/^https?:\/\//i.test(mediaUrl)) {
|
|
266
|
-
const fetched = await fetchRemoteMedia(mediaUrl, maxBytes);
|
|
267
|
-
return {
|
|
268
|
-
buffer: fetched.buffer,
|
|
269
|
-
contentType: fetched.contentType,
|
|
270
|
-
fileName: fetched.fileName,
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
// 展开 ~ 路径
|
|
274
|
-
if (mediaUrl.startsWith("~")) {
|
|
275
|
-
mediaUrl = resolveUserPath(mediaUrl);
|
|
276
|
-
}
|
|
277
|
-
// 本地文件:安全校验
|
|
278
|
-
await assertLocalMediaAllowed(mediaUrl, mediaLocalRoots);
|
|
279
|
-
// 读取本地文件
|
|
280
|
-
let data;
|
|
281
|
-
try {
|
|
282
|
-
const stat = await fs__namespace.stat(mediaUrl);
|
|
283
|
-
if (!stat.isFile()) {
|
|
284
|
-
throw new Error(`Local media path is not a file: ${mediaUrl}`);
|
|
285
|
-
}
|
|
286
|
-
data = await fs__namespace.readFile(mediaUrl);
|
|
287
|
-
}
|
|
288
|
-
catch (err) {
|
|
289
|
-
if (err?.code === "ENOENT") {
|
|
290
|
-
throw new Error(`Local media file not found: ${mediaUrl}`);
|
|
291
|
-
}
|
|
292
|
-
throw err;
|
|
293
|
-
}
|
|
294
|
-
if (maxBytes && data.length > maxBytes) {
|
|
295
|
-
throw new Error(`Local media exceeds max size (${data.length} > ${maxBytes})`);
|
|
296
|
-
}
|
|
297
|
-
const mime = await detectMimeFallback({ buffer: data, filePath: mediaUrl });
|
|
298
|
-
const fileName = path__namespace.basename(mediaUrl) || undefined;
|
|
299
|
-
return {
|
|
300
|
-
buffer: data,
|
|
301
|
-
contentType: mime,
|
|
302
|
-
fileName,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* 从 URL 或本地路径加载媒体文件(兼容入口)
|
|
307
|
-
*
|
|
308
|
-
* 优先使用 SDK 版本,不可用时使用 fallback。
|
|
309
|
-
* SDK 版本抛出的业务异常(如 LocalMediaAccessError)会直接透传。
|
|
310
|
-
*/
|
|
311
|
-
async function loadOutboundMediaFromUrl(mediaUrl, options = {}) {
|
|
312
|
-
const sdk = await _sdkReady;
|
|
313
|
-
if (sdk.loadOutboundMediaFromUrl) {
|
|
314
|
-
return sdk.loadOutboundMediaFromUrl(mediaUrl, options);
|
|
315
|
-
}
|
|
316
|
-
return loadOutboundMediaFromUrlFallback(mediaUrl, options);
|
|
317
|
-
}
|
|
318
|
-
// ============================================================================
|
|
319
|
-
// addWildcardAllowFrom —— 向 allowFrom 列表添加通配符 "*"
|
|
320
|
-
// ============================================================================
|
|
321
|
-
/** fallback 版 addWildcardAllowFrom:确保列表中包含 "*" 通配符 */
|
|
322
|
-
function addWildcardAllowFromFallback(allowFrom) {
|
|
323
|
-
if (allowFrom.includes("*")) {
|
|
324
|
-
return allowFrom;
|
|
325
|
-
}
|
|
326
|
-
return [...allowFrom, "*"];
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* 向 allowFrom 列表添加通配符 "*"(兼容入口)
|
|
330
|
-
*
|
|
331
|
-
* 当 dmPolicy 为 "open" 时,需要确保 allowFrom 中包含 "*" 以允许所有来源。
|
|
332
|
-
* 优先使用 SDK 版本(plugin-sdk/setup 或 plugin-sdk/core),不可用时使用 fallback。
|
|
333
|
-
*
|
|
334
|
-
* 注意:此函数为同步函数,与 SDK 原始签名一致。
|
|
335
|
-
* SDK 引用在模块加载时异步探测并缓存,调用时同步读取缓存。
|
|
336
|
-
*/
|
|
337
|
-
function addWildcardAllowFrom(allowFrom) {
|
|
338
|
-
if (_cachedAddWildcardAllowFrom) {
|
|
339
|
-
try {
|
|
340
|
-
return _cachedAddWildcardAllowFrom(allowFrom);
|
|
341
|
-
}
|
|
342
|
-
catch {
|
|
343
|
-
// SDK 版本异常,降级到 fallback
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
return addWildcardAllowFromFallback(allowFrom);
|
|
347
|
-
}
|
|
348
|
-
// ============================================================================
|
|
349
|
-
// getDefaultMediaLocalRoots —— 获取默认媒体本地路径白名单
|
|
350
|
-
// ============================================================================
|
|
351
|
-
/**
|
|
352
|
-
* 获取默认媒体本地路径白名单(兼容入口)
|
|
353
|
-
*
|
|
354
|
-
* 优先使用 SDK 版本,不可用时手动构建白名单(与 weclaw/src/media/local-roots.ts 逻辑一致)。
|
|
355
|
-
*/
|
|
356
|
-
async function getDefaultMediaLocalRoots() {
|
|
357
|
-
const sdk = await _sdkReady;
|
|
358
|
-
if (sdk.getDefaultMediaLocalRoots) {
|
|
359
|
-
try {
|
|
360
|
-
return sdk.getDefaultMediaLocalRoots();
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
// SDK 版本异常,降级到 fallback
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
// fallback: 手动构建默认白名单
|
|
367
|
-
const stateDir = path__namespace.resolve(stateDirResolve.resolveStateDir());
|
|
368
|
-
return [
|
|
369
|
-
path__namespace.join(stateDir, "media"),
|
|
370
|
-
path__namespace.join(stateDir, "agents"),
|
|
371
|
-
path__namespace.join(stateDir, "workspace"),
|
|
372
|
-
path__namespace.join(stateDir, "sandboxes"),
|
|
373
|
-
];
|
|
374
|
-
}
|
|
375
|
-
function emptyPluginConfigSchema() {
|
|
376
|
-
return {
|
|
377
|
-
type: 'object',
|
|
378
|
-
additionalProperties: false,
|
|
379
|
-
properties: {},
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* 格式化配对审批提示信息(参考 moltbot 实现)
|
|
384
|
-
* @param channelId 频道ID
|
|
385
|
-
* @returns 配对审批提示字符串
|
|
386
|
-
*/
|
|
387
|
-
function formatPairingApproveHint(channelId) {
|
|
388
|
-
const listCmd = `openclaw pairing list ${channelId}`;
|
|
389
|
-
const approveCmd = `openclaw pairing approve ${channelId} <code>`;
|
|
390
|
-
return `向 ${channelId} 机器人发送消息以完成配对审批(命令行:${listCmd} / ${approveCmd})`;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
exports.DEFAULT_ACCOUNT_ID = DEFAULT_ACCOUNT_ID;
|
|
394
|
-
exports.addWildcardAllowFrom = addWildcardAllowFrom;
|
|
395
|
-
exports.detectMime = detectMime;
|
|
396
|
-
exports.emptyPluginConfigSchema = emptyPluginConfigSchema;
|
|
397
|
-
exports.formatPairingApproveHint = formatPairingApproveHint;
|
|
398
|
-
exports.getDefaultMediaLocalRoots = getDefaultMediaLocalRoots;
|
|
399
|
-
exports.loadOutboundMediaFromUrl = loadOutboundMediaFromUrl;
|
|
400
|
-
//# sourceMappingURL=openclaw-compat.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openclaw-compat.js","sources":["../../../../../src/openclaw-compat.ts"],"sourcesContent":["/**\n * openclaw plugin-sdk 高版本方法兼容层\n *\n * 部分方法(如 loadOutboundMediaFromUrl、detectMime、getDefaultMediaLocalRoots)\n * 仅在较新版本的 openclaw plugin-sdk 中才导出。\n *\n * 本模块在加载时一次性探测 SDK 导出,存在则直接 re-export SDK 版本,\n * 不存在则导出 fallback 实现。其他模块统一从本文件导入,无需关心底层兼容细节。\n */\n\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\nimport { resolveStateDir } from \"./state-dir-resolve\";\n\nexport const DEFAULT_ACCOUNT_ID = \"default\";\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/** 与 openclaw plugin-sdk 中 WebMediaResult 兼容的类型 */\nexport type WebMediaResult = {\n buffer: Buffer;\n contentType?: string;\n kind?: string;\n fileName?: string;\n};\n\nexport type OutboundMediaLoadOptions = {\n maxBytes?: number;\n mediaLocalRoots?: readonly string[];\n};\n\nexport type DetectMimeOptions = {\n buffer?: Buffer;\n headerMime?: string | null;\n filePath?: string;\n};\n\n// ============================================================================\n// SDK 一次性探测(模块加载时执行,结果缓存)\n// ============================================================================\n\ninterface SdkExports {\n loadOutboundMediaFromUrl?: (url: string, opts?: OutboundMediaLoadOptions) => Promise<WebMediaResult>;\n detectMime?: (opts: DetectMimeOptions) => Promise<string | undefined>;\n getDefaultMediaLocalRoots?: () => readonly string[];\n addWildcardAllowFrom?: (allowFrom: string[]) => string[];\n}\n\nconst _sdkReady: Promise<SdkExports> = import(\"openclaw/plugin-sdk/core\")\n .then((sdk: any) => {\n const exports: SdkExports = {};\n if (typeof sdk.loadOutboundMediaFromUrl === \"function\") {\n exports.loadOutboundMediaFromUrl = sdk.loadOutboundMediaFromUrl;\n }\n if (typeof sdk.detectMime === \"function\") {\n exports.detectMime = sdk.detectMime;\n }\n if (typeof sdk.getDefaultMediaLocalRoots === \"function\") {\n exports.getDefaultMediaLocalRoots = sdk.getDefaultMediaLocalRoots;\n }\n if (typeof sdk.addWildcardAllowFrom === \"function\") {\n exports.addWildcardAllowFrom = sdk.addWildcardAllowFrom;\n }\n return exports;\n })\n .catch(() => {\n // openclaw/plugin-sdk 不可用或版本过低,全部使用 fallback\n return {} as SdkExports;\n });\n\n// 同时尝试从 plugin-sdk/setup 模块探测(缓存同步可用的引用)\nlet _cachedAddWildcardAllowFrom: ((allowFrom: string[]) => string[]) | undefined;\n\nconst _setupSdkReady: Promise<void> = import(\"openclaw/plugin-sdk/setup\")\n .then((sdk: any) => {\n if (typeof sdk.addWildcardAllowFrom === \"function\") {\n _cachedAddWildcardAllowFrom = sdk.addWildcardAllowFrom;\n }\n })\n .catch(() => { /* plugin-sdk/setup 不可用 */ });\n\n// 同时也从 core 模块的结果中缓存\n_sdkReady.then((sdk) => {\n if (!_cachedAddWildcardAllowFrom && sdk.addWildcardAllowFrom) {\n _cachedAddWildcardAllowFrom = sdk.addWildcardAllowFrom;\n }\n});\n\n// ============================================================================\n// detectMime —— 检测 MIME 类型\n// ============================================================================\n\nconst MIME_BY_EXT: Record<string, string> = {\n \".heic\": \"image/heic\",\n \".heif\": \"image/heif\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".webp\": \"image/webp\",\n \".gif\": \"image/gif\",\n \".ogg\": \"audio/ogg\",\n \".mp3\": \"audio/mpeg\",\n \".m4a\": \"audio/x-m4a\",\n \".mp4\": \"video/mp4\",\n \".mov\": \"video/quicktime\",\n \".pdf\": \"application/pdf\",\n \".json\": \"application/json\",\n \".zip\": \"application/zip\",\n \".gz\": \"application/gzip\",\n \".tar\": \"application/x-tar\",\n \".7z\": \"application/x-7z-compressed\",\n \".rar\": \"application/vnd.rar\",\n \".doc\": \"application/msword\",\n \".xls\": \"application/vnd.ms-excel\",\n \".ppt\": \"application/vnd.ms-powerpoint\",\n \".docx\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n \".xlsx\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n \".pptx\": \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n \".csv\": \"text/csv\",\n \".txt\": \"text/plain\",\n \".md\": \"text/markdown\",\n \".amr\": \"audio/amr\",\n \".aac\": \"audio/aac\",\n \".wav\": \"audio/wav\",\n \".webm\": \"video/webm\",\n \".avi\": \"video/x-msvideo\",\n \".bmp\": \"image/bmp\",\n \".svg\": \"image/svg+xml\",\n};\n\n/** 通过 buffer 魔术字节嗅探 MIME 类型(动态导入 file-type,不强依赖) */\nasync function sniffMimeFromBuffer(buffer: Buffer): Promise<string | undefined> {\n try {\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const type = await fileTypeFromBuffer(buffer);\n return type?.mime ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/** fallback 版 detectMime,参考 weclaw/src/media/mime.ts */\nasync function detectMimeFallback(opts: DetectMimeOptions): Promise<string | undefined> {\n const ext = opts.filePath ? path.extname(opts.filePath).toLowerCase() : undefined;\n const extMime = ext ? MIME_BY_EXT[ext] : undefined;\n\n const sniffed = opts.buffer ? await sniffMimeFromBuffer(opts.buffer) : undefined;\n\n const isGeneric = (m?: string) =>\n !m || m === \"application/octet-stream\" || m === \"application/zip\";\n\n if (sniffed && (!isGeneric(sniffed) || !extMime)) {\n return sniffed;\n }\n if (extMime) {\n return extMime;\n }\n const headerMime = opts.headerMime?.split(\";\")?.[0]?.trim().toLowerCase();\n if (headerMime && !isGeneric(headerMime)) {\n return headerMime;\n }\n if (sniffed) {\n return sniffed;\n }\n if (headerMime) {\n return headerMime;\n }\n return undefined;\n}\n\n/**\n * 检测 MIME 类型(兼容入口)\n *\n * 支持两种调用签名以兼容不同使用场景:\n * - detectMime(buffer) → 旧式调用\n * - detectMime({ buffer, headerMime, filePath }) → 完整参数\n *\n * 优先使用 SDK 版本,不可用时使用 fallback。\n */\nexport async function detectMime(\n bufferOrOpts: Buffer | DetectMimeOptions,\n): Promise<string | undefined> {\n const sdk = await _sdkReady;\n\n const opts: DetectMimeOptions = Buffer.isBuffer(bufferOrOpts)\n ? { buffer: bufferOrOpts }\n : bufferOrOpts;\n\n if (sdk.detectMime) {\n try {\n return await sdk.detectMime(opts);\n } catch {\n // SDK detectMime 异常,降级到 fallback\n }\n }\n return detectMimeFallback(opts);\n}\n\n// ============================================================================\n// loadOutboundMediaFromUrl —— 从 URL/路径加载媒体文件\n// ============================================================================\n\n/** 安全的本地文件路径校验,参考 weclaw/src/web/media.ts */\nasync function assertLocalMediaAllowed(\n mediaPath: string,\n localRoots: readonly string[] | undefined,\n): Promise<void> {\n if (!localRoots || localRoots.length === 0) {\n throw new Error(`Local media path is not under an allowed directory: ${mediaPath}`);\n }\n\n let resolved: string;\n try {\n resolved = await fs.realpath(mediaPath);\n } catch {\n resolved = path.resolve(mediaPath);\n }\n\n for (const root of localRoots) {\n let resolvedRoot: string;\n try {\n resolvedRoot = await fs.realpath(root);\n } catch {\n resolvedRoot = path.resolve(root);\n }\n if (resolvedRoot === path.parse(resolvedRoot).root) {\n continue;\n }\n if (resolved === resolvedRoot || resolved.startsWith(resolvedRoot + path.sep)) {\n return;\n }\n }\n\n throw new Error(`Local media path is not under an allowed directory: ${mediaPath}`);\n}\n\n/** 从远程 URL 获取媒体 */\nasync function fetchRemoteMedia(\n url: string,\n maxBytes?: number,\n): Promise<{ buffer: Buffer; contentType?: string; fileName?: string }> {\n const res = await fetch(url, { redirect: \"follow\" });\n if (!res.ok) {\n throw new Error(`Failed to fetch media from ${url}: HTTP ${res.status} ${res.statusText}`);\n }\n\n const buffer = Buffer.from(await res.arrayBuffer());\n if (maxBytes && buffer.length > maxBytes) {\n throw new Error(`Media from ${url} exceeds max size (${buffer.length} > ${maxBytes})`);\n }\n\n const headerMime = res.headers.get(\"content-type\")?.split(\";\")?.[0]?.trim();\n\n let fileName: string | undefined;\n const disposition = res.headers.get(\"content-disposition\");\n if (disposition) {\n const match = /filename\\*?\\s*=\\s*(?:UTF-8''|\")?([^\";]+)/i.exec(disposition);\n if (match?.[1]) {\n try {\n fileName = path.basename(decodeURIComponent(match[1].replace(/[\"']/g, \"\").trim()));\n } catch {\n fileName = path.basename(match[1].replace(/[\"']/g, \"\").trim());\n }\n }\n }\n if (!fileName) {\n try {\n const parsed = new URL(url);\n const base = path.basename(parsed.pathname);\n if (base && base.includes(\".\")) fileName = base;\n } catch { /* ignore */ }\n }\n\n const contentType = await detectMimeFallback({ buffer, headerMime, filePath: fileName ?? url });\n\n return { buffer, contentType, fileName };\n}\n\n/** 展开 ~ 为用户主目录 */\nfunction resolveUserPath(p: string): string {\n if (p.startsWith(\"~\")) {\n return path.join(os.homedir(), p.slice(1));\n }\n return p;\n}\n\n/** fallback 版 loadOutboundMediaFromUrl,参考 weclaw/src/web/media.ts */\nasync function loadOutboundMediaFromUrlFallback(\n mediaUrl: string,\n options: OutboundMediaLoadOptions = {},\n): Promise<WebMediaResult> {\n const { maxBytes, mediaLocalRoots } = options;\n\n // 去除 MEDIA: 前缀\n mediaUrl = mediaUrl.replace(/^\\s*MEDIA\\s*:\\s*/i, \"\");\n\n // 处理 file:// URL\n if (mediaUrl.startsWith(\"file://\")) {\n try {\n mediaUrl = fileURLToPath(mediaUrl);\n } catch {\n throw new Error(`Invalid file:// URL: ${mediaUrl}`);\n }\n }\n\n // 远程 URL\n if (/^https?:\\/\\//i.test(mediaUrl)) {\n const fetched = await fetchRemoteMedia(mediaUrl, maxBytes);\n return {\n buffer: fetched.buffer,\n contentType: fetched.contentType,\n fileName: fetched.fileName,\n };\n }\n\n // 展开 ~ 路径\n if (mediaUrl.startsWith(\"~\")) {\n mediaUrl = resolveUserPath(mediaUrl);\n }\n\n // 本地文件:安全校验\n await assertLocalMediaAllowed(mediaUrl, mediaLocalRoots);\n\n // 读取本地文件\n let data: Buffer;\n try {\n const stat = await fs.stat(mediaUrl);\n if (!stat.isFile()) {\n throw new Error(`Local media path is not a file: ${mediaUrl}`);\n }\n data = await fs.readFile(mediaUrl);\n } catch (err: any) {\n if (err?.code === \"ENOENT\") {\n throw new Error(`Local media file not found: ${mediaUrl}`);\n }\n throw err;\n }\n\n if (maxBytes && data.length > maxBytes) {\n throw new Error(`Local media exceeds max size (${data.length} > ${maxBytes})`);\n }\n\n const mime = await detectMimeFallback({ buffer: data, filePath: mediaUrl });\n const fileName = path.basename(mediaUrl) || undefined;\n\n return {\n buffer: data,\n contentType: mime,\n fileName,\n };\n}\n\n/**\n * 从 URL 或本地路径加载媒体文件(兼容入口)\n *\n * 优先使用 SDK 版本,不可用时使用 fallback。\n * SDK 版本抛出的业务异常(如 LocalMediaAccessError)会直接透传。\n */\nexport async function loadOutboundMediaFromUrl(\n mediaUrl: string,\n options: OutboundMediaLoadOptions = {},\n): Promise<WebMediaResult> {\n const sdk = await _sdkReady;\n\n if (sdk.loadOutboundMediaFromUrl) {\n return sdk.loadOutboundMediaFromUrl(mediaUrl, options);\n }\n return loadOutboundMediaFromUrlFallback(mediaUrl, options);\n}\n\n// ============================================================================\n// addWildcardAllowFrom —— 向 allowFrom 列表添加通配符 \"*\"\n// ============================================================================\n\n/** fallback 版 addWildcardAllowFrom:确保列表中包含 \"*\" 通配符 */\nfunction addWildcardAllowFromFallback(allowFrom: string[]): string[] {\n if (allowFrom.includes(\"*\")) {\n return allowFrom;\n }\n return [...allowFrom, \"*\"];\n}\n\n/**\n * 向 allowFrom 列表添加通配符 \"*\"(兼容入口)\n *\n * 当 dmPolicy 为 \"open\" 时,需要确保 allowFrom 中包含 \"*\" 以允许所有来源。\n * 优先使用 SDK 版本(plugin-sdk/setup 或 plugin-sdk/core),不可用时使用 fallback。\n *\n * 注意:此函数为同步函数,与 SDK 原始签名一致。\n * SDK 引用在模块加载时异步探测并缓存,调用时同步读取缓存。\n */\nexport function addWildcardAllowFrom(allowFrom: string[]): string[] {\n if (_cachedAddWildcardAllowFrom) {\n try {\n return _cachedAddWildcardAllowFrom(allowFrom);\n } catch {\n // SDK 版本异常,降级到 fallback\n }\n }\n return addWildcardAllowFromFallback(allowFrom);\n}\n\n// ============================================================================\n// getDefaultMediaLocalRoots —— 获取默认媒体本地路径白名单\n// ============================================================================\n\n/**\n * 获取默认媒体本地路径白名单(兼容入口)\n *\n * 优先使用 SDK 版本,不可用时手动构建白名单(与 weclaw/src/media/local-roots.ts 逻辑一致)。\n */\nexport async function getDefaultMediaLocalRoots(): Promise<readonly string[]> {\n const sdk = await _sdkReady;\n\n if (sdk.getDefaultMediaLocalRoots) {\n try {\n return sdk.getDefaultMediaLocalRoots();\n } catch {\n // SDK 版本异常,降级到 fallback\n }\n }\n\n // fallback: 手动构建默认白名单\n const stateDir = path.resolve(resolveStateDir());\n return [\n path.join(stateDir, \"media\"),\n path.join(stateDir, \"agents\"),\n path.join(stateDir, \"workspace\"),\n path.join(stateDir, \"sandboxes\"),\n ];\n}\n\nexport function emptyPluginConfigSchema(): Record<string, unknown> {\n return {\n type: 'object',\n additionalProperties: false,\n properties: {},\n };\n}\n\n// ============================================================================\n// 辅助函数(参考 moltbot 实现)\n// ============================================================================\n\n/**\n * 解析可选的分隔条目\n * @param value 输入字符串,支持逗号、分号、换行符分隔\n * @returns 解析后的字符串数组,如果输入为空则返回 undefined\n */\nexport function parseOptionalDelimitedEntries(value?: string): string[] | undefined {\n if (!value?.trim()) {\n return undefined;\n }\n const parsed = value\n .split(/[\\n,;]+/g)\n .map((entry) => entry.trim())\n .filter(Boolean);\n return parsed.length > 0 ? parsed : undefined;\n}\n\n/**\n * 构建账户范围的 DM 安全策略\n */\nexport function buildAccountScopedDmSecurityPolicy(params: {\n cfg: Record<string, unknown>;\n channelKey: string;\n accountId?: string | null;\n fallbackAccountId?: string | null;\n policy?: string | null;\n allowFrom?: Array<string | number> | null;\n defaultPolicy?: string;\n allowFromPathSuffix?: string;\n policyPathSuffix?: string;\n approveChannelId?: string;\n approveHint?: string;\n normalizeEntry?: (raw: string) => string;\n}): {\n policy: string;\n allowFrom: Array<string | number>;\n policyPath?: string;\n allowFromPath: string;\n approveHint: string;\n normalizeEntry?: (raw: string) => string;\n} {\n const DEFAULT_ACCOUNT_ID = \"default\";\n const resolvedAccountId = params.accountId ?? params.fallbackAccountId ?? DEFAULT_ACCOUNT_ID;\n const channelConfig = (params.cfg.channels as Record<string, unknown> | undefined)?.[\n params.channelKey\n ] as { accounts?: Record<string, unknown> } | undefined;\n const useAccountPath = Boolean(channelConfig?.accounts?.[resolvedAccountId]);\n const basePath = useAccountPath\n ? `channels.${params.channelKey}.accounts.${resolvedAccountId}.`\n : `channels.${params.channelKey}.`;\n const allowFromPath = `${basePath}${params.allowFromPathSuffix ?? \"\"}`;\n const policyPath =\n params.policyPathSuffix != null ? `${basePath}${params.policyPathSuffix}` : undefined;\n\n return {\n policy: params.policy ?? params.defaultPolicy ?? \"pairing\",\n allowFrom: params.allowFrom ?? [],\n policyPath,\n allowFromPath,\n approveHint:\n params.approveHint ?? formatPairingApproveHint(params.approveChannelId ?? params.channelKey),\n normalizeEntry: params.normalizeEntry,\n };\n}\n\n/**\n * 格式化配对审批提示信息(参考 moltbot 实现)\n * @param channelId 频道ID\n * @returns 配对审批提示字符串\n */\nexport function formatPairingApproveHint(channelId: string): string {\n const listCmd = `openclaw pairing list ${channelId}`;\n const approveCmd = `openclaw pairing approve ${channelId} <code>`;\n return `向 ${channelId} 机器人发送消息以完成配对审批(命令行:${listCmd} / ${approveCmd})`;\n}\n"],"names":["exports","path","fs","os","fileURLToPath","resolveStateDir"],"mappings":"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"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// ============================================================================
|
|
4
|
-
// 类型定义
|
|
5
|
-
// ============================================================================
|
|
6
|
-
// ============================================================================
|
|
7
|
-
// 常量
|
|
8
|
-
// ============================================================================
|
|
9
|
-
const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 天
|
|
10
|
-
const DEFAULT_MEMORY_MAX_SIZE = 200;
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// 核心实现
|
|
13
|
-
// ============================================================================
|
|
14
|
-
function createPersistentReqIdStore(accountId, options) {
|
|
15
|
-
const ttlMs = DEFAULT_TTL_MS;
|
|
16
|
-
const memoryMaxSize = DEFAULT_MEMORY_MAX_SIZE;
|
|
17
|
-
// 内存层:chatId → ReqIdEntry
|
|
18
|
-
const memory = new Map();
|
|
19
|
-
// ========== 内部辅助函数 ==========
|
|
20
|
-
/** 检查条目是否过期 */
|
|
21
|
-
function isExpired(entry, now) {
|
|
22
|
-
return now - entry.ts >= ttlMs;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* 内存容量控制:淘汰最旧的条目。
|
|
26
|
-
* 利用 Map 的插入顺序 + touch(先 delete 再 set) 实现类 LRU 效果。
|
|
27
|
-
*/
|
|
28
|
-
function pruneMemory() {
|
|
29
|
-
if (memory.size <= memoryMaxSize)
|
|
30
|
-
return;
|
|
31
|
-
const sorted = [...memory.entries()].sort((a, b) => a[1].ts - b[1].ts);
|
|
32
|
-
const toRemove = sorted.slice(0, memory.size - memoryMaxSize);
|
|
33
|
-
for (const [key] of toRemove) {
|
|
34
|
-
memory.delete(key);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// ========== 公开 API ==========
|
|
38
|
-
function set(chatId, reqId) {
|
|
39
|
-
const entry = { reqId, ts: Date.now() };
|
|
40
|
-
// touch:先删再设,保持 Map 插入顺序(类 LRU)
|
|
41
|
-
memory.delete(chatId);
|
|
42
|
-
memory.set(chatId, entry);
|
|
43
|
-
pruneMemory();
|
|
44
|
-
}
|
|
45
|
-
async function get(chatId) {
|
|
46
|
-
const now = Date.now();
|
|
47
|
-
// 仅查内存
|
|
48
|
-
const memEntry = memory.get(chatId);
|
|
49
|
-
if (memEntry && !isExpired(memEntry, now)) {
|
|
50
|
-
return memEntry.reqId;
|
|
51
|
-
}
|
|
52
|
-
if (memEntry) {
|
|
53
|
-
memory.delete(chatId); // 过期则删除
|
|
54
|
-
}
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
function getSync(chatId) {
|
|
58
|
-
const now = Date.now();
|
|
59
|
-
const entry = memory.get(chatId);
|
|
60
|
-
if (entry && !isExpired(entry, now)) {
|
|
61
|
-
return entry.reqId;
|
|
62
|
-
}
|
|
63
|
-
if (entry) {
|
|
64
|
-
memory.delete(chatId);
|
|
65
|
-
}
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
function del(chatId) {
|
|
69
|
-
memory.delete(chatId);
|
|
70
|
-
}
|
|
71
|
-
function clearMemory() {
|
|
72
|
-
memory.clear();
|
|
73
|
-
}
|
|
74
|
-
function memorySize() {
|
|
75
|
-
return memory.size;
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
set,
|
|
79
|
-
get,
|
|
80
|
-
getSync,
|
|
81
|
-
delete: del,
|
|
82
|
-
clearMemory,
|
|
83
|
-
memorySize,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
exports.createPersistentReqIdStore = createPersistentReqIdStore;
|
|
88
|
-
//# sourceMappingURL=reqid-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reqid-store.js","sources":["../../../../../src/reqid-store.ts"],"sourcesContent":["// ============================================================================\n// 类型定义\n// ============================================================================\n\n/** 单条 reqId 记录 */\ninterface ReqIdEntry {\n /** 请求 ID */\n reqId: string;\n /** 记录时间戳(毫秒) */\n ts: number;\n}\n\n/** Store 配置 */\ninterface ReqIdStoreOptions {\n /** TTL 毫秒数,超时的 reqId 视为过期(默认 7 天) */\n ttlMs?: number;\n /** 内存最大条目数(默认 200) */\n memoryMaxSize?: number;\n}\n\n// ============================================================================\n// 常量\n// ============================================================================\n\nconst DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 天\nconst DEFAULT_MEMORY_MAX_SIZE = 200;\n\n// ============================================================================\n// 公开接口\n// ============================================================================\n\nexport interface PersistentReqIdStore {\n /** 设置 chatId 对应的 reqId(仅写入内存) */\n set(chatId: string, reqId: string): void;\n /** 获取 chatId 对应的 reqId(仅内存) */\n get(chatId: string): Promise<string | undefined>;\n /** 同步获取 chatId 对应的 reqId(仅内存) */\n getSync(chatId: string): string | undefined;\n /** 删除 chatId 对应的 reqId */\n delete(chatId: string): void;\n /** 清空内存缓存 */\n clearMemory(): void;\n /** 返回内存中的条目数 */\n memorySize(): number;\n}\n\n// ============================================================================\n// 核心实现\n// ============================================================================\n\nexport function createPersistentReqIdStore(\n accountId: string,\n options?: ReqIdStoreOptions,\n): PersistentReqIdStore {\n const ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;\n const memoryMaxSize = options?.memoryMaxSize ?? DEFAULT_MEMORY_MAX_SIZE;\n\n // 内存层:chatId → ReqIdEntry\n const memory = new Map<string, ReqIdEntry>();\n\n // ========== 内部辅助函数 ==========\n\n /** 检查条目是否过期 */\n function isExpired(entry: ReqIdEntry, now: number): boolean {\n return ttlMs > 0 && now - entry.ts >= ttlMs;\n }\n\n /**\n * 内存容量控制:淘汰最旧的条目。\n * 利用 Map 的插入顺序 + touch(先 delete 再 set) 实现类 LRU 效果。\n */\n function pruneMemory(): void {\n if (memory.size <= memoryMaxSize) return;\n const sorted = [...memory.entries()].sort((a, b) => a[1].ts - b[1].ts);\n const toRemove = sorted.slice(0, memory.size - memoryMaxSize);\n for (const [key] of toRemove) {\n memory.delete(key);\n }\n }\n\n // ========== 公开 API ==========\n\n function set(chatId: string, reqId: string): void {\n const entry: ReqIdEntry = { reqId, ts: Date.now() };\n // touch:先删再设,保持 Map 插入顺序(类 LRU)\n memory.delete(chatId);\n memory.set(chatId, entry);\n pruneMemory();\n }\n\n async function get(chatId: string): Promise<string | undefined> {\n const now = Date.now();\n\n // 仅查内存\n const memEntry = memory.get(chatId);\n if (memEntry && !isExpired(memEntry, now)) {\n return memEntry.reqId;\n }\n if (memEntry) {\n memory.delete(chatId); // 过期则删除\n }\n\n return undefined;\n }\n\n function getSync(chatId: string): string | undefined {\n const now = Date.now();\n const entry = memory.get(chatId);\n if (entry && !isExpired(entry, now)) {\n return entry.reqId;\n }\n if (entry) {\n memory.delete(chatId);\n }\n return undefined;\n }\n\n function del(chatId: string): void {\n memory.delete(chatId);\n }\n\n function clearMemory(): void {\n memory.clear();\n }\n\n function memorySize(): number {\n return memory.size;\n }\n\n return {\n set,\n get,\n getSync,\n delete: del,\n clearMemory,\n memorySize,\n };\n}\n"],"names":[],"mappings":"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"}
|
package/dist/cjs/src/runtime.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
let runtime = null;
|
|
4
|
-
function setWeComRuntime(r) {
|
|
5
|
-
runtime = r;
|
|
6
|
-
}
|
|
7
|
-
function getWeComRuntime() {
|
|
8
|
-
if (!runtime) {
|
|
9
|
-
throw new Error("WeCom runtime not initialized - plugin not registered");
|
|
10
|
-
}
|
|
11
|
-
return runtime;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
exports.getWeComRuntime = getWeComRuntime;
|
|
15
|
-
exports.setWeComRuntime = setWeComRuntime;
|
|
16
|
-
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sources":["../../../../../src/runtime.ts"],"sourcesContent":["import type { PluginRuntime } from \"openclaw/plugin-sdk/core\";\n\nlet runtime: PluginRuntime | null = null;\n\nexport function setWeComRuntime(r: PluginRuntime): void {\n runtime = r;\n}\n\nexport function getWeComRuntime(): PluginRuntime {\n if (!runtime) {\n throw new Error(\"WeCom runtime not initialized - plugin not registered\");\n }\n return runtime;\n}\n"],"names":[],"mappings":";;AAEA,IAAI,OAAO,GAAyB,IAAI;AAElC,SAAU,eAAe,CAAC,CAAgB,EAAA;IAC9C,OAAO,GAAG,CAAC;AACb;SAEgB,eAAe,GAAA;IAC7B,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC;IAC1E;AACA,IAAA,OAAO,OAAO;AAChB;;;;;"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var path = require('node:path');
|
|
4
|
-
var os = require('node:os');
|
|
5
|
-
|
|
6
|
-
function _interopNamespaceDefault(e) {
|
|
7
|
-
var n = Object.create(null);
|
|
8
|
-
if (e) {
|
|
9
|
-
Object.keys(e).forEach(function (k) {
|
|
10
|
-
if (k !== 'default') {
|
|
11
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () { return e[k]; }
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
n.default = e;
|
|
20
|
-
return Object.freeze(n);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
24
|
-
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
|
|
25
|
-
|
|
26
|
-
/** 解析 openclaw 状态目录 */
|
|
27
|
-
function resolveStateDir() {
|
|
28
|
-
const stateOverride = process.env.OPENCLAW_STATE_DIR?.trim() || process.env.CLAWDBOT_STATE_DIR?.trim();
|
|
29
|
-
if (stateOverride)
|
|
30
|
-
return stateOverride;
|
|
31
|
-
return path__namespace.join(os__namespace.homedir(), ".openclaw");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
exports.resolveStateDir = resolveStateDir;
|
|
35
|
-
//# sourceMappingURL=state-dir-resolve.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state-dir-resolve.js","sources":["../../../../../src/state-dir-resolve.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/** 解析 openclaw 状态目录 */\nexport function resolveStateDir(): string {\n const stateOverride = process.env.OPENCLAW_STATE_DIR?.trim() || process.env.CLAWDBOT_STATE_DIR?.trim();\n if (stateOverride) return stateOverride;\n return path.join(os.homedir(), \".openclaw\");\n}\n"],"names":["path","os"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAGA;SACgB,eAAe,GAAA;AAC7B,IAAA,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE;AACtG,IAAA,IAAI,aAAa;AAAE,QAAA,OAAO,aAAa;IACvC,OAAOA,eAAI,CAAC,IAAI,CAACC,aAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC;AAC7C;;;;"}
|