@openclaw/qqbot 2026.5.12 → 2026.5.14-beta.2
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/api.js +6 -6
- package/dist/channel-nG7HntSR.js +1102 -0
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-D_GS95Pk.js → channel.setup-D_8Ryfln.js} +1 -2
- package/dist/config-schema-BE5YP0NG.js +678 -0
- package/dist/{gateway-Bbsd8-ne.js → gateway-Bz_nu9BP.js} +98 -33
- package/dist/{handler-runtime-ZgvjnyoH.js → handler-runtime-DMMHU4NC.js} +3 -5
- package/dist/{outbound-BLWish89.js → outbound-DTQUASKu.js} +11 -3
- package/dist/{request-context-BwSBFANU.js → request-context-DiWgzdpn.js} +2 -2
- package/dist/{sender-BrpzCcXA.js → runtime-BFcYWYuk.js} +27 -6
- package/dist/runtime-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/package.json +5 -5
- package/dist/approval-cg0SVahb.js +0 -94
- package/dist/channel-CmK-n3Oz.js +0 -621
- package/dist/config-BT8KP_H1.js +0 -94
- package/dist/config-schema-BCxobX3l.js +0 -309
- package/dist/exec-approvals-W4oL9R6C.js +0 -138
- package/dist/narrowing-BoieBTIU.js +0 -25
- package/dist/resolve-D3lCbUze.js +0 -284
- package/dist/runtime-CZyFkpnB.js +0 -18
- package/dist/target-parser-C8HaD-ik.js +0 -245
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { E as setOutboundAudioPort, _ as sendVoice, c as isMediaPayload, g as sendVideoMsg, h as sendPhoto, l as parseQQBotPayload, m as sendDocument, o as encodePayloadForCron, r as sendMedia, s as isCronReminderPayload, u as normalizeMediaTags, v as resolveUserFacingMediaError, w as DEFAULT_MEDIA_SEND_ERROR } from "./outbound-
|
|
1
|
+
import { E as setOutboundAudioPort, _ as sendVoice, c as isMediaPayload, g as sendVideoMsg, h as sendPhoto, l as parseQQBotPayload, m as sendDocument, o as encodePayloadForCron, r as sendMedia, s as isCronReminderPayload, u as normalizeMediaTags, v as resolveUserFacingMediaError, w as DEFAULT_MEDIA_SEND_ERROR } from "./outbound-DTQUASKu.js";
|
|
2
2
|
import { c as getPlatformAdapter, i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, o as readStringField, s as sanitizeFileName, t as asOptionalObjectRecord } from "./string-normalize-C46CS-F1.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
7
|
-
import { n as getQQBotRuntimeForEngine, t as getQQBotRuntime } from "./runtime-CZyFkpnB.js";
|
|
8
|
-
import { a as getHomeDir, c as getQQBotMediaDir, d as isLocalPath, f as isWindows, i as checkSilkWasmAvailable, m as resolveQQBotPayloadLocalFilePath, o as getQQBotDataDir, p as normalizePath$1, s as getQQBotDataPath, u as getTempDir } from "./target-parser-C8HaD-ik.js";
|
|
9
|
-
import { a as getPluginVersion, i as getFrameworkVersion, n as runWithRequestContext, o as initCommands, s as matchSlashCommand } from "./request-context-BwSBFANU.js";
|
|
3
|
+
import { f as resolveAccountBase, h as setBridgeLogger, p as ensurePlatformAdapter } from "./config-schema-BE5YP0NG.js";
|
|
4
|
+
import { C as parseApprovalButtonData, a as getQQBotDataDir, d as isWindows, f as normalizePath$1, h as authorizeQQBotApprovalAction, i as getHomeDir, l as getTempDir, m as toGatewayAccount, o as getQQBotDataPath, p as resolveQQBotPayloadLocalFilePath, r as checkSilkWasmAvailable, s as getQQBotMediaDir, u as isLocalPath } from "./channel-nG7HntSR.js";
|
|
5
|
+
import { B as StreamContentType, C as debugError, D as getNextMsgSeq, F as getImageMimeType, H as StreamInputState, I as getMaxUploadSize, N as formatFileSize, R as formatDuration, S as withTokenRetry, T as debugWarn, V as StreamInputMode, _ as sendInputNotify, a as acknowledgeInteraction, b as startBackgroundTokenRefresh, c as createRawInputNotifyFn, d as getMessageApi, f as getPluginUserAgent, g as registerAccount, h as onMessageSent, i as accountToCreds, j as downloadFile, k as openLocalFile, l as getAccessToken, m as initSender, n as getQQBotRuntimeForEngine, o as buildDeliveryTarget, p as initApiConfig, s as clearTokenCache, t as getQQBotRuntime, u as getGatewayUrl, v as sendMedia$1, w as debugLog, x as stopBackgroundTokenRefresh, y as sendText, z as formatErrorMessage } from "./runtime-BFcYWYuk.js";
|
|
6
|
+
import { a as getPluginVersion, i as getFrameworkVersion, n as runWithRequestContext, o as initCommands, s as matchSlashCommand } from "./request-context-DiWgzdpn.js";
|
|
10
7
|
import * as fs$1 from "node:fs";
|
|
11
8
|
import fs from "node:fs";
|
|
12
9
|
import * as os$1 from "node:os";
|
|
@@ -3026,18 +3023,6 @@ function resolveQQBotEffectivePolicies(input) {
|
|
|
3026
3023
|
//#endregion
|
|
3027
3024
|
//#region extensions/qqbot/src/engine/gateway/interaction-handler.ts
|
|
3028
3025
|
/**
|
|
3029
|
-
* INTERACTION_CREATE event handler.
|
|
3030
|
-
*
|
|
3031
|
-
* Handles three interaction branches:
|
|
3032
|
-
*
|
|
3033
|
-
* 1. **Config query** (type=2001) — reads config, ACKs with `claw_cfg`.
|
|
3034
|
-
* 2. **Config update** (type=2002) — writes config, ACKs with updated snapshot.
|
|
3035
|
-
* 3. **Approval button** (other) — ACKs, resolves approval via PlatformAdapter.
|
|
3036
|
-
*
|
|
3037
|
-
* Config query/update require `runtime.config`. When unavailable, those
|
|
3038
|
-
* branches fall through to a bare ACK (backward-compatible).
|
|
3039
|
-
*/
|
|
3040
|
-
/**
|
|
3041
3026
|
* Build the canonical `claw_cfg` snapshot returned in interaction ACKs.
|
|
3042
3027
|
*
|
|
3043
3028
|
* Pure function — all resolution helpers live in engine/config/.
|
|
@@ -3123,7 +3108,7 @@ function applyRequireMentionUpdate(cfg, accountId, groupOpenid, update) {
|
|
|
3123
3108
|
* Returns a fire-and-forget callback that `GatewayConnection` calls
|
|
3124
3109
|
* on every `action: "interaction"` dispatch result.
|
|
3125
3110
|
*/
|
|
3126
|
-
function createInteractionHandler(account, runtime, log) {
|
|
3111
|
+
function createInteractionHandler(account, runtime, log, options) {
|
|
3127
3112
|
return (event) => {
|
|
3128
3113
|
const creds = accountToCreds(account);
|
|
3129
3114
|
const type = event.data?.type;
|
|
@@ -3137,22 +3122,102 @@ function createInteractionHandler(account, runtime, log) {
|
|
|
3137
3122
|
handleWithAck(creds, event, log, "CONFIG_UPDATE", () => applyConfigUpdate(event, account.accountId, runtime, log));
|
|
3138
3123
|
return;
|
|
3139
3124
|
}
|
|
3140
|
-
acknowledgeInteraction(creds, event.id).catch((err) => {
|
|
3141
|
-
log?.error(`Interaction ACK failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3142
|
-
});
|
|
3143
3125
|
const parsed = parseApprovalButtonData(event.data?.resolved?.button_data ?? "");
|
|
3144
|
-
if (!parsed)
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3126
|
+
if (!parsed) {
|
|
3127
|
+
acknowledgeInteraction(creds, event.id).catch((err) => {
|
|
3128
|
+
log?.error(`Interaction ACK failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3129
|
+
});
|
|
3148
3130
|
return;
|
|
3149
3131
|
}
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3132
|
+
handleApprovalButtonInteraction({
|
|
3133
|
+
accountId: account.accountId,
|
|
3134
|
+
creds,
|
|
3135
|
+
event,
|
|
3136
|
+
getActiveCfg: options?.getActiveCfg ?? runtime.config?.current,
|
|
3137
|
+
log,
|
|
3138
|
+
parsed
|
|
3153
3139
|
});
|
|
3154
3140
|
};
|
|
3155
3141
|
}
|
|
3142
|
+
async function handleApprovalButtonInteraction(params) {
|
|
3143
|
+
if (!params.getActiveCfg) {
|
|
3144
|
+
await acknowledgeApprovalInteraction(params.creds, params.event, params.log, { content: "Approval is unavailable." });
|
|
3145
|
+
params.log?.error("Approval button rejected: active config is unavailable");
|
|
3146
|
+
return;
|
|
3147
|
+
}
|
|
3148
|
+
let cfg;
|
|
3149
|
+
try {
|
|
3150
|
+
cfg = params.getActiveCfg();
|
|
3151
|
+
} catch (err) {
|
|
3152
|
+
await acknowledgeApprovalInteraction(params.creds, params.event, params.log, { content: "Approval is unavailable." });
|
|
3153
|
+
params.log?.error(`Approval button rejected: active config failed to load: ${err instanceof Error ? err.message : String(err)}`);
|
|
3154
|
+
return;
|
|
3155
|
+
}
|
|
3156
|
+
const authorization = authorizeApprovalButtonActor({
|
|
3157
|
+
cfg,
|
|
3158
|
+
accountId: params.accountId,
|
|
3159
|
+
event: params.event,
|
|
3160
|
+
approvalKind: resolveApprovalKind(params.parsed.approvalId)
|
|
3161
|
+
});
|
|
3162
|
+
if (!authorization.authorized) {
|
|
3163
|
+
await acknowledgeApprovalInteraction(params.creds, params.event, params.log, { content: authorization.reason ?? "You are not authorized to approve this request." });
|
|
3164
|
+
params.log?.info(`Approval button rejected: id=${params.parsed.approvalId}`);
|
|
3165
|
+
return;
|
|
3166
|
+
}
|
|
3167
|
+
await acknowledgeApprovalInteraction(params.creds, params.event, params.log);
|
|
3168
|
+
const adapter = getPlatformAdapter();
|
|
3169
|
+
if (!adapter.resolveApproval) {
|
|
3170
|
+
params.log?.error("resolveApproval not available on PlatformAdapter");
|
|
3171
|
+
return;
|
|
3172
|
+
}
|
|
3173
|
+
try {
|
|
3174
|
+
if (await adapter.resolveApproval(params.parsed.approvalId, params.parsed.decision)) params.log?.info(`Approval resolved: id=${params.parsed.approvalId}, decision=${params.parsed.decision}`);
|
|
3175
|
+
else params.log?.error(`Approval resolve failed: id=${params.parsed.approvalId}`);
|
|
3176
|
+
} catch (err) {
|
|
3177
|
+
params.log?.error(`Approval resolve failed: id=${params.parsed.approvalId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
async function acknowledgeApprovalInteraction(creds, event, log, data) {
|
|
3181
|
+
try {
|
|
3182
|
+
await acknowledgeInteraction(creds, event.id, 0, data);
|
|
3183
|
+
} catch (err) {
|
|
3184
|
+
log?.error(`Interaction ACK failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
function authorizeApprovalButtonActor(params) {
|
|
3188
|
+
const senderIds = resolveApprovalActorSenderIds(params.event);
|
|
3189
|
+
if (senderIds.length === 0) return authorizeQQBotApprovalAction({
|
|
3190
|
+
cfg: params.cfg,
|
|
3191
|
+
accountId: params.accountId,
|
|
3192
|
+
senderId: null,
|
|
3193
|
+
approvalKind: params.approvalKind
|
|
3194
|
+
});
|
|
3195
|
+
let denial;
|
|
3196
|
+
for (const senderId of senderIds) {
|
|
3197
|
+
const result = authorizeQQBotApprovalAction({
|
|
3198
|
+
cfg: params.cfg,
|
|
3199
|
+
accountId: params.accountId,
|
|
3200
|
+
senderId,
|
|
3201
|
+
approvalKind: params.approvalKind
|
|
3202
|
+
});
|
|
3203
|
+
if (result.authorized) return result;
|
|
3204
|
+
denial ??= result;
|
|
3205
|
+
}
|
|
3206
|
+
return denial ?? {
|
|
3207
|
+
authorized: false,
|
|
3208
|
+
reason: "You are not authorized to approve this request."
|
|
3209
|
+
};
|
|
3210
|
+
}
|
|
3211
|
+
function resolveApprovalActorSenderIds(event) {
|
|
3212
|
+
const ids = [event.group_member_openid, event.user_openid].flatMap((value) => {
|
|
3213
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
3214
|
+
return normalized ? [normalized] : [];
|
|
3215
|
+
});
|
|
3216
|
+
return Array.from(new Set(ids));
|
|
3217
|
+
}
|
|
3218
|
+
function resolveApprovalKind(approvalId) {
|
|
3219
|
+
return approvalId.toLowerCase().startsWith("plugin:") ? "plugin" : "exec";
|
|
3220
|
+
}
|
|
3156
3221
|
/** Execute an async handler, ACK with the result, and handle errors. */
|
|
3157
3222
|
async function handleWithAck(creds, event, log, label, handler) {
|
|
3158
3223
|
try {
|
|
@@ -3267,7 +3332,7 @@ const IMAGE_PROBE_SSRF_POLICY = {};
|
|
|
3267
3332
|
/**
|
|
3268
3333
|
* Fetch image dimensions from a public URL using only the first 64 KB.
|
|
3269
3334
|
*
|
|
3270
|
-
* Uses {@link
|
|
3335
|
+
* Uses {@link readRemoteMediaBuffer} with SSRF guard to block probes against
|
|
3271
3336
|
* private/reserved/loopback/link-local/metadata destinations.
|
|
3272
3337
|
*/
|
|
3273
3338
|
async function getImageSizeFromUrl(url, timeoutMs = 5e3) {
|
|
@@ -6069,7 +6134,7 @@ async function startGateway$1(ctx) {
|
|
|
6069
6134
|
});
|
|
6070
6135
|
}
|
|
6071
6136
|
};
|
|
6072
|
-
const handleInteraction = createInteractionHandler(account, ctx.runtime, log);
|
|
6137
|
+
const handleInteraction = createInteractionHandler(account, ctx.runtime, log, { getActiveCfg: () => activeCfgProvider.getActiveCfg() });
|
|
6073
6138
|
await new GatewayConnection({
|
|
6074
6139
|
account,
|
|
6075
6140
|
abortSignal: ctx.abortSignal,
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as resolveQQBotExecApprovalConfig, i as matchesQQBotApprovalAccount, o as shouldHandleQQBotExecApprovalRequest, r as isQQBotExecApprovalClientEnabled } from "./exec-approvals-W4oL9R6C.js";
|
|
5
|
-
import { c as getMessageApi, t as accountToCreds } from "./sender-BrpzCcXA.js";
|
|
1
|
+
import { m as getBridgeLogger, p as ensurePlatformAdapter, u as resolveQQBotAccount } from "./config-schema-BE5YP0NG.js";
|
|
2
|
+
import { S as buildPluginApprovalText, _ as matchesQQBotApprovalAccount, b as buildApprovalKeyboard, g as isQQBotExecApprovalClientEnabled, v as resolveQQBotExecApprovalConfig, w as resolveApprovalTarget, x as buildExecApprovalText, y as shouldHandleQQBotExecApprovalRequest } from "./channel-nG7HntSR.js";
|
|
3
|
+
import { d as getMessageApi, i as accountToCreds } from "./runtime-BFcYWYuk.js";
|
|
6
4
|
import { resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
7
5
|
import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
8
6
|
//#region extensions/qqbot/src/bridge/approval/handler-runtime.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, s as sanitizeFileName } from "./string-normalize-C46CS-F1.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { a as getQQBotDataDir, f as normalizePath, n as parseTarget$1, p as resolveQQBotPayloadLocalFilePath, s as getQQBotMediaDir, u as isLocalPath } from "./channel-nG7HntSR.js";
|
|
3
|
+
import { A as checkFileSize, C as debugError, E as UploadDailyLimitExceededError, F as getImageMimeType, I as getMaxUploadSize, L as readFileAsync, M as fileExistsAsync, N as formatFileSize, O as UPLOAD_PREPARE_FALLBACK_CODE, P as getFileTypeName, T as debugWarn, i as accountToCreds, j as downloadFile, p as initApiConfig, v as sendMedia$1, w as debugLog, y as sendText$1, z as formatErrorMessage } from "./runtime-BFcYWYuk.js";
|
|
4
4
|
import { pathExistsSync, resolveLocalPathFromRootsSync } from "openclaw/plugin-sdk/security-runtime";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { getFileExtension } from "openclaw/plugin-sdk/media-mime";
|
|
@@ -878,6 +878,14 @@ const CRON_PREFIX = "QQBOT_CRON:";
|
|
|
878
878
|
function formatErr(e) {
|
|
879
879
|
return e instanceof Error ? e.message : String(e);
|
|
880
880
|
}
|
|
881
|
+
function normalizeBase64ForCompare(value) {
|
|
882
|
+
return value.replace(/=+$/u, "").replace(/-/gu, "+").replace(/_/gu, "/");
|
|
883
|
+
}
|
|
884
|
+
function decodeStrictBase64Utf8(value) {
|
|
885
|
+
const buffer = Buffer.from(value, "base64");
|
|
886
|
+
if (normalizeBase64ForCompare(buffer.toString("base64")) !== normalizeBase64ForCompare(value)) throw new Error("Cron payload body is not valid base64");
|
|
887
|
+
return buffer.toString("utf-8");
|
|
888
|
+
}
|
|
881
889
|
/** Parse model output that may start with the QQ Bot structured payload prefix. */
|
|
882
890
|
function parseQQBotPayload(text) {
|
|
883
891
|
const trimmedText = text.trim();
|
|
@@ -933,7 +941,7 @@ function decodeCronPayload(message) {
|
|
|
933
941
|
error: "Cron payload body is empty"
|
|
934
942
|
};
|
|
935
943
|
try {
|
|
936
|
-
const jsonString =
|
|
944
|
+
const jsonString = decodeStrictBase64Utf8(base64Content);
|
|
937
945
|
const payload = JSON.parse(jsonString);
|
|
938
946
|
if (payload.type !== "cron_reminder") return {
|
|
939
947
|
isCronPayload: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { a as getQQBotDataDir, c as getQQBotMediaPath, d as isWindows, i as getHomeDir } from "./channel-nG7HntSR.js";
|
|
2
|
+
import { w as debugLog } from "./runtime-BFcYWYuk.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { loadJsonFile } from "openclaw/plugin-sdk/json-store";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { c as getPlatformAdapter, i as normalizeOptionalString, s as sanitizeFileName } from "./string-normalize-C46CS-F1.js";
|
|
2
2
|
import * as fs$1 from "node:fs";
|
|
3
|
+
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import * as crypto$1 from "node:crypto";
|
|
5
6
|
import crypto from "node:crypto";
|
|
@@ -1386,14 +1387,19 @@ var TokenManager = class {
|
|
|
1386
1387
|
}
|
|
1387
1388
|
const traceId = response.headers.get("x-tps-trace-id") ?? "";
|
|
1388
1389
|
this.logger?.debug?.(`[qqbot:token:${appId}] <<< ${response.status}${traceId ? ` | TraceId: ${traceId}` : ""}`);
|
|
1390
|
+
let rawBody;
|
|
1391
|
+
try {
|
|
1392
|
+
rawBody = await response.text();
|
|
1393
|
+
} catch (err) {
|
|
1394
|
+
throw new Error(`Failed to read access_token response: ${formatErrorMessage(err)}`, { cause: err });
|
|
1395
|
+
}
|
|
1396
|
+
const logBody = rawBody.replace(/"access_token"\s*:\s*"[^"]+"/g, "\"access_token\": \"***\"");
|
|
1397
|
+
this.logger?.debug?.(`[qqbot:token:${appId}] <<< Body: ${logBody}`);
|
|
1389
1398
|
let data;
|
|
1390
1399
|
try {
|
|
1391
|
-
const rawBody = await response.text();
|
|
1392
|
-
const logBody = rawBody.replace(/"access_token"\s*:\s*"[^"]+"/g, "\"access_token\": \"***\"");
|
|
1393
|
-
this.logger?.debug?.(`[qqbot:token:${appId}] <<< Body: ${logBody}`);
|
|
1394
1400
|
data = JSON.parse(rawBody);
|
|
1395
|
-
} catch
|
|
1396
|
-
throw new Error(
|
|
1401
|
+
} catch {
|
|
1402
|
+
throw new Error("QQBot access_token response was malformed JSON");
|
|
1397
1403
|
}
|
|
1398
1404
|
if (!data.access_token) throw new Error(`Failed to get access_token: ${JSON.stringify(data)}`);
|
|
1399
1405
|
const expiresAt = Date.now() + (data.expires_in ?? 7200) * 1e3;
|
|
@@ -1957,4 +1963,19 @@ function supportsRichMedia(targetType) {
|
|
|
1957
1963
|
return targetType === "c2c" || targetType === "group";
|
|
1958
1964
|
}
|
|
1959
1965
|
//#endregion
|
|
1960
|
-
|
|
1966
|
+
//#region extensions/qqbot/src/bridge/runtime.ts
|
|
1967
|
+
const { setRuntime: _setRuntime, getRuntime: getQQBotRuntime } = createPluginRuntimeStore({
|
|
1968
|
+
pluginId: "qqbot",
|
|
1969
|
+
errorMessage: "QQBot runtime not initialized"
|
|
1970
|
+
});
|
|
1971
|
+
/** Set the QQBot runtime and inject the framework version into the User-Agent. */
|
|
1972
|
+
function setQQBotRuntime(runtime) {
|
|
1973
|
+
_setRuntime(runtime);
|
|
1974
|
+
setOpenClawVersion(runtime.version);
|
|
1975
|
+
}
|
|
1976
|
+
/** Type-narrowed getter for engine/ modules that need GatewayPluginRuntime. */
|
|
1977
|
+
function getQQBotRuntimeForEngine() {
|
|
1978
|
+
return getQQBotRuntime();
|
|
1979
|
+
}
|
|
1980
|
+
//#endregion
|
|
1981
|
+
export { checkFileSize as A, StreamContentType as B, debugError as C, getNextMsgSeq as D, UploadDailyLimitExceededError as E, getImageMimeType as F, StreamInputState as H, getMaxUploadSize as I, readFileAsync as L, fileExistsAsync as M, formatFileSize as N, UPLOAD_PREPARE_FALLBACK_CODE as O, getFileTypeName as P, formatDuration as R, withTokenRetry as S, debugWarn as T, StreamInputMode as V, sendInputNotify as _, acknowledgeInteraction as a, startBackgroundTokenRefresh as b, createRawInputNotifyFn as c, getMessageApi as d, getPluginUserAgent as f, registerAccount as g, onMessageSent as h, accountToCreds as i, downloadFile as j, openLocalFile as k, getAccessToken as l, initSender as m, getQQBotRuntimeForEngine as n, buildDeliveryTarget as o, initApiConfig as p, setQQBotRuntime as r, clearTokenCache as s, getQQBotRuntime as t, getGatewayUrl as u, sendMedia as v, debugLog as w, stopBackgroundTokenRefresh as x, sendText as y, formatErrorMessage as z };
|
package/dist/runtime-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { r as setQQBotRuntime, t as getQQBotRuntime } from "./runtime-
|
|
1
|
+
import { r as setQQBotRuntime, t as getQQBotRuntime } from "./runtime-BFcYWYuk.js";
|
|
2
2
|
export { getQQBotRuntime, setQQBotRuntime };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as qqbotSetupPlugin } from "./channel.setup-
|
|
1
|
+
import { t as qqbotSetupPlugin } from "./channel.setup-D_8Ryfln.js";
|
|
2
2
|
export { qqbotSetupPlugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/qqbot",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.14-beta.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OpenClaw QQ Bot channel plugin",
|
|
6
6
|
"repository": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@tencent-connect/qqbot-connector": "1.1.0",
|
|
13
13
|
"mpg123-decoder": "1.0.3",
|
|
14
14
|
"silk-wasm": "3.7.1",
|
|
15
|
-
"ws": "8.20.
|
|
15
|
+
"ws": "8.20.1",
|
|
16
16
|
"zod": "4.4.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"openclaw": "workspace:*"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"openclaw": ">=2026.5.
|
|
24
|
+
"openclaw": ">=2026.5.14-beta.2"
|
|
25
25
|
},
|
|
26
26
|
"peerDependenciesMeta": {
|
|
27
27
|
"openclaw": {
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"minHostVersion": ">=2026.4.10"
|
|
51
51
|
},
|
|
52
52
|
"compat": {
|
|
53
|
-
"pluginApi": ">=2026.5.
|
|
53
|
+
"pluginApi": ">=2026.5.14-beta.2"
|
|
54
54
|
},
|
|
55
55
|
"build": {
|
|
56
|
-
"openclawVersion": "2026.5.
|
|
56
|
+
"openclawVersion": "2026.5.14-beta.2"
|
|
57
57
|
},
|
|
58
58
|
"release": {
|
|
59
59
|
"publishToClawHub": true,
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
//#region extensions/qqbot/src/engine/approval/index.ts
|
|
2
|
-
function buildExecApprovalText(request) {
|
|
3
|
-
const expiresIn = Math.max(0, Math.round((request.expiresAtMs - Date.now()) / 1e3));
|
|
4
|
-
const lines = ["🔐 命令执行审批", ""];
|
|
5
|
-
const cmd = request.request.commandPreview ?? request.request.command ?? "";
|
|
6
|
-
if (cmd) lines.push(`\`\`\`\n${cmd.slice(0, 300)}\n\`\`\``);
|
|
7
|
-
if (request.request.cwd) lines.push(`\u{1f4c1} \u76ee\u5f55: ${request.request.cwd}`);
|
|
8
|
-
if (request.request.agentId) lines.push(`\u{1f916} Agent: ${request.request.agentId}`);
|
|
9
|
-
lines.push("", `\u23f1\ufe0f \u8d85\u65f6: ${expiresIn} \u79d2`);
|
|
10
|
-
return lines.join("\n");
|
|
11
|
-
}
|
|
12
|
-
function buildPluginApprovalText(request) {
|
|
13
|
-
const timeoutSec = Math.round((request.request.timeoutMs ?? 12e4) / 1e3);
|
|
14
|
-
const lines = [`${request.request.severity === "critical" ? "🔴" : request.request.severity === "info" ? "🔵" : "🟡"} \u5ba1\u6279\u8bf7\u6c42`, ""];
|
|
15
|
-
lines.push(`\u{1f4cb} ${request.request.title}`);
|
|
16
|
-
if (request.request.description) lines.push(`\u{1f4dd} ${request.request.description}`);
|
|
17
|
-
if (request.request.toolName) lines.push(`\u{1f527} \u5de5\u5177: ${request.request.toolName}`);
|
|
18
|
-
if (request.request.pluginId) lines.push(`\u{1f50c} \u63d2\u4ef6: ${request.request.pluginId}`);
|
|
19
|
-
if (request.request.agentId) lines.push(`\u{1f916} Agent: ${request.request.agentId}`);
|
|
20
|
-
lines.push("", `\u23f1\ufe0f \u8d85\u65f6: ${timeoutSec} \u79d2`);
|
|
21
|
-
return lines.join("\n");
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Build the three-button inline keyboard for approval messages.
|
|
25
|
-
*
|
|
26
|
-
* type=1 (Callback): click triggers INTERACTION_CREATE, button_data = data field.
|
|
27
|
-
* group_id "approval": clicking one button grays out the others (mutual exclusion).
|
|
28
|
-
* click_limit=1: each user can only click once.
|
|
29
|
-
* permission.type=2: all users can interact.
|
|
30
|
-
*/
|
|
31
|
-
function buildApprovalKeyboard(approvalId, allowedDecisions = [
|
|
32
|
-
"allow-once",
|
|
33
|
-
"allow-always",
|
|
34
|
-
"deny"
|
|
35
|
-
]) {
|
|
36
|
-
const makeBtn = (id, label, visitedLabel, data, style) => ({
|
|
37
|
-
id,
|
|
38
|
-
render_data: {
|
|
39
|
-
label,
|
|
40
|
-
visited_label: visitedLabel,
|
|
41
|
-
style
|
|
42
|
-
},
|
|
43
|
-
action: {
|
|
44
|
-
type: 1,
|
|
45
|
-
data,
|
|
46
|
-
permission: { type: 2 },
|
|
47
|
-
click_limit: 1
|
|
48
|
-
},
|
|
49
|
-
group_id: "approval"
|
|
50
|
-
});
|
|
51
|
-
const buttons = [];
|
|
52
|
-
if (allowedDecisions.includes("allow-once")) buttons.push(makeBtn("allow", "✅ 允许一次", "已允许", `approve:${approvalId}:allow-once`, 1));
|
|
53
|
-
if (allowedDecisions.includes("allow-always")) buttons.push(makeBtn("always", "⭐ 始终允许", "已始终允许", `approve:${approvalId}:allow-always`, 1));
|
|
54
|
-
if (allowedDecisions.includes("deny")) buttons.push(makeBtn("deny", "❌ 拒绝", "已拒绝", `approve:${approvalId}:deny`, 0));
|
|
55
|
-
return { content: { rows: [{ buttons }] } };
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Extract the delivery target from a sessionKey or turnSourceTo string.
|
|
59
|
-
*
|
|
60
|
-
* Expected formats:
|
|
61
|
-
* agent:main:qqbot:direct:OPENID -> { type: "c2c", id: "OPENID" }
|
|
62
|
-
* agent:main:qqbot:c2c:OPENID -> { type: "c2c", id: "OPENID" }
|
|
63
|
-
* agent:main:qqbot:group:GROUPID -> { type: "group", id: "GROUPID" }
|
|
64
|
-
*
|
|
65
|
-
* Returns null if neither field matches the expected pattern.
|
|
66
|
-
*/
|
|
67
|
-
function resolveApprovalTarget(sessionKey, turnSourceTo) {
|
|
68
|
-
const sk = sessionKey ?? turnSourceTo;
|
|
69
|
-
if (!sk) return null;
|
|
70
|
-
const m = sk.match(/qqbot:(c2c|direct|group):([A-F0-9]+)/i);
|
|
71
|
-
if (!m) return null;
|
|
72
|
-
return {
|
|
73
|
-
type: m[1].toLowerCase() === "group" ? "group" : "c2c",
|
|
74
|
-
id: m[2]
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Parse the button_data string from an INTERACTION_CREATE event.
|
|
79
|
-
*
|
|
80
|
-
* Expected format: `approve:<approvalId>:<decision>`
|
|
81
|
-
* where approvalId may be prefixed with "exec:" or "plugin:".
|
|
82
|
-
*
|
|
83
|
-
* Returns null if the data does not match the approval button format.
|
|
84
|
-
*/
|
|
85
|
-
function parseApprovalButtonData(buttonData) {
|
|
86
|
-
const m = buttonData.match(/^approve:((?:(?:exec|plugin):)?[0-9a-f-]+):(allow-once|allow-always|deny)$/i);
|
|
87
|
-
if (!m) return null;
|
|
88
|
-
return {
|
|
89
|
-
approvalId: m[1],
|
|
90
|
-
decision: m[2]
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
//#endregion
|
|
94
|
-
export { resolveApprovalTarget as a, parseApprovalButtonData as i, buildExecApprovalText as n, buildPluginApprovalText as r, buildApprovalKeyboard as t };
|