@jerryliang122/openclaw-qqbot 1.0.8 → 2.0.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/dist/index.cjs CHANGED
@@ -8259,7 +8259,7 @@ var init_outbound_service = __esm({
8259
8259
 
8260
8260
  // src/utils/pkg-version.ts
8261
8261
  function getPackageVersion() {
8262
- return true ? "1.0.8" : "unknown";
8262
+ return true ? "2.0.0" : "unknown";
8263
8263
  }
8264
8264
  function getOpenclawVersion(runtimeVersion) {
8265
8265
  return runtimeVersion && runtimeVersion !== "unknown" ? runtimeVersion : "unknown";
@@ -12904,70 +12904,42 @@ init_webhook_server_node();
12904
12904
  init_webhook_verify();
12905
12905
 
12906
12906
  // src/utils/stt.ts
12907
- var fs18 = __toESM(require("fs"), 1);
12908
12907
  var path16 = __toESM(require("path"), 1);
12908
+ var import_media_understanding_runtime = require("openclaw/plugin-sdk/media-understanding-runtime");
12909
12909
  function shouldUsePlatformAsr(cfg) {
12910
12910
  const channels = asRecord(cfg.channels);
12911
12911
  const qqbot = asRecord(channels?.qqbot);
12912
- return asRecord(qqbot?.stt)?.asrFallback === true;
12912
+ return asRecord(qqbot?.stt)?.asrFallback !== false;
12913
12913
  }
12914
- function resolveSTTConfig(cfg) {
12914
+ function isFrameworkSttConfigured(cfg) {
12915
12915
  const channels = asRecord(cfg.channels);
12916
12916
  const qqbot = asRecord(channels?.qqbot);
12917
- const sttCfg = asRecord(qqbot?.stt);
12918
- if (sttCfg?.enabled === false) {
12919
- return null;
12920
- }
12921
- const models = asRecord(cfg.models);
12922
- const providers = asRecord(models?.providers);
12923
- if (sttCfg) {
12924
- const providerId = readString(sttCfg, "provider") ?? "openai";
12925
- const providerCfg = asRecord(providers?.[providerId]);
12926
- const baseUrl = readString(sttCfg, "baseUrl") ?? readString(providerCfg, "baseUrl");
12927
- const apiKey = readString(sttCfg, "apiKey") ?? readString(providerCfg, "apiKey");
12928
- const model = readString(sttCfg, "model") ?? "whisper-1";
12929
- if (baseUrl && apiKey) {
12930
- return { enabled: true, baseUrl: baseUrl.replace(/\/+$/, ""), apiKey, model };
12931
- }
12917
+ if (asRecord(qqbot?.stt)?.enabled === false) {
12918
+ return false;
12932
12919
  }
12933
12920
  const tools = asRecord(cfg.tools);
12934
12921
  const media = asRecord(tools?.media);
12935
12922
  const audio = asRecord(media?.audio);
12936
- const audioModels = audio?.models;
12937
- const audioModelEntry = Array.isArray(audioModels) ? asRecord(audioModels[0]) : void 0;
12938
- if (audioModelEntry) {
12939
- const providerId = readString(audioModelEntry, "provider") ?? "openai";
12940
- const providerCfg = asRecord(providers?.[providerId]);
12941
- const baseUrl = readString(audioModelEntry, "baseUrl") ?? readString(providerCfg, "baseUrl");
12942
- const apiKey = readString(audioModelEntry, "apiKey") ?? readString(providerCfg, "apiKey");
12943
- const model = readString(audioModelEntry, "model") ?? "whisper-1";
12944
- if (baseUrl && apiKey) {
12945
- return { enabled: true, baseUrl: baseUrl.replace(/\/+$/, ""), apiKey, model };
12946
- }
12923
+ if (!audio || audio.enabled === false) {
12924
+ return false;
12947
12925
  }
12948
- return null;
12926
+ return Array.isArray(audio.models) && audio.models.length > 0;
12949
12927
  }
12950
- async function transcribeAudio(audioPath, cfg) {
12951
- const sttCfg = resolveSTTConfig(cfg);
12952
- if (!sttCfg) {
12953
- return null;
12954
- }
12955
- const fileBuffer = fs18.readFileSync(audioPath);
12956
- const fileName = sanitizeFileName2(path16.basename(audioPath));
12957
- const mime = guessMimeType(fileName);
12958
- const form = new FormData();
12959
- form.append("file", new Blob([fileBuffer], { type: mime }), fileName);
12960
- form.append("model", sttCfg.model);
12961
- const resp = await fetch(`${sttCfg.baseUrl}/audio/transcriptions`, {
12962
- method: "POST",
12963
- headers: { Authorization: `Bearer ${sttCfg.apiKey}` },
12964
- body: form
12928
+ function hasLegacySttCredentials(cfg) {
12929
+ const channels = asRecord(cfg.channels);
12930
+ const qqbot = asRecord(channels?.qqbot);
12931
+ const stt = asRecord(qqbot?.stt);
12932
+ if (!stt) return false;
12933
+ return ["provider", "baseUrl", "apiKey", "model"].some(
12934
+ (key2) => typeof stt[key2] === "string" && stt[key2].trim().length > 0
12935
+ );
12936
+ }
12937
+ async function transcribeAudioViaFramework(audioPath, cfg) {
12938
+ const result = await (0, import_media_understanding_runtime.transcribeAudioFile)({
12939
+ filePath: audioPath,
12940
+ cfg,
12941
+ mime: guessMimeType(audioPath)
12965
12942
  });
12966
- if (!resp.ok) {
12967
- const detail = await resp.text().catch(() => "");
12968
- throw new Error(`STT failed (HTTP ${resp.status}): ${detail.slice(0, 300)}`);
12969
- }
12970
- const result = await resp.json();
12971
12943
  return result.text?.trim() || null;
12972
12944
  }
12973
12945
  function asRecord(value) {
@@ -12976,16 +12948,6 @@ function asRecord(value) {
12976
12948
  }
12977
12949
  return void 0;
12978
12950
  }
12979
- function readString(obj, key2) {
12980
- const val = obj?.[key2];
12981
- if (typeof val === "string" && val.trim()) {
12982
- return val.trim();
12983
- }
12984
- return void 0;
12985
- }
12986
- function sanitizeFileName2(name) {
12987
- return name.replace(/[^a-zA-Z0-9._-]/g, "_");
12988
- }
12989
12951
  function guessMimeType(fileName) {
12990
12952
  const ext = path16.extname(fileName).toLowerCase();
12991
12953
  const mimeMap = {
@@ -13061,8 +13023,9 @@ function attachmentProcessor(opts) {
13061
13023
  };
13062
13024
  }
13063
13025
  async function processAttachments(attachments, cfg, log5) {
13064
- const sttCfg = resolveSTTConfig(cfg);
13065
13026
  const usePlatformAsr = shouldUsePlatformAsr(cfg);
13027
+ const sttConfigured = isFrameworkSttConfigured(cfg);
13028
+ warnLegacySttCredentials(cfg, log5);
13066
13029
  const audioPolicy = resolveAudioPolicy(cfg);
13067
13030
  const imageUrls = [];
13068
13031
  const otherParts = [];
@@ -13080,7 +13043,7 @@ async function processAttachments(attachments, cfg, log5) {
13080
13043
  return { type: "image", localPath, url, contentType: att.content_type ?? "image/png", filename: att.filename };
13081
13044
  }
13082
13045
  if (isVoice) {
13083
- const transcript = await processVoiceAttachment(att, sttCfg, usePlatformAsr, audioPolicy, log5);
13046
+ const transcript = await processVoiceAttachment(att, cfg, usePlatformAsr, sttConfigured, audioPolicy, log5);
13084
13047
  return { type: "voice", transcript };
13085
13048
  }
13086
13049
  if (url) {
@@ -13153,16 +13116,25 @@ function kindFromContentType(contentType) {
13153
13116
  if (contentType?.startsWith("audio/")) return "audio";
13154
13117
  return "document";
13155
13118
  }
13156
- async function processVoiceAttachment(att, sttCfg, usePlatformAsr, audioPolicy, log5) {
13119
+ var legacySttWarned = false;
13120
+ function warnLegacySttCredentials(cfg, log5) {
13121
+ if (!legacySttWarned && hasLegacySttCredentials(cfg)) {
13122
+ legacySttWarned = true;
13123
+ log5?.info(
13124
+ "Voice: channels.qqbot.stt credentials (provider/baseUrl/apiKey/model) are deprecated and ignored; configure tools.media.audio.models instead \u2014 platform asr_refer_text is used when framework STT is absent"
13125
+ );
13126
+ }
13127
+ }
13128
+ async function processVoiceAttachment(att, cfg, usePlatformAsr, sttConfigured, audioPolicy, log5) {
13157
13129
  const rawAsrText = att.asr_refer_text?.trim() || void 0;
13158
13130
  const asrReferText = usePlatformAsr ? rawAsrText : void 0;
13159
13131
  const remoteUrl = normalizeUrl(att.voice_wav_url) || normalizeUrl(att.url) || void 0;
13160
- if (!sttCfg) {
13132
+ if (!sttConfigured) {
13161
13133
  if (!usePlatformAsr && rawAsrText) {
13162
- log5?.info(`Voice: STT not configured; platform asr_refer_text discarded (asrFallback not enabled)`);
13134
+ log5?.info(`Voice: framework STT not configured; platform asr_refer_text discarded (asrFallback: false)`);
13163
13135
  }
13164
13136
  if (asrReferText) {
13165
- log5?.debug?.(`Voice: using asr_refer_text (STT not configured, asrFallback enabled)`);
13137
+ log5?.debug?.(`Voice: using platform asr_refer_text (framework STT not configured)`);
13166
13138
  return { text: asrReferText, source: "asr", asrReferText, remoteUrl };
13167
13139
  }
13168
13140
  return {
@@ -13209,16 +13181,17 @@ async function processVoiceAttachment(att, sttCfg, usePlatformAsr, audioPolicy,
13209
13181
  }
13210
13182
  if (localPath) {
13211
13183
  try {
13212
- const transcript = await transcribeAudio(localPath, cfg2stt(sttCfg));
13184
+ const transcript = await transcribeAudioViaFramework(localPath, cfg);
13213
13185
  if (transcript) {
13214
- log5?.debug?.(`Voice STT: ${transcript.slice(0, 80)}...`);
13186
+ log5?.debug?.(`Voice STT (framework): ${transcript.slice(0, 80)}...`);
13215
13187
  return { text: transcript, source: "stt", duration, localPath, remoteUrl, asrReferText };
13216
13188
  }
13217
13189
  } catch (err) {
13218
- log5?.error(`Voice STT failed: ${err instanceof Error ? err.message : String(err)}`);
13190
+ log5?.error(`Voice STT (framework) failed: ${err instanceof Error ? err.message : String(err)}`);
13219
13191
  }
13220
13192
  }
13221
13193
  if (asrReferText) {
13194
+ log5?.debug?.(`Voice: falling back to platform asr_refer_text after framework STT failure`);
13222
13195
  return { text: asrReferText, source: "asr", duration, localPath, remoteUrl, asrReferText };
13223
13196
  }
13224
13197
  return {
@@ -13248,9 +13221,6 @@ function normalizeFormats(formats) {
13248
13221
  return lower.startsWith(".") ? lower : `.${lower}`;
13249
13222
  });
13250
13223
  }
13251
- function cfg2stt(sttCfg) {
13252
- return { channels: { qqbot: { stt: sttCfg } } };
13253
- }
13254
13224
  function normalizeUrl(url) {
13255
13225
  if (!url) return "";
13256
13226
  return url.startsWith("//") ? `https:${url}` : url;
@@ -15891,7 +15861,7 @@ function getQQBotApprovalCapability() {
15891
15861
 
15892
15862
  // src/features/proactive.ts
15893
15863
  init_plugin_logger();
15894
- var fs19 = __toESM(require("fs"), 1);
15864
+ var fs18 = __toESM(require("fs"), 1);
15895
15865
  var path20 = __toESM(require("path"), 1);
15896
15866
  init_bot_instance();
15897
15867
  init_config();
@@ -15902,8 +15872,8 @@ var KNOWN_USERS_FILE = path20.join(STORAGE_DIR, "known-users.json");
15902
15872
  var knownUsersCache = null;
15903
15873
  var cacheLastModified = 0;
15904
15874
  function ensureStorageDir() {
15905
- if (!fs19.existsSync(STORAGE_DIR)) {
15906
- fs19.mkdirSync(STORAGE_DIR, { recursive: true });
15875
+ if (!fs18.existsSync(STORAGE_DIR)) {
15876
+ fs18.mkdirSync(STORAGE_DIR, { recursive: true });
15907
15877
  }
15908
15878
  }
15909
15879
  function getUserKey(type, openid, accountId) {
@@ -15912,7 +15882,7 @@ function getUserKey(type, openid, accountId) {
15912
15882
  function loadKnownUsers() {
15913
15883
  if (knownUsersCache !== null) {
15914
15884
  try {
15915
- const stat = fs19.statSync(KNOWN_USERS_FILE);
15885
+ const stat = fs18.statSync(KNOWN_USERS_FILE);
15916
15886
  if (stat.mtimeMs <= cacheLastModified) {
15917
15887
  return knownUsersCache;
15918
15888
  }
@@ -15922,14 +15892,14 @@ function loadKnownUsers() {
15922
15892
  }
15923
15893
  const users = /* @__PURE__ */ new Map();
15924
15894
  try {
15925
- if (fs19.existsSync(KNOWN_USERS_FILE)) {
15926
- const data = fs19.readFileSync(KNOWN_USERS_FILE, "utf-8");
15895
+ if (fs18.existsSync(KNOWN_USERS_FILE)) {
15896
+ const data = fs18.readFileSync(KNOWN_USERS_FILE, "utf-8");
15927
15897
  const parsed = JSON.parse(data);
15928
15898
  for (const user of parsed) {
15929
15899
  const key2 = getUserKey(user.type, user.openid, user.accountId);
15930
15900
  users.set(key2, user);
15931
15901
  }
15932
- cacheLastModified = fs19.statSync(KNOWN_USERS_FILE).mtimeMs;
15902
+ cacheLastModified = fs18.statSync(KNOWN_USERS_FILE).mtimeMs;
15933
15903
  }
15934
15904
  } catch (err) {
15935
15905
  log3.error(`Failed to load known users: ${err}`);
@@ -15941,7 +15911,7 @@ function saveKnownUsers(users) {
15941
15911
  try {
15942
15912
  ensureStorageDir();
15943
15913
  const data = Array.from(users.values());
15944
- fs19.writeFileSync(KNOWN_USERS_FILE, JSON.stringify(data, null, 2), "utf-8");
15914
+ fs18.writeFileSync(KNOWN_USERS_FILE, JSON.stringify(data, null, 2), "utf-8");
15945
15915
  cacheLastModified = Date.now();
15946
15916
  knownUsersCache = users;
15947
15917
  } catch (err) {
@@ -17478,9 +17448,33 @@ init_runtime();
17478
17448
 
17479
17449
  // src/tools/platform.ts
17480
17450
  init_config();
17481
- init_bot_instance();
17482
- init_request_context();
17451
+ init_outbound_service();
17483
17452
  init_plugin_logger();
17453
+
17454
+ // src/tools/tool-session.ts
17455
+ init_request_context();
17456
+ function resolveToolSessionRoute(delivery) {
17457
+ const alsTarget = getRequestTarget();
17458
+ if (alsTarget) {
17459
+ return {
17460
+ target: alsTarget,
17461
+ accountId: getRequestAccountId(),
17462
+ source: "request-context"
17463
+ };
17464
+ }
17465
+ const to = typeof delivery?.to === "string" ? delivery.to.trim() : "";
17466
+ if (!to) return void 0;
17467
+ const channel = typeof delivery?.channel === "string" ? delivery.channel.trim() : "";
17468
+ if (channel && channel !== "qqbot") return void 0;
17469
+ if (!/^qqbot:(c2c|group|channel):/i.test(to)) return void 0;
17470
+ return {
17471
+ target: to,
17472
+ accountId: delivery?.accountId,
17473
+ source: "delivery-context"
17474
+ };
17475
+ }
17476
+
17477
+ // src/tools/platform.ts
17484
17478
  var toolLog = createPluginLogger({ prefix: "[tool:platform]" });
17485
17479
  var PlatformApiSchema = {
17486
17480
  type: "object",
@@ -17526,68 +17520,76 @@ function registerPlatformTool(api) {
17526
17520
  const accountIds = listQQBotAccountIds(cfg);
17527
17521
  if (accountIds.length === 0) return;
17528
17522
  api.registerTool(
17529
- {
17530
- name: "qqbot_platform_api",
17531
- label: "QQBot Platform API Gateway",
17532
- description: "QQ \u5F00\u653E\u5E73\u53F0\u7EDF\u4E00 HTTP API \u7F51\u5173\uFF0C\u81EA\u52A8\u586B\u5145\u9274\u6743 Token\u3002\u5E38\u7528\u63A5\u53E3\u901F\u67E5\uFF1A\u3010\u9891\u9053\u3011GET /users/@me/guilds | /guilds/{guild_id}/channels | /channels/{channel_id} | \u3010\u7FA4\u3011GET /v2/groups/{group_id}/bot_state | /v2/groups/{group_id}/members/{member_id} | /v2/groups/{group_id}/info\u3002\u66F4\u591A\u63A5\u53E3\u548C\u53C2\u6570\u8BE6\u60C5\u8BF7\u9605\u8BFB qqbot-channel \u548C qqbot-group skill\u3002",
17533
- parameters: PlatformApiSchema,
17534
- async execute(_toolCallId, params) {
17535
- const p2 = params;
17536
- if (!p2.method) return json({ error: "method \u4E3A\u5FC5\u586B\u53C2\u6570" });
17537
- if (!p2.path) return json({ error: "path \u4E3A\u5FC5\u586B\u53C2\u6570" });
17538
- const method = p2.method.toUpperCase();
17539
- if (!["GET", "POST", "PUT", "PATCH", "DELETE"].includes(method)) {
17540
- return json({ error: `\u4E0D\u652F\u6301\u7684 HTTP \u65B9\u6CD5: ${method}` });
17541
- }
17542
- const pathError = validatePath(p2.path);
17543
- if (pathError) return json({ error: pathError });
17544
- const accountId = getRequestAccountId();
17545
- if (!accountId) {
17546
- return json({ error: "\u65E0\u6CD5\u83B7\u53D6\u5F53\u524D\u8BF7\u6C42\u7684\u8D26\u53F7\u4FE1\u606F\uFF0C\u6B64\u5DE5\u5177\u4EC5\u652F\u6301\u5728\u6D88\u606F\u4F1A\u8BDD\u4E2D\u4F7F\u7528" });
17547
- }
17548
- try {
17549
- const bot = getBotForAccount(accountId);
17550
- const apiGateway = bot.api;
17551
- const startedAt = Date.now();
17552
- let data;
17553
- switch (method) {
17554
- case "GET":
17555
- data = await apiGateway.get(p2.path, p2.query);
17556
- break;
17557
- case "POST":
17558
- data = await apiGateway.post(p2.path, p2.body);
17559
- break;
17560
- case "PUT":
17561
- data = await apiGateway.put(p2.path, p2.body);
17562
- break;
17563
- case "PATCH":
17564
- data = await apiGateway.patch(p2.path, p2.body);
17565
- break;
17566
- case "DELETE":
17567
- data = await apiGateway.delete(p2.path);
17568
- break;
17523
+ (factoryCtx) => {
17524
+ const delivery = factoryCtx.deliveryContext;
17525
+ return {
17526
+ name: "qqbot_platform_api",
17527
+ label: "QQBot Platform API Gateway",
17528
+ description: "QQ \u5F00\u653E\u5E73\u53F0\u7EDF\u4E00 HTTP API \u7F51\u5173\uFF0C\u81EA\u52A8\u586B\u5145\u9274\u6743 Token\u3002\u5E38\u7528\u63A5\u53E3\u901F\u67E5\uFF1A\u3010\u9891\u9053\u3011GET /users/@me/guilds | /guilds/{guild_id}/channels | /channels/{channel_id} | \u3010\u7FA4\u3011GET /v2/groups/{group_id}/bot_state | /v2/groups/{group_id}/members/{member_id} | /v2/groups/{group_id}/info\u3002\u66F4\u591A\u63A5\u53E3\u548C\u53C2\u6570\u8BE6\u60C5\u8BF7\u9605\u8BFB qqbot-channel \u548C qqbot-group skill\u3002",
17529
+ parameters: PlatformApiSchema,
17530
+ async execute(_toolCallId, params) {
17531
+ const p2 = params;
17532
+ if (!p2.method) return json({ error: "method \u4E3A\u5FC5\u586B\u53C2\u6570" });
17533
+ if (!p2.path) return json({ error: "path \u4E3A\u5FC5\u586B\u53C2\u6570" });
17534
+ const method = p2.method.toUpperCase();
17535
+ if (!["GET", "POST", "PUT", "PATCH", "DELETE"].includes(method)) {
17536
+ return json({ error: `\u4E0D\u652F\u6301\u7684 HTTP \u65B9\u6CD5: ${method}` });
17537
+ }
17538
+ const pathError = validatePath(p2.path);
17539
+ if (pathError) return json({ error: pathError });
17540
+ const route = resolveToolSessionRoute(delivery);
17541
+ if (!route) {
17542
+ return json({
17543
+ error: "\u5F53\u524D\u8FD0\u884C\u6CA1\u6709 QQ \u4F1A\u8BDD\u6765\u6E90\uFF08\u53EF\u80FD\u7531\u5B9A\u65F6\u4EFB\u52A1\u6216\u6846\u67B6\u5185\u90E8\u89E6\u53D1\u7684 run\uFF09\uFF0C\u65E0\u6CD5\u786E\u5B9A\u8C03\u7528\u54EA\u4E2A QQ Bot \u8D26\u6237\u3002\u8BF7\u5728 QQ \u6D88\u606F\u4F1A\u8BDD\u4E2D\u4F7F\u7528\u672C\u5DE5\u5177\u3002"
17544
+ });
17545
+ }
17546
+ try {
17547
+ const resolvedGateway = resolveGatewayForSend(route.accountId ?? "default");
17548
+ if (!resolvedGateway) {
17549
+ return json({ error: `\u8D26\u6237 ${route.accountId ?? "default"} \u7684 gateway \u5C1A\u672A\u542F\u52A8` });
17550
+ }
17551
+ const bot = resolvedGateway.gw.bot;
17552
+ const apiGateway = bot.api;
17553
+ const startedAt = Date.now();
17554
+ let data;
17555
+ switch (method) {
17556
+ case "GET":
17557
+ data = await apiGateway.get(p2.path, p2.query);
17558
+ break;
17559
+ case "POST":
17560
+ data = await apiGateway.post(p2.path, p2.body);
17561
+ break;
17562
+ case "PUT":
17563
+ data = await apiGateway.put(p2.path, p2.body);
17564
+ break;
17565
+ case "PATCH":
17566
+ data = await apiGateway.patch(p2.path, p2.body);
17567
+ break;
17568
+ case "DELETE":
17569
+ data = await apiGateway.delete(p2.path);
17570
+ break;
17571
+ }
17572
+ toolLog.info(`${method} ${p2.path} ok (${Date.now() - startedAt}ms)`, { accountId: resolvedGateway.accountId });
17573
+ return json(data);
17574
+ } catch (err) {
17575
+ const errMsg = err instanceof Error ? err.message : String(err);
17576
+ const apiErr = err;
17577
+ toolLog.warn(`${method} ${p2.path} failed status=${apiErr.httpStatus ?? "?"} code=${apiErr.bizCode ?? "?"}: ${errMsg}`, { accountId: route.accountId ?? "default" });
17578
+ return json({
17579
+ error: errMsg,
17580
+ status: apiErr.httpStatus,
17581
+ code: apiErr.bizCode,
17582
+ path: p2.path
17583
+ });
17569
17584
  }
17570
- toolLog.info(`${method} ${p2.path} ok (${Date.now() - startedAt}ms)`, { accountId });
17571
- return json(data);
17572
- } catch (err) {
17573
- const errMsg = err instanceof Error ? err.message : String(err);
17574
- const apiErr = err;
17575
- toolLog.warn(`${method} ${p2.path} failed status=${apiErr.httpStatus ?? "?"} code=${apiErr.bizCode ?? "?"}: ${errMsg}`, { accountId });
17576
- return json({
17577
- error: errMsg,
17578
- status: apiErr.httpStatus,
17579
- code: apiErr.bizCode,
17580
- path: p2.path
17581
- });
17582
17585
  }
17583
- }
17586
+ };
17584
17587
  },
17585
17588
  { name: "qqbot_platform_api" }
17586
17589
  );
17587
17590
  }
17588
17591
 
17589
17592
  // src/tools/remind.ts
17590
- init_request_context();
17591
17593
  var RemindSchema = {
17592
17594
  type: "object",
17593
17595
  properties: {
@@ -17732,71 +17734,76 @@ function formatDelay(ms) {
17732
17734
  }
17733
17735
  function registerRemindTool(api) {
17734
17736
  api.registerTool(
17735
- {
17736
- name: "qqbot_remind",
17737
- label: "QQBot \u5B9A\u65F6\u63D0\u9192",
17738
- description: '\u521B\u5EFA\u3001\u67E5\u8BE2\u3001\u5220\u9664 QQ \u5B9A\u65F6\u63D0\u9192\u3002\u4F7F\u7528\u7B80\u5355\u53C2\u6570\u5373\u53EF\uFF0C\u65E0\u9700\u624B\u52A8\u6784\u9020 cron JSON\u3002\n\u521B\u5EFA\u63D0\u9192\uFF1Aaction=add, content=\u63D0\u9192\u5185\u5BB9, to=\u76EE\u6807\u5730\u5740, time=\u65F6\u95F4\n\u67E5\u770B\u63D0\u9192\uFF1Aaction=list\n\u5220\u9664\u63D0\u9192\uFF1Aaction=remove, jobId=\u4EFB\u52A1ID\uFF08\u5148 list \u83B7\u53D6\uFF09\n\u65F6\u95F4\u683C\u5F0F\u793A\u4F8B\uFF1A"5m"(5\u5206\u949F\u540E) "1h"(1\u5C0F\u65F6\u540E) "0 8 * * *"(\u6BCF\u59298\u70B9)',
17739
- parameters: RemindSchema,
17740
- execute(_toolCallId, params) {
17741
- const p2 = params;
17742
- if (p2.action === "list") {
17743
- return json2({
17744
- _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\u6267\u884C\u4EE5\u4E0B\u53C2\u6570",
17745
- cronParams: { action: "list" }
17746
- });
17747
- }
17748
- if (p2.action === "remove") {
17749
- if (!p2.jobId) {
17750
- return json2({ error: "action=remove \u65F6 jobId \u4E3A\u5FC5\u586B\u53C2\u6570\u3002\u8BF7\u5148\u7528 action=list \u83B7\u53D6 jobId\u3002" });
17737
+ (factoryCtx) => {
17738
+ const delivery = factoryCtx.deliveryContext;
17739
+ return {
17740
+ name: "qqbot_remind",
17741
+ label: "QQBot \u5B9A\u65F6\u63D0\u9192",
17742
+ description: '\u521B\u5EFA\u3001\u67E5\u8BE2\u3001\u5220\u9664 QQ \u5B9A\u65F6\u63D0\u9192\u3002\u4F7F\u7528\u7B80\u5355\u53C2\u6570\u5373\u53EF\uFF0C\u65E0\u9700\u624B\u52A8\u6784\u9020 cron JSON\u3002\n\u521B\u5EFA\u63D0\u9192\uFF1Aaction=add, content=\u63D0\u9192\u5185\u5BB9, to=\u76EE\u6807\u5730\u5740, time=\u65F6\u95F4\n\u67E5\u770B\u63D0\u9192\uFF1Aaction=list\n\u5220\u9664\u63D0\u9192\uFF1Aaction=remove, jobId=\u4EFB\u52A1ID\uFF08\u5148 list \u83B7\u53D6\uFF09\n\u65F6\u95F4\u683C\u5F0F\u793A\u4F8B\uFF1A"5m"(5\u5206\u949F\u540E) "1h"(1\u5C0F\u65F6\u540E) "0 8 * * *"(\u6BCF\u59298\u70B9)',
17743
+ parameters: RemindSchema,
17744
+ async execute(_toolCallId, params) {
17745
+ const p2 = params;
17746
+ if (p2.action === "list") {
17747
+ return json2({
17748
+ _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\u6267\u884C\u4EE5\u4E0B\u53C2\u6570",
17749
+ cronParams: { action: "list" }
17750
+ });
17751
17751
  }
17752
- return json2({
17753
- _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\u6267\u884C\u4EE5\u4E0B\u53C2\u6570",
17754
- cronParams: { action: "remove", jobId: p2.jobId }
17755
- });
17756
- }
17757
- if (!p2.content) {
17758
- return json2({ error: "action=add \u65F6 content\uFF08\u63D0\u9192\u5185\u5BB9\uFF09\u4E3A\u5FC5\u586B\u53C2\u6570" });
17759
- }
17760
- const resolvedTo = p2.to || getRequestTarget();
17761
- if (!resolvedTo) {
17762
- return json2({ error: "action=add \u65F6\u65E0\u6CD5\u786E\u5B9A\u6295\u9012\u76EE\u6807\u5730\u5740\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" });
17763
- }
17764
- const resolvedAccountId = getRequestAccountId() || "default";
17765
- if (!p2.time) {
17766
- return json2({ error: 'action=add \u65F6 time\uFF08\u65F6\u95F4\uFF09\u4E3A\u5FC5\u586B\u53C2\u6570\u3002\u793A\u4F8B\uFF1A"5m"\u3001"1h30m"\u3001"0 8 * * *"' });
17767
- }
17768
- if (isCronExpression(p2.time)) {
17769
- const cronJob = buildCronJob(p2, resolvedTo, resolvedAccountId);
17752
+ if (p2.action === "remove") {
17753
+ if (!p2.jobId) {
17754
+ return json2({ error: "action=remove \u65F6 jobId \u4E3A\u5FC5\u586B\u53C2\u6570\u3002\u8BF7\u5148\u7528 action=list \u83B7\u53D6 jobId\u3002" });
17755
+ }
17756
+ return json2({
17757
+ _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\u6267\u884C\u4EE5\u4E0B\u53C2\u6570",
17758
+ cronParams: { action: "remove", jobId: p2.jobId }
17759
+ });
17760
+ }
17761
+ if (!p2.content) {
17762
+ return json2({ error: "action=add \u65F6 content\uFF08\u63D0\u9192\u5185\u5BB9\uFF09\u4E3A\u5FC5\u586B\u53C2\u6570" });
17763
+ }
17764
+ const route = resolveToolSessionRoute(delivery);
17765
+ const resolvedTo = p2.to || route?.target;
17766
+ if (!resolvedTo) {
17767
+ return json2({
17768
+ error: "action=add \u65F6\u65E0\u6CD5\u786E\u5B9A\u6295\u9012\u76EE\u6807\u5730\u5740\uFF08\u5F53\u524D run \u65E0 QQ \u4F1A\u8BDD\u6765\u6E90\uFF09\u3002\u8BF7\u663E\u5F0F\u4F20\u5165 to\uFF08\u683C\u5F0F\uFF1Aqqbot:c2c:user_openid \u6216 qqbot:group:group_openid\uFF09\u540E\u91CD\u8BD5\u3002"
17769
+ });
17770
+ }
17771
+ const resolvedAccountId = route?.accountId || "default";
17772
+ if (!p2.time) {
17773
+ return json2({ error: 'action=add \u65F6 time\uFF08\u65F6\u95F4\uFF09\u4E3A\u5FC5\u586B\u53C2\u6570\u3002\u793A\u4F8B\uFF1A"5m"\u3001"1h30m"\u3001"0 8 * * *"' });
17774
+ }
17775
+ if (isCronExpression(p2.time)) {
17776
+ const cronJob = buildCronJob(p2, resolvedTo, resolvedAccountId);
17777
+ return json2({
17778
+ _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\uFF0C\u5C06 cronParams \u7684\u503C\u539F\u6837\u4F5C\u4E3A\u53C2\u6570\u4F20\u5165\uFF08\u4E0D\u8981\u4FEE\u6539\u6216\u7701\u7565\u4EFB\u4F55\u5B57\u6BB5\uFF0C\u7279\u522B\u662F delivery.accountId\uFF09\uFF0C\u7136\u540E\u56DE\u590D\u7528\u6237\u63D0\u9192\u5DF2\u8BBE\u7F6E",
17779
+ cronParams: cronJob,
17780
+ summary: `\u23F0 \u5468\u671F\u63D0\u9192: "${p2.content}" (${p2.time}, tz=${p2.timezone || "Asia/Shanghai"})`
17781
+ });
17782
+ }
17783
+ const delayMs = parseRelativeTime(p2.time);
17784
+ if (!delayMs || delayMs <= 0) {
17785
+ return json2({
17786
+ error: `\u65E0\u6CD5\u89E3\u6790\u65F6\u95F4 "${p2.time}"\u3002\u652F\u6301\u683C\u5F0F\uFF1A\u76F8\u5BF9\u65F6\u95F4\u5982 "5m"\u3001"1h"\u3001"1h30m"\u3001"2d"\uFF1Bcron \u8868\u8FBE\u5F0F\u5982 "0 8 * * *"\uFF08\u6BCF\u59298\u70B9\uFF09`
17787
+ });
17788
+ }
17789
+ if (delayMs < 3e4) {
17790
+ return json2({ error: "\u63D0\u9192\u65F6\u95F4\u4E0D\u80FD\u5C11\u4E8E 30 \u79D2" });
17791
+ }
17792
+ const onceJob = buildOnceJob(p2, delayMs, resolvedTo, resolvedAccountId);
17770
17793
  return json2({
17771
17794
  _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\uFF0C\u5C06 cronParams \u7684\u503C\u539F\u6837\u4F5C\u4E3A\u53C2\u6570\u4F20\u5165\uFF08\u4E0D\u8981\u4FEE\u6539\u6216\u7701\u7565\u4EFB\u4F55\u5B57\u6BB5\uFF0C\u7279\u522B\u662F delivery.accountId\uFF09\uFF0C\u7136\u540E\u56DE\u590D\u7528\u6237\u63D0\u9192\u5DF2\u8BBE\u7F6E",
17772
- cronParams: cronJob,
17773
- summary: `\u23F0 \u5468\u671F\u63D0\u9192: "${p2.content}" (${p2.time}, tz=${p2.timezone || "Asia/Shanghai"})`
17774
- });
17775
- }
17776
- const delayMs = parseRelativeTime(p2.time);
17777
- if (!delayMs || delayMs <= 0) {
17778
- return json2({
17779
- error: `\u65E0\u6CD5\u89E3\u6790\u65F6\u95F4 "${p2.time}"\u3002\u652F\u6301\u683C\u5F0F\uFF1A\u76F8\u5BF9\u65F6\u95F4\u5982 "5m"\u3001"1h"\u3001"1h30m"\u3001"2d"\uFF1Bcron \u8868\u8FBE\u5F0F\u5982 "0 8 * * *"\uFF08\u6BCF\u59298\u70B9\uFF09`
17795
+ cronParams: onceJob,
17796
+ summary: `\u23F0 ${formatDelay(delayMs)}\u540E\u63D0\u9192: "${p2.content}"`
17780
17797
  });
17781
17798
  }
17782
- if (delayMs < 3e4) {
17783
- return json2({ error: "\u63D0\u9192\u65F6\u95F4\u4E0D\u80FD\u5C11\u4E8E 30 \u79D2" });
17784
- }
17785
- const onceJob = buildOnceJob(p2, delayMs, resolvedTo, resolvedAccountId);
17786
- return json2({
17787
- _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\uFF0C\u5C06 cronParams \u7684\u503C\u539F\u6837\u4F5C\u4E3A\u53C2\u6570\u4F20\u5165\uFF08\u4E0D\u8981\u4FEE\u6539\u6216\u7701\u7565\u4EFB\u4F55\u5B57\u6BB5\uFF0C\u7279\u522B\u662F delivery.accountId\uFF09\uFF0C\u7136\u540E\u56DE\u590D\u7528\u6237\u63D0\u9192\u5DF2\u8BBE\u7F6E",
17788
- cronParams: onceJob,
17789
- summary: `\u23F0 ${formatDelay(delayMs)}\u540E\u63D0\u9192: "${p2.content}"`
17790
- });
17791
- }
17799
+ };
17792
17800
  },
17793
17801
  { name: "qqbot_remind" }
17794
17802
  );
17795
17803
  }
17796
17804
 
17797
17805
  // src/tools/secret-input.ts
17798
- init_bot_instance();
17799
- init_request_context();
17806
+ init_outbound_service();
17800
17807
  init_target();
17801
17808
  init_plugin_logger();
17802
17809
  var toolLog2 = createPluginLogger({ prefix: "[tool:secret-input]" });
@@ -17856,67 +17863,77 @@ function json3(data) {
17856
17863
  }
17857
17864
  function registerSecretInputTool(api) {
17858
17865
  api.registerTool(
17859
- {
17860
- name: "qqbot_secret_input",
17861
- label: "QQBot Secret Input Card",
17862
- description: "\u5F53\u7528\u6237\u8981\u4EA4\u4ED8\u4E00\u4E2A\u65B0\u5BC6\u94A5/\u51ED\u636E\uFF08API Key\u3001Token \u7B49\uFF09\u7ED9\u7CFB\u7EDF\u4FDD\u5B58\u65F6\u8C03\u7528\uFF1A\u5411\u7528\u6237\u79C1\u804A\u53D1\u9001\u4E00\u5F20\u5BC6\u94A5\u8F93\u5165\u5361\u7247\uFF0C\u7528\u6237\u628A\u5BC6\u94A5\u7C98\u8D34\u5728\u8F93\u5165\u6846\u53D1\u9001\u540E\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u62E6\u622A\u8BE5\u6D88\u606F\u5E76\u6267\u884C openclaw secrets store set \u5B8C\u6210\u4FDD\u5B58\uFF0C\u7ED3\u679C\u7531\u63D2\u4EF6\u76F4\u63A5\u56DE\u590D\u7528\u6237\u3002\u5BC6\u94A5\u5185\u5BB9\u4E0D\u4F1A\u8FDB\u5165\u5BF9\u8BDD\u3002\u5FC5\u987B\u7531\u7528\u6237\u63D0\u4F9B name \u53C2\u6570\uFF08\u73AF\u5883\u53D8\u91CF\u540D\uFF09\u3002",
17863
- parameters: SecretInputSchema,
17864
- async execute(_toolCallId, params) {
17865
- const p2 = params;
17866
- const name = (p2.name ?? "").trim();
17867
- if (!name) return json3({ error: "name \u4E3A\u5FC5\u586B\u53C2\u6570\uFF08\u73AF\u5883\u53D8\u91CF\u540D\uFF09" });
17868
- if (!isValidSecretName(name)) {
17869
- return json3({
17870
- error: `\u73AF\u5883\u53D8\u91CF\u540D\u4E0D\u5408\u6CD5\uFF1A\u5FC5\u987B\u4EE5\u5927\u5199\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u542B\u5927\u5199\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF\uFF0C\u6700\u957F 128 \u5B57\u7B26\uFF08\u6536\u5230 "${name}"\uFF09\u3002\u793A\u4F8B\uFF1AOPENWEATHER_API_KEY\u3002\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002`
17871
- });
17872
- }
17873
- const kind = "env";
17874
- const target = getRequestTarget();
17875
- const accountId = getRequestAccountId() ?? "default";
17876
- if (!target) {
17877
- return json3({ error: "\u65E0\u6CD5\u83B7\u53D6\u5F53\u524D\u4F1A\u8BDD\u76EE\u6807\uFF0C\u6B64\u5DE5\u5177\u4EC5\u652F\u6301\u5728 QQ Bot \u6D88\u606F\u4F1A\u8BDD\u4E2D\u4F7F\u7528" });
17878
- }
17879
- const parsed = parseTarget(target);
17880
- if (parsed.scope !== "c2c" || !parsed.targetId) {
17881
- return json3({
17882
- error: `\u5BC6\u94A5\u8F93\u5165\u5361\u7247\u4EC5\u652F\u6301\u79C1\u804A\uFF08c2c\uFF09\u4F1A\u8BDD\uFF0C\u5F53\u524D\u76EE\u6807 ${target} \u4E0D\u9002\u7528\u2014\u2014\u5BC6\u94A5\u4E0D\u5E94\u51FA\u73B0\u5728\u7FA4\u804A\u4E2D\u3002\u8BF7\u5F15\u5BFC\u7528\u6237\u5728\u79C1\u804A\u4E2D\u53D1\u8D77\u3002`
17866
+ (factoryCtx) => {
17867
+ const delivery = factoryCtx.deliveryContext;
17868
+ return {
17869
+ name: "qqbot_secret_input",
17870
+ label: "QQBot Secret Input Card",
17871
+ description: "\u5F53\u7528\u6237\u8981\u4EA4\u4ED8\u4E00\u4E2A\u65B0\u5BC6\u94A5/\u51ED\u636E\uFF08API Key\u3001Token \u7B49\uFF09\u7ED9\u7CFB\u7EDF\u4FDD\u5B58\u65F6\u8C03\u7528\uFF1A\u5411\u7528\u6237\u79C1\u804A\u53D1\u9001\u4E00\u5F20\u5BC6\u94A5\u8F93\u5165\u5361\u7247\uFF0C\u7528\u6237\u628A\u5BC6\u94A5\u7C98\u8D34\u5728\u8F93\u5165\u6846\u53D1\u9001\u540E\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u62E6\u622A\u8BE5\u6D88\u606F\u5E76\u6267\u884C openclaw secrets store set \u5B8C\u6210\u4FDD\u5B58\uFF0C\u7ED3\u679C\u7531\u63D2\u4EF6\u76F4\u63A5\u56DE\u590D\u7528\u6237\u3002\u5BC6\u94A5\u5185\u5BB9\u4E0D\u4F1A\u8FDB\u5165\u5BF9\u8BDD\u3002\u5FC5\u987B\u7531\u7528\u6237\u63D0\u4F9B name \u53C2\u6570\uFF08\u73AF\u5883\u53D8\u91CF\u540D\uFF09\u3002",
17872
+ parameters: SecretInputSchema,
17873
+ async execute(_toolCallId, params) {
17874
+ const p2 = params;
17875
+ const name = (p2.name ?? "").trim();
17876
+ if (!name) return json3({ error: "name \u4E3A\u5FC5\u586B\u53C2\u6570\uFF08\u73AF\u5883\u53D8\u91CF\u540D\uFF09" });
17877
+ if (!isValidSecretName(name)) {
17878
+ return json3({
17879
+ error: `\u73AF\u5883\u53D8\u91CF\u540D\u4E0D\u5408\u6CD5\uFF1A\u5FC5\u987B\u4EE5\u5927\u5199\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u542B\u5927\u5199\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF\uFF0C\u6700\u957F 128 \u5B57\u7B26\uFF08\u6536\u5230 "${name}"\uFF09\u3002\u793A\u4F8B\uFF1AOPENWEATHER_API_KEY\u3002\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002`
17880
+ });
17881
+ }
17882
+ const kind = "env";
17883
+ const route = resolveToolSessionRoute(delivery);
17884
+ if (!route) {
17885
+ return json3({
17886
+ error: "\u5F53\u524D\u8FD0\u884C\u6CA1\u6709 QQ \u4F1A\u8BDD\u6765\u6E90\uFF08\u53EF\u80FD\u7531\u5B9A\u65F6\u4EFB\u52A1\u6216\u6846\u67B6\u5185\u90E8\u89E6\u53D1\u7684 run\uFF09\uFF0C\u65E0\u6CD5\u5B9A\u4F4D\u8981\u53D1\u5361\u7684\u7528\u6237\u3002\u8BF7\u5F15\u5BFC\u7528\u6237\u5728 QQ \u79C1\u804A\u4E2D\u76F4\u63A5\u53D1\u8D77\u5BC6\u94A5\u8F93\u5165\uFF0C\u4E0D\u8981\u5728\u65E0\u4F1A\u8BDD\u4E0A\u4E0B\u6587\u7684\u4EFB\u52A1\u91CC\u8C03\u7528\u672C\u5DE5\u5177\u3002"
17887
+ });
17888
+ }
17889
+ const scope = QQBOT_PREFIX_RE.exec(route.target)?.[1]?.toLowerCase();
17890
+ const parsed = parseTarget(route.target);
17891
+ if (scope !== "c2c" || !parsed.targetId) {
17892
+ return json3({
17893
+ error: `\u5BC6\u94A5\u8F93\u5165\u5361\u7247\u4EC5\u652F\u6301\u79C1\u804A\uFF08c2c\uFF09\u4F1A\u8BDD\uFF0C\u5F53\u524D\u76EE\u6807 ${route.target} \u4E0D\u9002\u7528\u2014\u2014\u5BC6\u94A5\u4E0D\u5E94\u51FA\u73B0\u5728\u7FA4\u804A\u6216\u9891\u9053\u4E2D\u3002\u8BF7\u5F15\u5BFC\u7528\u6237\u5728\u79C1\u804A\u4E2D\u53D1\u8D77\u3002`
17894
+ });
17895
+ }
17896
+ const requestedAccountId = route.accountId ?? "default";
17897
+ const resolvedGateway = resolveGatewayForSend(requestedAccountId);
17898
+ if (!resolvedGateway) {
17899
+ return json3({ error: `\u8D26\u6237 ${requestedAccountId} \u7684 gateway \u5C1A\u672A\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u5BC6\u94A5\u8F93\u5165\u5361\u7247` });
17900
+ }
17901
+ const accountId = resolvedGateway.accountId;
17902
+ const bot = resolvedGateway.gw.bot;
17903
+ const description = p2.description?.trim() || void 0;
17904
+ registerPendingSecretInput({
17905
+ accountId,
17906
+ senderOpenid: parsed.targetId,
17907
+ name,
17908
+ kind,
17909
+ description,
17910
+ createdAt: Date.now()
17883
17911
  });
17884
- }
17885
- const bot = tryGetBotForAccount(accountId);
17886
- if (!bot) {
17887
- return json3({ error: `\u8D26\u6237 ${accountId} \u7684 gateway \u5C1A\u672A\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u5BC6\u94A5\u8F93\u5165\u5361\u7247` });
17888
- }
17889
- const description = p2.description?.trim() || void 0;
17890
- registerPendingSecretInput({
17891
- accountId,
17892
- senderOpenid: parsed.targetId,
17893
- name,
17894
- kind,
17895
- description,
17896
- createdAt: Date.now()
17897
- });
17898
- try {
17899
- await bot.sendTextWithKeyboard(
17900
- { scope: "c2c", targetId: parsed.targetId },
17901
- buildSecretInputCard(name, description, DEFAULT_SECRET_INPUT_TTL_MS / 6e4),
17902
- buildSecretInputKeyboard()
17912
+ try {
17913
+ await bot.sendTextWithKeyboard(
17914
+ { scope: "c2c", targetId: parsed.targetId },
17915
+ buildSecretInputCard(name, description, DEFAULT_SECRET_INPUT_TTL_MS / 6e4),
17916
+ buildSecretInputKeyboard()
17917
+ );
17918
+ } catch (err) {
17919
+ cancelPendingSecretInput(accountId, parsed.targetId);
17920
+ toolLog2.error(`card send failed: ${err instanceof Error ? err.message : String(err)}`, { name, accountId });
17921
+ return json3({
17922
+ error: `\u5BC6\u94A5\u8F93\u5165\u5361\u7247\u53D1\u9001\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}`
17923
+ });
17924
+ }
17925
+ toolLog2.info(
17926
+ `card sent, pending registered name=${name} accountId=${accountId} route=${route.source} ttlMinutes=${DEFAULT_SECRET_INPUT_TTL_MS / 6e4}`
17903
17927
  );
17904
- } catch (err) {
17905
- cancelPendingSecretInput(accountId, parsed.targetId);
17906
- toolLog2.error(`card send failed: ${err instanceof Error ? err.message : String(err)}`, { name, accountId });
17907
17928
  return json3({
17908
- error: `\u5BC6\u94A5\u8F93\u5165\u5361\u7247\u53D1\u9001\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}`
17929
+ ok: true,
17930
+ name,
17931
+ kind,
17932
+ command: `openclaw secrets store set ${name} --kind env --value <\u7528\u6237\u8F93\u5165>`,
17933
+ instruction: `\u5361\u7247\u5DF2\u53D1\u9001\u7ED9\u7528\u6237\u3002\u7528\u6237\u4E0B\u4E00\u6761\u79C1\u804A\u6D88\u606F\u5C06\u88AB\u63D2\u4EF6\u81EA\u52A8\u62E6\u622A\uFF08\u4E0D\u4F1A\u8FDB\u5165\u5BF9\u8BDD\uFF09\uFF0C\u6267\u884C\u4E0A\u8FF0\u547D\u4EE4\u4FDD\u5B58\u5BC6\u94A5\uFF0C\u6210\u529F/\u5931\u8D25\u7531\u63D2\u4EF6\u76F4\u63A5\u56DE\u590D\u7528\u6237\u3002\u8BF7\u76F4\u63A5\u7ED3\u675F\u672C\u8F6E\uFF08\u53EF\u544A\u77E5\u7528\u6237\u6309\u5361\u7247\u63D0\u793A\u53D1\u9001\u5BC6\u94A5\uFF09\uFF0C\u4E0D\u8981\u7B49\u5F85\u7528\u6237\u8F93\u5165\uFF0C\u4E5F\u4E0D\u8981\u8BA9\u7528\u6237\u628A\u5BC6\u94A5\u5185\u5BB9\u53D1\u5230\u5BF9\u8BDD\u91CC\u3002`
17909
17934
  });
17910
17935
  }
17911
- toolLog2.info(`card sent, pending registered name=${name} ttlMinutes=${DEFAULT_SECRET_INPUT_TTL_MS / 6e4}`);
17912
- return json3({
17913
- ok: true,
17914
- name,
17915
- kind,
17916
- command: `openclaw secrets store set ${name} --kind env --value <\u7528\u6237\u8F93\u5165>`,
17917
- instruction: `\u5361\u7247\u5DF2\u53D1\u9001\u7ED9\u7528\u6237\u3002\u7528\u6237\u4E0B\u4E00\u6761\u79C1\u804A\u6D88\u606F\u5C06\u88AB\u63D2\u4EF6\u81EA\u52A8\u62E6\u622A\uFF08\u4E0D\u4F1A\u8FDB\u5165\u5BF9\u8BDD\uFF09\uFF0C\u6267\u884C\u4E0A\u8FF0\u547D\u4EE4\u4FDD\u5B58\u5BC6\u94A5\uFF0C\u6210\u529F/\u5931\u8D25\u7531\u63D2\u4EF6\u76F4\u63A5\u56DE\u590D\u7528\u6237\u3002\u8BF7\u76F4\u63A5\u7ED3\u675F\u672C\u8F6E\uFF08\u53EF\u544A\u77E5\u7528\u6237\u6309\u5361\u7247\u63D0\u793A\u53D1\u9001\u5BC6\u94A5\uFF09\uFF0C\u4E0D\u8981\u7B49\u5F85\u7528\u6237\u8F93\u5165\uFF0C\u4E5F\u4E0D\u8981\u8BA9\u7528\u6237\u628A\u5BC6\u94A5\u5185\u5BB9\u53D1\u5230\u5BF9\u8BDD\u91CC\u3002`
17918
- });
17919
- }
17936
+ };
17920
17937
  },
17921
17938
  { name: "qqbot_secret_input" }
17922
17939
  );