@jerryliang122/openclaw-qqbot 1.0.8 → 1.0.9

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 ? "1.0.9" : "unknown";
8263
8263
  }
8264
8264
  function getOpenclawVersion(runtimeVersion) {
8265
8265
  return runtimeVersion && runtimeVersion !== "unknown" ? runtimeVersion : "unknown";
@@ -17478,9 +17478,33 @@ init_runtime();
17478
17478
 
17479
17479
  // src/tools/platform.ts
17480
17480
  init_config();
17481
- init_bot_instance();
17482
- init_request_context();
17481
+ init_outbound_service();
17483
17482
  init_plugin_logger();
17483
+
17484
+ // src/tools/tool-session.ts
17485
+ init_request_context();
17486
+ function resolveToolSessionRoute(delivery) {
17487
+ const alsTarget = getRequestTarget();
17488
+ if (alsTarget) {
17489
+ return {
17490
+ target: alsTarget,
17491
+ accountId: getRequestAccountId(),
17492
+ source: "request-context"
17493
+ };
17494
+ }
17495
+ const to = typeof delivery?.to === "string" ? delivery.to.trim() : "";
17496
+ if (!to) return void 0;
17497
+ const channel = typeof delivery?.channel === "string" ? delivery.channel.trim() : "";
17498
+ if (channel && channel !== "qqbot") return void 0;
17499
+ if (!/^qqbot:(c2c|group|channel):/i.test(to)) return void 0;
17500
+ return {
17501
+ target: to,
17502
+ accountId: delivery?.accountId,
17503
+ source: "delivery-context"
17504
+ };
17505
+ }
17506
+
17507
+ // src/tools/platform.ts
17484
17508
  var toolLog = createPluginLogger({ prefix: "[tool:platform]" });
17485
17509
  var PlatformApiSchema = {
17486
17510
  type: "object",
@@ -17526,68 +17550,76 @@ function registerPlatformTool(api) {
17526
17550
  const accountIds = listQQBotAccountIds(cfg);
17527
17551
  if (accountIds.length === 0) return;
17528
17552
  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;
17553
+ (factoryCtx) => {
17554
+ const delivery = factoryCtx.deliveryContext;
17555
+ return {
17556
+ name: "qqbot_platform_api",
17557
+ label: "QQBot Platform API Gateway",
17558
+ 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",
17559
+ parameters: PlatformApiSchema,
17560
+ async execute(_toolCallId, params) {
17561
+ const p2 = params;
17562
+ if (!p2.method) return json({ error: "method \u4E3A\u5FC5\u586B\u53C2\u6570" });
17563
+ if (!p2.path) return json({ error: "path \u4E3A\u5FC5\u586B\u53C2\u6570" });
17564
+ const method = p2.method.toUpperCase();
17565
+ if (!["GET", "POST", "PUT", "PATCH", "DELETE"].includes(method)) {
17566
+ return json({ error: `\u4E0D\u652F\u6301\u7684 HTTP \u65B9\u6CD5: ${method}` });
17567
+ }
17568
+ const pathError = validatePath(p2.path);
17569
+ if (pathError) return json({ error: pathError });
17570
+ const route = resolveToolSessionRoute(delivery);
17571
+ if (!route) {
17572
+ return json({
17573
+ 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"
17574
+ });
17575
+ }
17576
+ try {
17577
+ const resolvedGateway = resolveGatewayForSend(route.accountId ?? "default");
17578
+ if (!resolvedGateway) {
17579
+ return json({ error: `\u8D26\u6237 ${route.accountId ?? "default"} \u7684 gateway \u5C1A\u672A\u542F\u52A8` });
17580
+ }
17581
+ const bot = resolvedGateway.gw.bot;
17582
+ const apiGateway = bot.api;
17583
+ const startedAt = Date.now();
17584
+ let data;
17585
+ switch (method) {
17586
+ case "GET":
17587
+ data = await apiGateway.get(p2.path, p2.query);
17588
+ break;
17589
+ case "POST":
17590
+ data = await apiGateway.post(p2.path, p2.body);
17591
+ break;
17592
+ case "PUT":
17593
+ data = await apiGateway.put(p2.path, p2.body);
17594
+ break;
17595
+ case "PATCH":
17596
+ data = await apiGateway.patch(p2.path, p2.body);
17597
+ break;
17598
+ case "DELETE":
17599
+ data = await apiGateway.delete(p2.path);
17600
+ break;
17601
+ }
17602
+ toolLog.info(`${method} ${p2.path} ok (${Date.now() - startedAt}ms)`, { accountId: resolvedGateway.accountId });
17603
+ return json(data);
17604
+ } catch (err) {
17605
+ const errMsg = err instanceof Error ? err.message : String(err);
17606
+ const apiErr = err;
17607
+ toolLog.warn(`${method} ${p2.path} failed status=${apiErr.httpStatus ?? "?"} code=${apiErr.bizCode ?? "?"}: ${errMsg}`, { accountId: route.accountId ?? "default" });
17608
+ return json({
17609
+ error: errMsg,
17610
+ status: apiErr.httpStatus,
17611
+ code: apiErr.bizCode,
17612
+ path: p2.path
17613
+ });
17569
17614
  }
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
17615
  }
17583
- }
17616
+ };
17584
17617
  },
17585
17618
  { name: "qqbot_platform_api" }
17586
17619
  );
17587
17620
  }
