@openclaw/qqbot 2026.5.7 → 2026.5.10-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.
@@ -1,8 +1,8 @@
1
- import { l as ensurePlatformAdapter, u as getBridgeLogger } from "./resolve-D_06fV6-.js";
1
+ import { l as ensurePlatformAdapter, u as getBridgeLogger } from "./resolve-Cm33TWZp.js";
2
2
  import { a as resolveApprovalTarget, n as buildExecApprovalText, r as buildPluginApprovalText, t as buildApprovalKeyboard } from "./approval-cg0SVahb.js";
3
- import { a as resolveQQBotAccount } from "./config-D6545NkC.js";
4
- import { a as resolveQQBotExecApprovalConfig, i as matchesQQBotApprovalAccount, o as shouldHandleQQBotExecApprovalRequest, r as isQQBotExecApprovalClientEnabled } from "./exec-approvals-COUsM6wZ.js";
5
- import { c as getMessageApi, t as accountToCreds } from "./sender-p-B14eLG.js";
3
+ import { a as resolveQQBotAccount } from "./config-BNAanXEH.js";
4
+ import { a as resolveQQBotExecApprovalConfig, i as matchesQQBotApprovalAccount, o as shouldHandleQQBotExecApprovalRequest, r as isQQBotExecApprovalClientEnabled } from "./exec-approvals-DgO1msIB.js";
5
+ import { c as getMessageApi, t as accountToCreds } from "./sender-C-TmIFow.js";
6
6
  import { resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
7
7
  import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
8
8
  //#region extensions/qqbot/src/bridge/approval/handler-runtime.ts
@@ -1,8 +1,9 @@
1
- import { i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, s as sanitizeFileName } from "./string-normalize-Ci6NM5DE.js";
2
- import { A as fileExistsAsync, C as debugLog, D as UPLOAD_PREPARE_FALLBACK_CODE, F as readFileAsync, L as formatErrorMessage, M as getFileTypeName, N as getImageMimeType, O as checkFileSize, P as getMaxUploadSize, S as debugError, T as UploadDailyLimitExceededError, g as sendText$1, h as sendMedia$1, j as formatFileSize, k as downloadFile, t as accountToCreds, u as initApiConfig, w as debugWarn } from "./sender-p-B14eLG.js";
3
- import { c as getQQBotMediaDir, d as isLocalPath, m as resolveQQBotPayloadLocalFilePath, o as getQQBotDataDir, p as normalizePath, r as parseTarget$1 } from "./target-parser-Y0prnrXD.js";
4
- import fs from "node:fs";
1
+ import { i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, s as sanitizeFileName } from "./string-normalize-BzzzPOeb.js";
2
+ import { A as fileExistsAsync, C as debugWarn, E as UPLOAD_PREPARE_FALLBACK_CODE, F as readFileAsync, L as formatErrorMessage, M as getFileTypeName, N as getImageMimeType, O as checkFileSize, P as getMaxUploadSize, S as debugLog, g as sendText$1, h as sendMedia$1, j as formatFileSize, k as downloadFile, t as accountToCreds, u as initApiConfig, w as UploadDailyLimitExceededError, x as debugError } from "./sender-C-TmIFow.js";
3
+ import { c as getQQBotMediaDir, d as isLocalPath, m as resolveQQBotPayloadLocalFilePath, o as getQQBotDataDir, p as normalizePath, r as parseTarget$1 } from "./target-parser-CTNFSKb1.js";
4
+ import { pathExistsSync, resolveLocalPathFromRootsSync } from "openclaw/plugin-sdk/security-runtime";
5
5
  import path from "node:path";
6
+ import { getFileExtension } from "openclaw/plugin-sdk/media-mime";
6
7
  //#region \0rolldown/runtime.js
7
8
  var __defProp = Object.defineProperty;
8
9
  var __exportAll = (all, no_symbols) => {
@@ -239,53 +240,22 @@ const qqBotMediaKindLabel = {
239
240
  function isHttpOrDataSource(pathValue) {
240
241
  return pathValue.startsWith("http://") || pathValue.startsWith("https://") || pathValue.startsWith("data:");
241
242
  }
242
- function isPathWithinRoot(candidate, root) {
243
- const relative = path.relative(root, candidate);
244
- return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
245
- }
246
243
  function resolveMissingPathWithinMediaRoot(normalizedPath) {
247
244
  const resolvedCandidate = path.resolve(normalizedPath);
248
- if (fs.existsSync(resolvedCandidate)) return null;
249
- const allowedRoot = path.resolve(getQQBotMediaDir());
250
- let canonicalAllowedRoot;
251
- try {
252
- canonicalAllowedRoot = fs.realpathSync(allowedRoot);
253
- } catch {
254
- return null;
255
- }
256
- const missingSegments = [];
257
- let cursor = resolvedCandidate;
258
- while (!fs.existsSync(cursor)) {
259
- const parent = path.dirname(cursor);
260
- if (parent === cursor) break;
261
- missingSegments.unshift(path.basename(cursor));
262
- cursor = parent;
263
- }
264
- if (!fs.existsSync(cursor)) return null;
265
- let canonicalCursor;
266
- try {
267
- canonicalCursor = fs.realpathSync(cursor);
268
- } catch {
269
- return null;
270
- }
271
- const canonicalCandidate = missingSegments.length > 0 ? path.join(canonicalCursor, ...missingSegments) : canonicalCursor;
272
- return isPathWithinRoot(canonicalCandidate, canonicalAllowedRoot) ? canonicalCandidate : null;
245
+ if (pathExistsSync(resolvedCandidate)) return null;
246
+ return resolveLocalPathFromRootsSync({
247
+ filePath: resolvedCandidate,
248
+ roots: [getQQBotMediaDir()],
249
+ label: "QQ Bot media storage",
250
+ allowMissing: true
251
+ })?.path ?? null;
273
252
  }
274
253
  function resolveExistingPathWithinRoots(normalizedPath, allowedRoots) {
275
- const resolvedCandidate = path.resolve(normalizedPath);
276
- if (!fs.existsSync(resolvedCandidate)) return null;
277
- let canonicalCandidate;
278
- try {
279
- canonicalCandidate = fs.realpathSync(resolvedCandidate);
280
- } catch {
281
- return null;
282
- }
283
- for (const root of allowedRoots) {
284
- const resolvedRoot = path.resolve(root);
285
- const canonicalRoot = fs.existsSync(resolvedRoot) ? fs.realpathSync(resolvedRoot) : resolvedRoot;
286
- if (isPathWithinRoot(canonicalCandidate, canonicalRoot)) return canonicalCandidate;
287
- }
288
- return null;
254
+ return resolveLocalPathFromRootsSync({
255
+ filePath: normalizedPath,
256
+ roots: allowedRoots,
257
+ label: "QQ Bot local roots"
258
+ })?.path ?? null;
289
259
  }
290
260
  function resolveOutboundMediaPath(rawPath, mediaKind, options = {}) {
291
261
  const normalizedPath = normalizePath(rawPath);
@@ -1017,24 +987,15 @@ const VIDEO_EXTENSIONS = new Set([
1017
987
  ".flv",
1018
988
  ".wmv"
1019
989
  ]);
1020
- /**
1021
- * Extract a lowercase file extension from a path or URL, ignoring query and hash.
1022
- */
1023
- function getCleanExtension(filePath) {
1024
- const cleanPath = filePath.split("?")[0].split("#")[0];
1025
- const lastDot = cleanPath.lastIndexOf(".");
1026
- if (lastDot < 0) return "";
1027
- return cleanPath.slice(lastDot).toLowerCase();
1028
- }
1029
990
  /** Check whether a file is an image using MIME first and extension as fallback. */
1030
991
  function isImageFile$1(filePath, mimeType) {
1031
992
  if (mimeType?.startsWith("image/")) return true;
1032
- return IMAGE_EXTENSIONS.has(getCleanExtension(filePath));
993
+ return IMAGE_EXTENSIONS.has(getFileExtension(filePath) ?? "");
1033
994
  }
1034
995
  /** Check whether a file is a video using MIME first and extension as fallback. */
1035
996
  function isVideoFile$1(filePath, mimeType) {
1036
997
  if (mimeType?.startsWith("video/")) return true;
1037
- return VIDEO_EXTENSIONS.has(getCleanExtension(filePath));
998
+ return VIDEO_EXTENSIONS.has(getFileExtension(filePath) ?? "");
1038
999
  }
1039
1000
  //#endregion
1040
1001
  //#region extensions/qqbot/src/engine/messaging/outbound.ts
@@ -1,7 +1,8 @@
1
- import { C as debugLog } from "./sender-p-B14eLG.js";
2
- import { a as getHomeDir, f as isWindows, l as getQQBotMediaPath, o as getQQBotDataDir } from "./target-parser-Y0prnrXD.js";
1
+ import { S as debugLog } from "./sender-C-TmIFow.js";
2
+ import { a as getHomeDir, f as isWindows, l as getQQBotMediaPath, o as getQQBotDataDir } from "./target-parser-CTNFSKb1.js";
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
+ import { loadJsonFile } from "openclaw/plugin-sdk/json-store";
5
6
  import { AsyncLocalStorage } from "node:async_hooks";
6
7
  //#region extensions/qqbot/src/engine/commands/builtin/state.ts
7
8
  let _resolveVersion = () => "unknown";
@@ -427,9 +428,7 @@ function getConfiguredLogFiles() {
427
428
  "clawdbot",
428
429
  "moltbot"
429
430
  ]) try {
430
- const cfgPath = path.join(homeDir, `.${cli}`, `${cli}.json`);
431
- if (!fs.existsSync(cfgPath)) continue;
432
- const logFile = JSON.parse(fs.readFileSync(cfgPath, "utf8"))?.logging?.file;
431
+ const logFile = loadJsonFile(path.join(homeDir, `.${cli}`, `${cli}.json`))?.logging?.file;
433
432
  if (logFile && typeof logFile === "string") files.push(path.resolve(logFile));
434
433
  break;
435
434
  } catch {}
@@ -501,6 +500,27 @@ function collectCandidateLogDirs() {
501
500
  ]) pushDir(path.join(tmpRoot, name));
502
501
  return Array.from(dirs);
503
502
  }
503
+ function addCollisionSuffix(filePath, suffix) {
504
+ const ext = path.extname(filePath);
505
+ const baseName = path.basename(filePath, ext);
506
+ return path.join(path.dirname(filePath), `${baseName}-${suffix}${ext}`);
507
+ }
508
+ function writeNewTextFileSync(filePath, contents) {
509
+ for (let suffix = 1; suffix <= 100; suffix++) {
510
+ const candidate = suffix === 1 ? filePath : addCollisionSuffix(filePath, suffix);
511
+ try {
512
+ fs.writeFileSync(candidate, contents, {
513
+ encoding: "utf8",
514
+ flag: "wx"
515
+ });
516
+ return candidate;
517
+ } catch (error) {
518
+ if (typeof error === "object" && error && "code" in error && error.code === "EEXIST") continue;
519
+ throw error;
520
+ }
521
+ }
522
+ throw new Error(`Could not find an unused log export filename near ${filePath}`);
523
+ }
504
524
  function collectRecentLogFiles(logDirs) {
505
525
  const candidates = [];
506
526
  const dedupe = /* @__PURE__ */ new Set();
@@ -626,8 +646,7 @@ function buildBotLogsResult() {
626
646
  if (lines.length === 0) return `⚠️ 找到了日志文件,但无法读取。请检查文件权限。`;
627
647
  const tmpDir = getQQBotDataDir("downloads");
628
648
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
629
- const tmpFile = path.join(tmpDir, `bot-logs-${timestamp}.txt`);
630
- fs.writeFileSync(tmpFile, lines.join("\n"), "utf8");
649
+ const tmpFile = writeNewTextFileSync(path.join(tmpDir, `bot-logs-${timestamp}.txt`), lines.join("\n"));
631
650
  const fileCount = recentFiles.length;
632
651
  const topSources = Array.from(new Set(recentFiles.map((item) => item.sourceDir))).slice(0, 3);
633
652
  let summaryText = `共 ${fileCount} 个日志文件,包含 ${totalIncluded} 行内容`;
@@ -1,4 +1,4 @@
1
- import { a as normalizeStringifiedOptionalString, c as getPlatformAdapter, d as registerPlatformAdapterFactory, l as hasPlatformAdapter, o as readStringField, r as normalizeOptionalLowercaseString, t as asOptionalObjectRecord, u as registerPlatformAdapter } from "./string-normalize-Ci6NM5DE.js";
1
+ import { a as normalizeStringifiedOptionalString, c as getPlatformAdapter, d as registerPlatformAdapterFactory, l as hasPlatformAdapter, o as readStringField, r as normalizeOptionalLowercaseString, t as asOptionalObjectRecord, u as registerPlatformAdapter } from "./string-normalize-BzzzPOeb.js";
2
2
  import { hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
3
3
  import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
4
4
  //#region extensions/qqbot/src/bridge/logger.ts
@@ -1,4 +1,4 @@
1
- import { _ as setOpenClawVersion } from "./sender-p-B14eLG.js";
1
+ import { _ as setOpenClawVersion } from "./sender-C-TmIFow.js";
2
2
  import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
3
3
  //#region extensions/qqbot/src/bridge/runtime.ts
4
4
  const { setRuntime: _setRuntime, getRuntime: getQQBotRuntime } = createPluginRuntimeStore({
@@ -1,2 +1,2 @@
1
- import { r as setQQBotRuntime, t as getQQBotRuntime } from "./runtime-BJAS3eXW.js";
1
+ import { r as setQQBotRuntime, t as getQQBotRuntime } from "./runtime-CHGblcVc.js";
2
2
  export { getQQBotRuntime, setQQBotRuntime };