@jerryliang122/openclaw-qqbot 1.0.7 → 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/README.md +4 -4
- package/README.zh.md +4 -4
- package/dist/index.cjs +216 -169
- package/dist/index.cjs.map +1 -1
- package/package.json +3 -3
- package/src/adapter/pairing.ts +1 -1
- package/src/adapter/resolve.ts +2 -2
- package/src/adapter/setup.ts +1 -1
- package/src/dispatch/dispatch.ts +1 -1
- package/src/features/question-helpers.ts +1 -1
- package/src/openclaw-plugin-sdk.d.ts +39 -3
- package/src/tools/platform.ts +86 -72
- package/src/tools/remind.ts +53 -42
- package/src/tools/secret-input.ts +112 -80
- package/src/tools/tool-session.ts +74 -0
- package/src/utils/pkg-version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jerryliang122/openclaw-qqbot",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "QQ Bot channel plugin for OpenClaw (independently maintained fork)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^20.19.43",
|
|
51
|
-
"openclaw": "2026.9.
|
|
51
|
+
"openclaw": "2026.9.1",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
53
|
"typescript": "^5.9.3",
|
|
54
54
|
"tsx": "^4.23.13"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@tencent-connect/qqbot-connector": "1.2.0",
|
|
58
|
-
"openclaw": ">=2026.9.
|
|
58
|
+
"openclaw": ">=2026.9.1"
|
|
59
59
|
},
|
|
60
60
|
"homepage": "https://github.com/jerryliang122/qqbot-openclaw",
|
|
61
61
|
"repository": {
|
package/src/adapter/pairing.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* readAllowFromStore / issueChallenge / buildReply 直接来自稳定 subpath。
|
|
5
5
|
*
|
|
6
|
-
* approveCode 例外:`approveChannelPairingCode` 在 2026.9.2
|
|
6
|
+
* approveCode 例外:`approveChannelPairingCode` 在 2026.9.1/2026.9.2 均未从任何
|
|
7
7
|
* plugin-sdk subpath 导出(只存在于内部 pairing-store chunk 与
|
|
8
8
|
* `openclaw pairing approve` CLI),走与网关同源的 CLI 执行
|
|
9
9
|
* (见 secret-store-cli 的 resolveOpenClawCli 同源约束)。
|
package/src/adapter/resolve.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Runtime Adapters — 一次 resolve,全程复用。
|
|
3
3
|
*
|
|
4
4
|
* Capability Probe 模式:按候选 API 路径探测,选出第一个可用函数。
|
|
5
|
-
* 构建基线为 openclaw 2026.9.
|
|
5
|
+
* 构建基线为 openclaw 2026.9.1(peer >=2026.9.1),不再保留对更旧版本的回退。
|
|
6
6
|
*
|
|
7
7
|
* 调用方通过 `resolveRuntimeAdapters(runtime)` 获取适配层对象,
|
|
8
8
|
* 后续所有 dispatch / channel 代码只使用 adapters 上的方法。
|
|
@@ -237,7 +237,7 @@ export async function persistAuthConfig(
|
|
|
237
237
|
const config: Record<string, unknown> | undefined = runtime.config as any;
|
|
238
238
|
|
|
239
239
|
if (typeof config?.mutateConfigFile !== 'function') {
|
|
240
|
-
throw new Error('persistAuthConfig: runtime.config.mutateConfigFile is unavailable (requires openclaw >= 2026.9.
|
|
240
|
+
throw new Error('persistAuthConfig: runtime.config.mutateConfigFile is unavailable (requires openclaw >= 2026.9.1)');
|
|
241
241
|
}
|
|
242
242
|
await (config.mutateConfigFile as Function)({
|
|
243
243
|
mutate: () => cfg,
|
package/src/adapter/setup.ts
CHANGED
package/src/dispatch/dispatch.ts
CHANGED
|
@@ -97,7 +97,7 @@ export async function dispatchToOpenClaw(
|
|
|
97
97
|
dlog?.debug(`received sender=${envelope.senderId} scope=${envelope.chatScope} msgId=${envelope.messageId}`);
|
|
98
98
|
|
|
99
99
|
if (!adapters.inboundRun || !adapters.dispatchReply) {
|
|
100
|
-
dlog?.error(`runtime adapter inboundRun/dispatchReply not available (openclaw=${adapters.version}, requires >=2026.9.
|
|
100
|
+
dlog?.error(`runtime adapter inboundRun/dispatchReply not available (openclaw=${adapters.version}, requires >=2026.9.1)`);
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -74,7 +74,7 @@ let questionRuntimePromise: Promise<QuestionGatewayRuntime> | undefined;
|
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* question gateway runtime(openclaw/plugin-sdk/question-gateway-runtime,
|
|
77
|
-
* 2026.8.1+ 稳定导出,peer 已要求 >=2026.9.
|
|
77
|
+
* 2026.8.1+ 稳定导出,peer 已要求 >=2026.9.1)。
|
|
78
78
|
*/
|
|
79
79
|
export function getQuestionGatewayRuntime(): Promise<QuestionGatewayRuntime> {
|
|
80
80
|
questionRuntimePromise ??= import('openclaw/plugin-sdk/question-gateway-runtime')
|
|
@@ -77,6 +77,32 @@ declare module "openclaw/plugin-sdk" {
|
|
|
77
77
|
execute: (toolCallId: string, params: unknown) => Promise<AgentToolResult> | AgentToolResult;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* 工具工厂上下文(registerTool 工厂形式)
|
|
82
|
+
*
|
|
83
|
+
* 框架在装配当前 run 的工具面(或缓存描述符路径下的每次执行)时调用
|
|
84
|
+
* 工厂,ctx 携带 run 级会话信息——其中 deliveryContext 是框架按当前
|
|
85
|
+
* run 的 sessionCtx 派生的可信投递路由(2026-09-23 修复:延迟/排队
|
|
86
|
+
* turn 中 ALS 请求上下文失效时,工具由此回退解析会话目标)。
|
|
87
|
+
* 仅声明本项目实际使用的字段,其余字段经索引签名透传。
|
|
88
|
+
*/
|
|
89
|
+
export interface PluginToolFactoryContext {
|
|
90
|
+
config?: OpenClawConfig;
|
|
91
|
+
runtimeConfig?: OpenClawConfig;
|
|
92
|
+
agentId?: string;
|
|
93
|
+
sessionKey?: string;
|
|
94
|
+
sessionId?: string;
|
|
95
|
+
messageChannel?: string;
|
|
96
|
+
agentAccountId?: string;
|
|
97
|
+
/** 可信投递路由:{ channel, to, accountId, threadId? } */
|
|
98
|
+
deliveryContext?: { channel?: string; to?: string; accountId?: string; threadId?: string };
|
|
99
|
+
/** 当前入站 turn 的平台原生会话 ID */
|
|
100
|
+
nativeChannelId?: string;
|
|
101
|
+
/** 当前入站 turn 的发送者 ID(运行时提供,非工具参数) */
|
|
102
|
+
requesterSenderId?: string;
|
|
103
|
+
[key: string]: unknown;
|
|
104
|
+
}
|
|
105
|
+
|
|
80
106
|
/**
|
|
81
107
|
* Tool 注册选项
|
|
82
108
|
*/
|
|
@@ -103,8 +129,18 @@ declare module "openclaw/plugin-sdk" {
|
|
|
103
129
|
};
|
|
104
130
|
/** 注册频道 */
|
|
105
131
|
registerChannel<TAccount = unknown>(options: { plugin: ChannelPlugin<TAccount> }): void;
|
|
106
|
-
/**
|
|
107
|
-
|
|
132
|
+
/**
|
|
133
|
+
* 注册工具。支持两种形式:
|
|
134
|
+
* - 静态定义(AnyAgentTool)
|
|
135
|
+
* - 工厂函数:每次工具装配/执行时由框架调用,ctx 携带 run 级
|
|
136
|
+
* deliveryContext 等会话信息(推荐需要感知当前会话的工具使用)
|
|
137
|
+
*/
|
|
138
|
+
registerTool(
|
|
139
|
+
tool:
|
|
140
|
+
| AnyAgentTool
|
|
141
|
+
| ((ctx: PluginToolFactoryContext) => AnyAgentTool | AnyAgentTool[] | null | undefined),
|
|
142
|
+
opts?: ToolRegistrationOptions,
|
|
143
|
+
): void;
|
|
108
144
|
/** 其他 API 方法 */
|
|
109
145
|
[key: string]: unknown;
|
|
110
146
|
}
|
|
@@ -536,7 +572,7 @@ declare module "openclaw/plugin-sdk" {
|
|
|
536
572
|
}
|
|
537
573
|
|
|
538
574
|
// 2026.8.1-beta 起 openclaw 发布包明确排除该子路径的 .d.ts(files 列表
|
|
539
|
-
// "!dist/plugin-sdk/text-utility-runtime.d.ts"),2026.9.2
|
|
575
|
+
// "!dist/plugin-sdk/text-utility-runtime.d.ts"),2026.9.1/2026.9.2 均未恢复,运行时导出仍在。
|
|
540
576
|
// 仅声明本项目实际使用的函数(签名对齐 dist/utf16-slice-*.js)。
|
|
541
577
|
declare module "openclaw/plugin-sdk/text-utility-runtime" {
|
|
542
578
|
export function truncateUtf16Safe(input: string, maxLen: number): string;
|
package/src/tools/platform.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
|
|
2
2
|
import { listQQBotAccountIds } from '../config.js';
|
|
3
|
-
import {
|
|
4
|
-
import { getRequestAccountId } from '../request-context.js';
|
|
3
|
+
import { resolveGatewayForSend } from '../outbound/outbound-service.js';
|
|
5
4
|
import { createPluginLogger } from '../utils/plugin-logger.js';
|
|
5
|
+
import { resolveToolSessionRoute, type ToolDeliveryContext } from './tool-session.js';
|
|
6
6
|
|
|
7
7
|
// 工具 execute 无 logger 参数;request-context 活跃期间 enrichMeta
|
|
8
8
|
// 自动带上 accountId/openId/messageId
|
|
@@ -71,6 +71,8 @@ function validatePath(path: string): string | null {
|
|
|
71
71
|
* - 频道(Guild/Channel/Member/Announce/Forum/Schedule)→ 见 qqbot-channel skill
|
|
72
72
|
* - 群(Group/Member)→ 见 qqbot-group skill
|
|
73
73
|
*/
|
|
74
|
+
// 工厂注册形式(2026-09-23 修复):turn 被框架延迟/排队执行(ALS 失效)时,
|
|
75
|
+
// 从 deliveryContext 回退解析账户(见 tool-session.ts)。
|
|
74
76
|
export function registerPlatformTool(api: OpenClawPluginApi): void {
|
|
75
77
|
const cfg = api.config;
|
|
76
78
|
if (!cfg) return;
|
|
@@ -79,78 +81,90 @@ export function registerPlatformTool(api: OpenClawPluginApi): void {
|
|
|
79
81
|
if (accountIds.length === 0) return;
|
|
80
82
|
|
|
81
83
|
api.registerTool(
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
'
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
let data: unknown;
|
|
122
|
-
switch (method) {
|
|
123
|
-
case 'GET':
|
|
124
|
-
data = await apiGateway.get(p.path, p.query);
|
|
125
|
-
break;
|
|
126
|
-
case 'POST':
|
|
127
|
-
data = await apiGateway.post(p.path, p.body);
|
|
128
|
-
break;
|
|
129
|
-
case 'PUT':
|
|
130
|
-
data = await apiGateway.put(p.path, p.body);
|
|
131
|
-
break;
|
|
132
|
-
case 'PATCH':
|
|
133
|
-
data = await apiGateway.patch(p.path, p.body);
|
|
134
|
-
break;
|
|
135
|
-
case 'DELETE':
|
|
136
|
-
data = await apiGateway.delete(p.path);
|
|
137
|
-
break;
|
|
84
|
+
(factoryCtx) => {
|
|
85
|
+
const delivery = (factoryCtx as { deliveryContext?: ToolDeliveryContext }).deliveryContext;
|
|
86
|
+
return {
|
|
87
|
+
name: 'qqbot_platform_api',
|
|
88
|
+
label: 'QQBot Platform API Gateway',
|
|
89
|
+
description:
|
|
90
|
+
'QQ 开放平台统一 HTTP API 网关,自动填充鉴权 Token。' +
|
|
91
|
+
'常用接口速查:' +
|
|
92
|
+
'【频道】GET /users/@me/guilds | /guilds/{guild_id}/channels | /channels/{channel_id} | ' +
|
|
93
|
+
'【群】GET /v2/groups/{group_id}/bot_state | /v2/groups/{group_id}/members/{member_id} | /v2/groups/{group_id}/info。' +
|
|
94
|
+
'更多接口和参数详情请阅读 qqbot-channel 和 qqbot-group skill。',
|
|
95
|
+
parameters: PlatformApiSchema,
|
|
96
|
+
async execute(_toolCallId: string, params: unknown) {
|
|
97
|
+
const p = params as {
|
|
98
|
+
method: string;
|
|
99
|
+
path: string;
|
|
100
|
+
body?: Record<string, unknown>;
|
|
101
|
+
query?: Record<string, string>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
if (!p.method) return json({ error: 'method 为必填参数' });
|
|
105
|
+
if (!p.path) return json({ error: 'path 为必填参数' });
|
|
106
|
+
|
|
107
|
+
const method = p.method.toUpperCase();
|
|
108
|
+
if (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
|
|
109
|
+
return json({ error: `不支持的 HTTP 方法: ${method}` });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const pathError = validatePath(p.path);
|
|
113
|
+
if (pathError) return json({ error: pathError });
|
|
114
|
+
|
|
115
|
+
// 会话路由:ALS 优先,deliveryContext 回退(延迟/排队 turn)
|
|
116
|
+
const route = resolveToolSessionRoute(delivery);
|
|
117
|
+
if (!route) {
|
|
118
|
+
return json({
|
|
119
|
+
error:
|
|
120
|
+
'当前运行没有 QQ 会话来源(可能由定时任务或框架内部触发的 run),' +
|
|
121
|
+
'无法确定调用哪个 QQ Bot 账户。请在 QQ 消息会话中使用本工具。',
|
|
122
|
+
});
|
|
138
123
|
}
|
|
139
124
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
125
|
+
try {
|
|
126
|
+
const resolvedGateway = resolveGatewayForSend(route.accountId ?? 'default');
|
|
127
|
+
if (!resolvedGateway) {
|
|
128
|
+
return json({ error: `账户 ${route.accountId ?? 'default'} 的 gateway 尚未启动` });
|
|
129
|
+
}
|
|
130
|
+
const bot = resolvedGateway.gw.bot;
|
|
131
|
+
const apiGateway = bot.api;
|
|
132
|
+
const startedAt = Date.now();
|
|
133
|
+
|
|
134
|
+
let data: unknown;
|
|
135
|
+
switch (method) {
|
|
136
|
+
case 'GET':
|
|
137
|
+
data = await apiGateway.get(p.path, p.query);
|
|
138
|
+
break;
|
|
139
|
+
case 'POST':
|
|
140
|
+
data = await apiGateway.post(p.path, p.body);
|
|
141
|
+
break;
|
|
142
|
+
case 'PUT':
|
|
143
|
+
data = await apiGateway.put(p.path, p.body);
|
|
144
|
+
break;
|
|
145
|
+
case 'PATCH':
|
|
146
|
+
data = await apiGateway.patch(p.path, p.body);
|
|
147
|
+
break;
|
|
148
|
+
case 'DELETE':
|
|
149
|
+
data = await apiGateway.delete(p.path);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
toolLog.info(`${method} ${p.path} ok (${Date.now() - startedAt}ms)`, { accountId: resolvedGateway.accountId });
|
|
154
|
+
return json(data);
|
|
155
|
+
} catch (err: unknown) {
|
|
156
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
157
|
+
const apiErr = err as { httpStatus?: number; bizCode?: number; path?: string };
|
|
158
|
+
toolLog.warn(`${method} ${p.path} failed status=${apiErr.httpStatus ?? '?'} code=${apiErr.bizCode ?? '?'}: ${errMsg}`, { accountId: route.accountId ?? 'default' });
|
|
159
|
+
return json({
|
|
160
|
+
error: errMsg,
|
|
161
|
+
status: apiErr.httpStatus,
|
|
162
|
+
code: apiErr.bizCode,
|
|
163
|
+
path: p.path,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
};
|
|
154
168
|
},
|
|
155
169
|
{ name: 'qqbot_platform_api' },
|
|
156
170
|
);
|
package/src/tools/remind.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveToolSessionRoute, type ToolDeliveryContext } from "./tool-session.js";
|
|
3
3
|
|
|
4
4
|
// ========== 类型定义 ==========
|
|
5
5
|
|
|
@@ -218,52 +218,62 @@ function formatDelay(ms: number): string {
|
|
|
218
218
|
|
|
219
219
|
// ========== 注册入口 ==========
|
|
220
220
|
|
|
221
|
+
// 工厂注册形式(2026-09-23 修复):turn 被框架延迟/排队执行(ALS 失效)时,
|
|
222
|
+
// 从 deliveryContext 回退解析投递目标(见 tool-session.ts)。
|
|
221
223
|
export function registerRemindTool(api: OpenClawPluginApi): void {
|
|
222
224
|
api.registerTool(
|
|
223
|
-
{
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
"
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
225
|
+
(factoryCtx) => {
|
|
226
|
+
const delivery = (factoryCtx as { deliveryContext?: ToolDeliveryContext }).deliveryContext;
|
|
227
|
+
return {
|
|
228
|
+
name: "qqbot_remind",
|
|
229
|
+
label: "QQBot 定时提醒",
|
|
230
|
+
description:
|
|
231
|
+
"创建、查询、删除 QQ 定时提醒。" +
|
|
232
|
+
"使用简单参数即可,无需手动构造 cron JSON。\n" +
|
|
233
|
+
"创建提醒:action=add, content=提醒内容, to=目标地址, time=时间\n" +
|
|
234
|
+
"查看提醒:action=list\n" +
|
|
235
|
+
"删除提醒:action=remove, jobId=任务ID(先 list 获取)\n" +
|
|
236
|
+
"时间格式示例:\"5m\"(5分钟后) \"1h\"(1小时后) \"0 8 * * *\"(每天8点)",
|
|
237
|
+
parameters: RemindSchema,
|
|
238
|
+
async execute(_toolCallId: string, params: unknown) {
|
|
239
|
+
const p = params as RemindParams;
|
|
236
240
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
241
|
+
// ===== list =====
|
|
242
|
+
if (p.action === "list") {
|
|
243
|
+
return json({
|
|
244
|
+
_instruction: "请立即使用 cron 工具执行以下参数",
|
|
245
|
+
cronParams: { action: "list" },
|
|
246
|
+
});
|
|
247
|
+
}
|
|
244
248
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
// ===== remove =====
|
|
250
|
+
if (p.action === "remove") {
|
|
251
|
+
if (!p.jobId) {
|
|
252
|
+
return json({ error: "action=remove 时 jobId 为必填参数。请先用 action=list 获取 jobId。" });
|
|
253
|
+
}
|
|
254
|
+
return json({
|
|
255
|
+
_instruction: "请立即使用 cron 工具执行以下参数",
|
|
256
|
+
cronParams: { action: "remove", jobId: p.jobId },
|
|
257
|
+
});
|
|
249
258
|
}
|
|
250
|
-
return json({
|
|
251
|
-
_instruction: "请立即使用 cron 工具执行以下参数",
|
|
252
|
-
cronParams: { action: "remove", jobId: p.jobId },
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
259
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
260
|
+
// ===== add =====
|
|
261
|
+
if (!p.content) {
|
|
262
|
+
return json({ error: "action=add 时 content(提醒内容)为必填参数" });
|
|
263
|
+
}
|
|
264
|
+
// 优先使用 AI 传入的 to;否则双层解析当前会话路由:
|
|
265
|
+
// ALS 请求级上下文优先,框架 run 级 deliveryContext 回退
|
|
266
|
+
const route = resolveToolSessionRoute(delivery);
|
|
267
|
+
const resolvedTo = p.to || route?.target;
|
|
268
|
+
if (!resolvedTo) {
|
|
269
|
+
return json({
|
|
270
|
+
error:
|
|
271
|
+
"action=add 时无法确定投递目标地址(当前 run 无 QQ 会话来源)。" +
|
|
272
|
+
'请显式传入 to(格式:qqbot:c2c:user_openid 或 qqbot:group:group_openid)后重试。',
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
// 账户 ID:会话路由优先,fallback 到 "default"
|
|
276
|
+
const resolvedAccountId = route?.accountId || "default";
|
|
267
277
|
if (!p.time) {
|
|
268
278
|
return json({ error: "action=add 时 time(时间)为必填参数。示例:\"5m\"、\"1h30m\"、\"0 8 * * *\"" });
|
|
269
279
|
}
|
|
@@ -299,7 +309,8 @@ export function registerRemindTool(api: OpenClawPluginApi): void {
|
|
|
299
309
|
cronParams: onceJob,
|
|
300
310
|
summary: `⏰ ${formatDelay(delayMs)}后提醒: "${p.content}"`,
|
|
301
311
|
});
|
|
302
|
-
|
|
312
|
+
},
|
|
313
|
+
};
|
|
303
314
|
},
|
|
304
315
|
{ name: "qqbot_remind" },
|
|
305
316
|
);
|