@wecom/wecom-openclaw-plugin 2026.4.1-beta.0 → 2026.4.1-beta.1

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.
@@ -4,6 +4,7 @@ var fs = require('node:fs/promises');
4
4
  var path = require('node:path');
5
5
  var os = require('node:os');
6
6
  var node_url = require('node:url');
7
+ var stateDirResolve = require('./state-dir-resolve.js');
7
8
 
8
9
  function _interopNamespaceDefault(e) {
9
10
  var n = Object.create(null);
@@ -347,13 +348,6 @@ function addWildcardAllowFrom(allowFrom) {
347
348
  // ============================================================================
348
349
  // getDefaultMediaLocalRoots —— 获取默认媒体本地路径白名单
349
350
  // ============================================================================
350
- /** 解析 openclaw 状态目录 */
351
- function resolveStateDir() {
352
- const stateOverride = process.env.OPENCLAW_STATE_DIR?.trim() || process.env.CLAWDBOT_STATE_DIR?.trim();
353
- if (stateOverride)
354
- return stateOverride;
355
- return path__namespace.join(os__namespace.homedir(), ".openclaw");
356
- }
357
351
  /**
358
352
  * 获取默认媒体本地路径白名单(兼容入口)
359
353
  *
@@ -370,7 +364,7 @@ async function getDefaultMediaLocalRoots() {
370
364
  }
371
365
  }
372
366
  // fallback: 手动构建默认白名单
373
- const stateDir = path__namespace.resolve(resolveStateDir());
367
+ const stateDir = path__namespace.resolve(stateDirResolve.resolveStateDir());
374
368
  return [
375
369
  path__namespace.join(stateDir, "media"),
376
370
  path__namespace.join(stateDir, "agents"),
@@ -1 +1 @@
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\";\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/** 解析 openclaw 状态目录 */\nfunction 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\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"],"mappings":"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"}
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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"}
@@ -0,0 +1,35 @@
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
@@ -0,0 +1 @@
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;;;;"}
@@ -2,6 +2,7 @@ import * as fs from 'node:fs/promises';
2
2
  import * as path from 'node:path';
3
3
  import * as os from 'node:os';
4
4
  import { fileURLToPath } from 'node:url';
5
+ import { resolveStateDir } from './state-dir-resolve.js';
5
6
 
6
7
  /**
7
8
  * openclaw plugin-sdk 高版本方法兼容层
@@ -324,13 +325,6 @@ function addWildcardAllowFrom(allowFrom) {
324
325
  // ============================================================================
325
326
  // getDefaultMediaLocalRoots —— 获取默认媒体本地路径白名单
326
327
  // ============================================================================
327
- /** 解析 openclaw 状态目录 */
328
- function resolveStateDir() {
329
- const stateOverride = process.env.OPENCLAW_STATE_DIR?.trim() || process.env.CLAWDBOT_STATE_DIR?.trim();
330
- if (stateOverride)
331
- return stateOverride;
332
- return path.join(os.homedir(), ".openclaw");
333
- }
334
328
  /**
335
329
  * 获取默认媒体本地路径白名单(兼容入口)
336
330
  *
@@ -1 +1 @@
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\";\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/** 解析 openclaw 状态目录 */\nfunction 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\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"],"mappings":"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"}
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"],"mappings":";;;;;;AAAA;;;;;;;;AAQG;AAQI,MAAM,kBAAkB,GAAG;AAoClC,MAAM,SAAS,GAAwB,OAAO,0BAA0B;AACrE,KAAA,IAAI,CAAC,CAAC,GAAQ,KAAI;IACjB,MAAMA,SAAO,GAAe,EAAE;AAC9B,IAAA,IAAI,OAAO,GAAG,CAAC,wBAAwB,KAAK,UAAU,EAAE;AACtD,QAAAA,SAAO,CAAC,wBAAwB,GAAG,GAAG,CAAC,wBAAwB;IACjE;AACA,IAAA,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,UAAU,EAAE;AACxC,QAAAA,SAAO,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU;IACrC;AACA,IAAA,IAAI,OAAO,GAAG,CAAC,yBAAyB,KAAK,UAAU,EAAE;AACvD,QAAAA,SAAO,CAAC,yBAAyB,GAAG,GAAG,CAAC,yBAAyB;IACnE;AACA,IAAA,IAAI,OAAO,GAAG,CAAC,oBAAoB,KAAK,UAAU,EAAE;AAClD,QAAAA,SAAO,CAAC,oBAAoB,GAAG,GAAG,CAAC,oBAAoB;IACzD;AACA,IAAA,OAAOA,SAAO;AAChB,CAAC;KACA,KAAK,CAAC,MAAK;;AAEV,IAAA,OAAO,EAAgB;AACzB,CAAC,CAAC;AAEJ;AACA,IAAI,2BAA4E;AAE1C,OAAO,2BAA2B;AACrE,KAAA,IAAI,CAAC,CAAC,GAAQ,KAAI;AACjB,IAAA,IAAI,OAAO,GAAG,CAAC,oBAAoB,KAAK,UAAU,EAAE;AAClD,QAAA,2BAA2B,GAAG,GAAG,CAAC,oBAAoB;IACxD;AACF,CAAC;AACA,KAAA,KAAK,CAAC,MAAK,EAA8B,CAAC;AAE7C;AACA,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,KAAI;AACrB,IAAA,IAAI,CAAC,2BAA2B,IAAI,GAAG,CAAC,oBAAoB,EAAE;AAC5D,QAAA,2BAA2B,GAAG,GAAG,CAAC,oBAAoB;IACxD;AACF,CAAC,CAAC;AAEF;AACA;AACA;AAEA,MAAM,WAAW,GAA2B;AAC1C,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,MAAM,EAAE,YAAY;AACpB,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,MAAM,EAAE,YAAY;AACpB,IAAA,MAAM,EAAE,aAAa;AACrB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,MAAM,EAAE,iBAAiB;AACzB,IAAA,MAAM,EAAE,iBAAiB;AACzB,IAAA,OAAO,EAAE,kBAAkB;AAC3B,IAAA,MAAM,EAAE,iBAAiB;AACzB,IAAA,KAAK,EAAE,kBAAkB;AACzB,IAAA,MAAM,EAAE,mBAAmB;AAC3B,IAAA,KAAK,EAAE,6BAA6B;AACpC,IAAA,MAAM,EAAE,qBAAqB;AAC7B,IAAA,MAAM,EAAE,oBAAoB;AAC5B,IAAA,MAAM,EAAE,0BAA0B;AAClC,IAAA,MAAM,EAAE,+BAA+B;AACvC,IAAA,OAAO,EAAE,yEAAyE;AAClF,IAAA,OAAO,EAAE,mEAAmE;AAC5E,IAAA,OAAO,EAAE,2EAA2E;AACpF,IAAA,MAAM,EAAE,UAAU;AAClB,IAAA,MAAM,EAAE,YAAY;AACpB,IAAA,KAAK,EAAE,eAAe;AACtB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,MAAM,EAAE,iBAAiB;AACzB,IAAA,MAAM,EAAE,WAAW;AACnB,IAAA,MAAM,EAAE,eAAe;CACxB;AAED;AACA,eAAe,mBAAmB,CAAC,MAAc,EAAA;AAC/C,IAAA,IAAI;QACF,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,OAAO,WAAW,CAAC;AACxD,QAAA,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC;AAC7C,QAAA,OAAO,IAAI,EAAE,IAAI,IAAI,SAAS;IAChC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,SAAS;IAClB;AACF;AAEA;AACA,eAAe,kBAAkB,CAAC,IAAuB,EAAA;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS;AACjF,IAAA,MAAM,OAAO,GAAG,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,SAAS;AAElD,IAAA,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS;AAEhF,IAAA,MAAM,SAAS,GAAG,CAAC,CAAU,KAC3B,CAAC,CAAC,IAAI,CAAC,KAAK,0BAA0B,IAAI,CAAC,KAAK,iBAAiB;AAEnE,IAAA,IAAI,OAAO,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AAChD,QAAA,OAAO,OAAO;IAChB;IACA,IAAI,OAAO,EAAE;AACX,QAAA,OAAO,OAAO;IAChB;IACA,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE;IACzE,IAAI,UAAU,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;AACxC,QAAA,OAAO,UAAU;IACnB;IACA,IAAI,OAAO,EAAE;AACX,QAAA,OAAO,OAAO;IAChB;IACA,IAAI,UAAU,EAAE;AACd,QAAA,OAAO,UAAU;IACnB;AACA,IAAA,OAAO,SAAS;AAClB;AAEA;;;;;;;;AAQG;AACI,eAAe,UAAU,CAC9B,YAAwC,EAAA;AAExC,IAAA,MAAM,GAAG,GAAG,MAAM,SAAS;AAE3B,IAAA,MAAM,IAAI,GAAsB,MAAM,CAAC,QAAQ,CAAC,YAAY;AAC1D,UAAE,EAAE,MAAM,EAAE,YAAY;UACtB,YAAY;AAEhB,IAAA,IAAI,GAAG,CAAC,UAAU,EAAE;AAClB,QAAA,IAAI;AACF,YAAA,OAAO,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QACnC;AAAE,QAAA,MAAM;;QAER;IACF;AACA,IAAA,OAAO,kBAAkB,CAAC,IAAI,CAAC;AACjC;AAEA;AACA;AACA;AAEA;AACA,eAAe,uBAAuB,CACpC,SAAiB,EACjB,UAAyC,EAAA;IAEzC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;AAC1C,QAAA,MAAM,IAAI,KAAK,CAAC,uDAAuD,SAAS,CAAA,CAAE,CAAC;IACrF;AAEA,IAAA,IAAI,QAAgB;AACpB,IAAA,IAAI;QACF,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;IACzC;AAAE,IAAA,MAAM;AACN,QAAA,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;IACpC;AAEA,IAAA,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE;AAC7B,QAAA,IAAI,YAAoB;AACxB,QAAA,IAAI;YACF,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxC;AAAE,QAAA,MAAM;AACN,YAAA,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QACnC;QACA,IAAI,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE;YAClD;QACF;AACA,QAAA,IAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,CAAC,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;YAC7E;QACF;IACF;AAEA,IAAA,MAAM,IAAI,KAAK,CAAC,uDAAuD,SAAS,CAAA,CAAE,CAAC;AACrF;AAEA;AACA,eAAe,gBAAgB,CAC7B,GAAW,EACX,QAAiB,EAAA;AAEjB,IAAA,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACpD,IAAA,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;AACX,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,2BAAA,EAA8B,GAAG,CAAA,OAAA,EAAU,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAA,CAAE,CAAC;IAC5F;AAEA,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IACnD,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,QAAQ,EAAE;AACxC,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,WAAA,EAAc,GAAG,CAAA,mBAAA,EAAsB,MAAM,CAAC,MAAM,CAAA,GAAA,EAAM,QAAQ,CAAA,CAAA,CAAG,CAAC;IACxF;IAEA,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE;AAE3E,IAAA,IAAI,QAA4B;IAChC,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAC1D,IAAI,WAAW,EAAE;QACf,MAAM,KAAK,GAAG,2CAA2C,CAAC,IAAI,CAAC,WAAW,CAAC;AAC3E,QAAA,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AACd,YAAA,IAAI;gBACF,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACpF;AAAE,YAAA,MAAM;gBACN,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAChE;QACF;IACF;IACA,IAAI,CAAC,QAAQ,EAAE;AACb,QAAA,IAAI;AACF,YAAA,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC3C,YAAA,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,QAAQ,GAAG,IAAI;QACjD;AAAE,QAAA,MAAM,eAAe;IACzB;AAEA,IAAA,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,IAAI,GAAG,EAAE,CAAC;AAE/F,IAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE;AAC1C;AAEA;AACA,SAAS,eAAe,CAAC,CAAS,EAAA;AAChC,IAAA,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACrB,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5C;AACA,IAAA,OAAO,CAAC;AACV;AAEA;AACA,eAAe,gCAAgC,CAC7C,QAAgB,EAChB,UAAoC,EAAE,EAAA;AAEtC,IAAA,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,OAAO;;IAG7C,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;;AAGpD,IAAA,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;AAClC,QAAA,IAAI;AACF,YAAA,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;QACpC;AAAE,QAAA,MAAM;AACN,YAAA,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAA,CAAE,CAAC;QACrD;IACF;;AAGA,IAAA,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAClC,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC;QAC1D,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B;IACH;;AAGA,IAAA,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC5B,QAAA,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC;IACtC;;AAGA,IAAA,MAAM,uBAAuB,CAAC,QAAQ,EAAE,eAAe,CAAC;;AAGxD,IAAA,IAAI,IAAY;AAChB,IAAA,IAAI;QACF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;AACpC,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;AAClB,YAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,CAAA,CAAE,CAAC;QAChE;QACA,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACpC;IAAE,OAAO,GAAQ,EAAE;AACjB,QAAA,IAAI,GAAG,EAAE,IAAI,KAAK,QAAQ,EAAE;AAC1B,YAAA,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAA,CAAE,CAAC;QAC5D;AACA,QAAA,MAAM,GAAG;IACX;IAEA,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE;QACtC,MAAM,IAAI,KAAK,CAAC,CAAA,8BAAA,EAAiC,IAAI,CAAC,MAAM,CAAA,GAAA,EAAM,QAAQ,CAAA,CAAA,CAAG,CAAC;IAChF;AAEA,IAAA,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,SAAS;IAErD,OAAO;AACL,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,WAAW,EAAE,IAAI;QACjB,QAAQ;KACT;AACH;AAEA;;;;;AAKG;AACI,eAAe,wBAAwB,CAC5C,QAAgB,EAChB,UAAoC,EAAE,EAAA;AAEtC,IAAA,MAAM,GAAG,GAAG,MAAM,SAAS;AAE3B,IAAA,IAAI,GAAG,CAAC,wBAAwB,EAAE;QAChC,OAAO,GAAG,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC;IACxD;AACA,IAAA,OAAO,gCAAgC,CAAC,QAAQ,EAAE,OAAO,CAAC;AAC5D;AAEA;AACA;AACA;AAEA;AACA,SAAS,4BAA4B,CAAC,SAAmB,EAAA;AACvD,IAAA,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC3B,QAAA,OAAO,SAAS;IAClB;AACA,IAAA,OAAO,CAAC,GAAG,SAAS,EAAE,GAAG,CAAC;AAC5B;AAEA;;;;;;;;AAQG;AACG,SAAU,oBAAoB,CAAC,SAAmB,EAAA;IACtD,IAAI,2BAA2B,EAAE;AAC/B,QAAA,IAAI;AACF,YAAA,OAAO,2BAA2B,CAAC,SAAS,CAAC;QAC/C;AAAE,QAAA,MAAM;;QAER;IACF;AACA,IAAA,OAAO,4BAA4B,CAAC,SAAS,CAAC;AAChD;AAEA;AACA;AACA;AAEA;;;;AAIG;AACI,eAAe,yBAAyB,GAAA;AAC7C,IAAA,MAAM,GAAG,GAAG,MAAM,SAAS;AAE3B,IAAA,IAAI,GAAG,CAAC,yBAAyB,EAAE;AACjC,QAAA,IAAI;AACF,YAAA,OAAO,GAAG,CAAC,yBAAyB,EAAE;QACxC;AAAE,QAAA,MAAM;;QAER;IACF;;IAGA,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IAChD,OAAO;AACL,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC;AAC5B,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC;AAChC,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC;KACjC;AACH;SAEgB,uBAAuB,GAAA;IACrC,OAAO;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,oBAAoB,EAAE,KAAK;AAC3B,QAAA,UAAU,EAAE,EAAE;KACf;AACH;AAsEA;;;;AAIG;AACG,SAAU,wBAAwB,CAAC,SAAiB,EAAA;AACxD,IAAA,MAAM,OAAO,GAAG,CAAA,sBAAA,EAAyB,SAAS,EAAE;AACpD,IAAA,MAAM,UAAU,GAAG,CAAA,yBAAA,EAA4B,SAAS,SAAS;AACjE,IAAA,OAAO,KAAK,SAAS,CAAA,oBAAA,EAAuB,OAAO,CAAA,GAAA,EAAM,UAAU,GAAG;AACxE;;;;"}
@@ -0,0 +1,13 @@
1
+ import * as path from 'node:path';
2
+ import * as os from 'node:os';
3
+
4
+ /** 解析 openclaw 状态目录 */
5
+ function resolveStateDir() {
6
+ const stateOverride = process.env.OPENCLAW_STATE_DIR?.trim() || process.env.CLAWDBOT_STATE_DIR?.trim();
7
+ if (stateOverride)
8
+ return stateOverride;
9
+ return path.join(os.homedir(), ".openclaw");
10
+ }
11
+
12
+ export { resolveStateDir };
13
+ //# sourceMappingURL=state-dir-resolve.js.map
@@ -0,0 +1 @@
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":[],"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,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC;AAC7C;;;;"}
@@ -0,0 +1,2 @@
1
+ /** 解析 openclaw 状态目录 */
2
+ export declare function resolveStateDir(): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wecom/wecom-openclaw-plugin",
3
- "version": "2026.4.1-beta.0",
3
+ "version": "2026.4.1-beta.1",
4
4
  "type": "module",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",