17588
17621
 
17589
17622
  // src/tools/remind.ts
17590
- init_request_context();
17591
17623
  var RemindSchema = {
17592
17624
  type: "object",
17593
17625
  properties: {
@@ -17732,71 +17764,76 @@ function formatDelay(ms) {
17732
17764
  }
17733
17765
  function registerRemindTool(api) {
17734
17766
  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" });
17767
+ (factoryCtx) => {
17768
+ const delivery = factoryCtx.deliveryContext;
17769
+ return {
17770
+ name: "qqbot_remind",
17771
+ label: "QQBot \u5B9A\u65F6\u63D0\u9192",
17772
+ 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)',
17773
+ parameters: RemindSchema,
17774
+ async execute(_toolCallId, params) {
17775
+ const p2 = params;
17776
+ if (p2.action === "list") {
17777
+ return json2({
17778
+ _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\u6267\u884C\u4EE5\u4E0B\u53C2\u6570",
17779
+ cronParams: { action: "list" }
17780
+ });
17751
17781
  }
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);
17782
+ if (p2.action === "remove") {
17783
+ if (!p2.jobId) {
17784
+ return json2({ error: "action=remove \u65F6 jobId \u4E3A\u5FC5\u586B\u53C2\u6570\u3002\u8BF7\u5148\u7528 action=list \u83B7\u53D6 jobId\u3002" });
17785
+ }
17786
+ return json2({
17787
+ _instruction: "\u8BF7\u7ACB\u5373\u4F7F\u7528 cron \u5DE5\u5177\u6267\u884C\u4EE5\u4E0B\u53C2\u6570",
17788
+ cronParams: { action: "remove", jobId: p2.jobId }
17789
+ });
17790
+ }
17791
+ if (!p2.content) {
17792
+ return json2({ error: "action=add \u65F6 content\uFF08\u63D0\u9192\u5185\u5BB9\uFF09\u4E3A\u5FC5\u586B\u53C2\u6570" });
17793
+ }
17794
+ const route = resolveToolSessionRoute(delivery);
17795
+ const resolvedTo = p2.to || route?.target;
17796
+ if (!resolvedTo) {
17797
+ return json2({
17798
+ 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"
17799
+ });
17800
+ }
17801
+ const resolvedAccountId = route?.accountId || "default";
17802
+ if (!p2.time) {
17803
+ 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 * * *"' });
17804
+ }
17805
+ if (isCronExpression(p2.time)) {
17806
+ const cronJob = buildCronJob(p2, resolvedTo, resolvedAccountId);
17807
+ return json2({
17808
+ _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",
17809
+ cronParams: cronJob,
17810
+ summary: `\u23F0 \u5468\u671F\u63D0\u9192: "${p2.content}" (${p2.time}, tz=${p2.timezone || "Asia/Shanghai"})`
17811
+ });
17812
+ }
17813
+ const delayMs = parseRelativeTime(p2.time);
17814
+ if (!delayMs || delayMs <= 0) {
17815
+ return json2({
17816
+ 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`
17817
+ });
17818
+ }
17819
+ if (delayMs < 3e4) {
17820
+ return json2({ error: "\u63D0\u9192\u65F6\u95F4\u4E0D\u80FD\u5C11\u4E8E 30 \u79D2" });
17821
+ }
17822
+ const onceJob = buildOnceJob(p2, delayMs, resolvedTo, resolvedAccountId);
17770
17823
  return json2({
17771
17824
  _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"})`
17825
+ cronParams: onceJob,
17826
+ summary: `\u23F0 ${formatDelay(delayMs)}\u540E\u63D0\u9192: "${p2.content}"`
17774
17827
  });
17775
17828
  }
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`
17780
- });
17781
- }
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
- }
17829
+ };
17792
17830
  },
17793
17831
  { name: "qqbot_remind" }
17794
17832
  );
17795
17833
  }
17796
17834
 
17797
17835
  // src/tools/secret-input.ts
17798
- init_bot_instance();
17799
- init_request_context();
17836
+ init_outbound_service();
17800
17837
  init_target();
17801
17838
  init_plugin_logger();
17802
17839
  var toolLog2 = createPluginLogger({ prefix: "[tool:secret-input]" });
@@ -17856,67 +17893,77 @@ function json3(data) {
17856
17893
  }
17857
17894
  function registerSecretInputTool(api) {
17858
17895
  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`
17896
+ (factoryCtx) => {
17897
+ const delivery = factoryCtx.deliveryContext;
17898
+ return {
17899
+ name: "qqbot_secret_input",
17900
+ label: "QQBot Secret Input Card",
17901
+ 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",
17902
+ parameters: SecretInputSchema,
17903
+ async execute(_toolCallId, params) {
17904
+ const p2 = params;
17905
+ const name = (p2.name ?? "").trim();
17906
+ if (!name) return json3({ error: "name \u4E3A\u5FC5\u586B\u53C2\u6570\uFF08\u73AF\u5883\u53D8\u91CF\u540D\uFF09" });
17907
+ if (!isValidSecretName(name)) {
17908
+ return json3({
17909
+ 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`
17910
+ });
17911
+ }
17912
+ const kind = "env";
17913
+ const route = resolveToolSessionRoute(delivery);
17914
+ if (!route) {
17915
+ return json3({
17916
+ 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"
17917
+ });
17918
+ }
17919
+ const scope = QQBOT_PREFIX_RE.exec(route.target)?.[1]?.toLowerCase();
17920
+ const parsed = parseTarget(route.target);
17921
+ if (scope !== "c2c" || !parsed.targetId) {
17922
+ return json3({
17923
+ 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`
17924
+ });
17925
+ }
17926
+ const requestedAccountId = route.accountId ?? "default";
17927
+ const resolvedGateway = resolveGatewayForSend(requestedAccountId);
17928
+ if (!resolvedGateway) {
17929
+ return json3({ error: `\u8D26\u6237 ${requestedAccountId} \u7684 gateway \u5C1A\u672A\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u5BC6\u94A5\u8F93\u5165\u5361\u7247` });
17930
+ }
17931
+ const accountId = resolvedGateway.accountId;
17932
+ const bot = resolvedGateway.gw.bot;
17933
+ const description = p2.description?.trim() || void 0;
17934
+ registerPendingSecretInput({
17935
+ accountId,
17936
+ senderOpenid: parsed.targetId,
17937
+ name,
17938
+ kind,
17939
+ description,
17940
+ createdAt: Date.now()
17883
17941
  });
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()
17942
+ try {
17943
+ await bot.sendTextWithKeyboard(
17944
+ { scope: "c2c", targetId: parsed.targetId },
17945
+ buildSecretInputCard(name, description, DEFAULT_SECRET_INPUT_TTL_MS / 6e4),
17946
+ buildSecretInputKeyboard()
17947
+ );
17948
+ } catch (err) {
17949
+ cancelPendingSecretInput(accountId, parsed.targetId);
17950
+ toolLog2.error(`card send failed: ${err instanceof Error ? err.message : String(err)}`, { name, accountId });
17951
+ return json3({
17952
+ error: `\u5BC6\u94A5\u8F93\u5165\u5361\u7247\u53D1\u9001\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}`
17953
+ });
17954
+ }
17955
+ toolLog2.info(
17956
+ `card sent, pending registered name=${name} accountId=${accountId} route=${route.source} ttlMinutes=${DEFAULT_SECRET_INPUT_TTL_MS / 6e4}`
17903
17957
  );
17904
- } catch (err) {
17905
- cancelPendingSecretInput(accountId, parsed.targetId);
17906
- toolLog2.error(`card send failed: ${err instanceof Error ? err.message : String(err)}`, { name, accountId });
17907
17958
  return json3({
17908
- error: `\u5BC6\u94A5\u8F93\u5165\u5361\u7247\u53D1\u9001\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}`
17959
+ ok: true,
17960
+ name,
17961
+ kind,
17962
+ command: `openclaw secrets store set ${name} --kind env --value <\u7528\u6237\u8F93\u5165>`,
17963
+ 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
17964
  });
17910
17965
  }
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
- }
17966
+ };
17920
17967
  },
17921
17968
  { name: "qqbot_secret_input" }
17922
17969
  );