@jerryliang122/openclaw-qqbot 1.0.5 → 1.0.7
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 +608 -500
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/package.json +1 -1
- package/src/config.ts +64 -4
- package/src/dispatch/ctx-builder.ts +30 -2
- package/src/dispatch/envelope-builder.ts +7 -2
- package/src/gateway/lifecycle.ts +3 -1
- package/src/outbound/media-send.ts +9 -6
- package/src/outbound/outbound-service.ts +116 -21
package/dist/index.cjs
CHANGED
|
@@ -34,367 +34,79 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
));
|
|
35
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
36
|
|
|
37
|
-
// src/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
listQQBotAccountIds: () => listQQBotAccountIds,
|
|
44
|
-
resolveDefaultQQBotAccountId: () => resolveDefaultQQBotAccountId,
|
|
45
|
-
resolveGroupAllowFrom: () => resolveGroupAllowFrom,
|
|
46
|
-
resolveGroupCoalesceConfig: () => resolveGroupCoalesceConfig,
|
|
47
|
-
resolveGroupCoalesceEnabled: () => resolveGroupCoalesceEnabled,
|
|
48
|
-
resolveGroupConfig: () => resolveGroupConfig,
|
|
49
|
-
resolveGroupConfigFromAccount: () => resolveGroupConfigFromAccount,
|
|
50
|
-
resolveGroupName: () => resolveGroupName,
|
|
51
|
-
resolveGroupPolicy: () => resolveGroupPolicy,
|
|
52
|
-
resolveGroupPrompt: () => resolveGroupPrompt,
|
|
53
|
-
resolveHistoryLimit: () => resolveHistoryLimit,
|
|
54
|
-
resolveIgnoreOtherMentions: () => resolveIgnoreOtherMentions,
|
|
55
|
-
resolveMentionPatterns: () => resolveMentionPatterns,
|
|
56
|
-
resolveQQBotAccount: () => resolveQQBotAccount,
|
|
57
|
-
resolveQQBotEnvAppId: () => resolveQQBotEnvAppId,
|
|
58
|
-
resolveQQBotEnvClientSecret: () => resolveQQBotEnvClientSecret,
|
|
59
|
-
resolveRequireMention: () => resolveRequireMention,
|
|
60
|
-
resolveToolPolicy: () => resolveToolPolicy,
|
|
61
|
-
resolveUserAgentSuffix: () => resolveUserAgentSuffix
|
|
62
|
-
});
|
|
63
|
-
function resolveMentionPatterns(cfg, agentId) {
|
|
64
|
-
if (agentId) {
|
|
65
|
-
const agents = cfg.agents;
|
|
66
|
-
const entry = agents?.list?.find((a) => a.id?.trim().toLowerCase() === agentId.trim().toLowerCase());
|
|
67
|
-
const agentGroupChat = entry?.groupChat;
|
|
68
|
-
if (agentGroupChat && Object.hasOwn(agentGroupChat, "mentionPatterns")) {
|
|
69
|
-
return agentGroupChat.mentionPatterns ?? [];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const globalGroupChat = cfg?.messages?.groupChat;
|
|
73
|
-
if (globalGroupChat && typeof globalGroupChat === "object" && Object.hasOwn(globalGroupChat, "mentionPatterns")) {
|
|
74
|
-
return globalGroupChat.mentionPatterns ?? [];
|
|
37
|
+
// src/utils/platform.ts
|
|
38
|
+
function getHomeDir() {
|
|
39
|
+
try {
|
|
40
|
+
const home = os.homedir();
|
|
41
|
+
if (home && fs.existsSync(home)) return home;
|
|
42
|
+
} catch {
|
|
75
43
|
}
|
|
76
|
-
|
|
44
|
+
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
45
|
+
if (envHome && fs.existsSync(envHome)) return envHome;
|
|
46
|
+
return os.tmpdir();
|
|
77
47
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (params.groupPolicy === "allowlist") {
|
|
83
|
-
if (params.requireMatchInput && !params.hasMatchInput) {
|
|
84
|
-
return { allowed: false, groupPolicy: params.groupPolicy, reason: "missing_match_input" };
|
|
85
|
-
}
|
|
86
|
-
if (!params.allowlistConfigured) {
|
|
87
|
-
return { allowed: false, groupPolicy: params.groupPolicy, reason: "empty_allowlist" };
|
|
88
|
-
}
|
|
89
|
-
if (!params.allowlistMatched) {
|
|
90
|
-
return { allowed: false, groupPolicy: params.groupPolicy, reason: "not_allowlisted" };
|
|
91
|
-
}
|
|
48
|
+
function getQQBotDataDir(...subPaths) {
|
|
49
|
+
const dir = path.join(getHomeDir(), ".openclaw", "qqbot", ...subPaths);
|
|
50
|
+
if (!fs.existsSync(dir)) {
|
|
51
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
92
52
|
}
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
function resolveGroupPolicy(cfg, accountId) {
|
|
96
|
-
const account = resolveQQBotAccount(cfg, accountId);
|
|
97
|
-
return account.config?.groupPolicy ?? DEFAULT_GROUP_POLICY;
|
|
98
|
-
}
|
|
99
|
-
function resolveGroupAllowFrom(cfg, accountId) {
|
|
100
|
-
const account = resolveQQBotAccount(cfg, accountId);
|
|
101
|
-
return (account.config?.groupAllowFrom ?? []).map((id) => String(id).trim().toUpperCase());
|
|
102
|
-
}
|
|
103
|
-
function isGroupAllowed(cfg, groupOpenid, accountId) {
|
|
104
|
-
const account = resolveQQBotAccount(cfg, accountId);
|
|
105
|
-
const policy = account.config?.groupPolicy ?? DEFAULT_GROUP_POLICY;
|
|
106
|
-
const allowList = (account.config?.groupAllowFrom ?? []).map((id) => String(id).trim().toUpperCase());
|
|
107
|
-
const allowlistConfigured = allowList.length > 0;
|
|
108
|
-
const allowlistMatched = allowList.some((id) => id === "*" || id === groupOpenid.toUpperCase());
|
|
109
|
-
return evaluateMatchedGroupAccessForPolicy({
|
|
110
|
-
groupPolicy: policy,
|
|
111
|
-
allowlistConfigured,
|
|
112
|
-
allowlistMatched
|
|
113
|
-
}).allowed;
|
|
114
|
-
}
|
|
115
|
-
function resolveGroupConfigFromAccount(account, groupOpenid) {
|
|
116
|
-
const groups = account.config?.groups ?? {};
|
|
117
|
-
const wildcardCfg = groups["*"] ?? {};
|
|
118
|
-
const specificCfg = groups[groupOpenid] ?? {};
|
|
119
|
-
const accountDefaultRequireMention = account.config?.defaultRequireMention ?? DEFAULT_GROUP_CONFIG.requireMention;
|
|
120
|
-
const accountDefaultCoalesce = account.config?.groupCoalesce ?? DEFAULT_GROUP_COALESCE_CONFIG;
|
|
121
|
-
const coalesce = {
|
|
122
|
-
enabled: specificCfg.coalesce?.enabled ?? wildcardCfg.coalesce?.enabled ?? accountDefaultCoalesce.enabled ?? DEFAULT_GROUP_COALESCE_CONFIG.enabled
|
|
123
|
-
};
|
|
124
|
-
return {
|
|
125
|
-
requireMention: specificCfg.requireMention ?? wildcardCfg.requireMention ?? accountDefaultRequireMention,
|
|
126
|
-
ignoreOtherMentions: specificCfg.ignoreOtherMentions ?? wildcardCfg.ignoreOtherMentions ?? DEFAULT_GROUP_CONFIG.ignoreOtherMentions,
|
|
127
|
-
toolPolicy: specificCfg.toolPolicy ?? wildcardCfg.toolPolicy ?? DEFAULT_GROUP_CONFIG.toolPolicy,
|
|
128
|
-
name: specificCfg.name ?? wildcardCfg.name ?? DEFAULT_GROUP_CONFIG.name,
|
|
129
|
-
prompt: specificCfg.prompt ?? wildcardCfg.prompt ?? DEFAULT_GROUP_PROMPT,
|
|
130
|
-
historyLimit: specificCfg.historyLimit ?? wildcardCfg.historyLimit ?? DEFAULT_GROUP_CONFIG.historyLimit,
|
|
131
|
-
historyMode: specificCfg.historyMode ?? wildcardCfg.historyMode ?? DEFAULT_GROUP_CONFIG.historyMode,
|
|
132
|
-
unmentionedInbound: specificCfg.unmentionedInbound ?? wildcardCfg.unmentionedInbound ?? DEFAULT_GROUP_CONFIG.unmentionedInbound,
|
|
133
|
-
coalesce
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
function resolveGroupConfig(cfg, groupOpenid, accountId) {
|
|
137
|
-
return resolveGroupConfigFromAccount(resolveQQBotAccount(cfg, accountId), groupOpenid);
|
|
138
|
-
}
|
|
139
|
-
function resolveHistoryLimit(cfg, groupOpenid, accountId) {
|
|
140
|
-
return Math.max(0, resolveGroupConfig(cfg, groupOpenid, accountId).historyLimit);
|
|
141
|
-
}
|
|
142
|
-
function resolveGroupPrompt(cfg, groupOpenid, accountId) {
|
|
143
|
-
return resolveGroupConfig(cfg, groupOpenid, accountId).prompt;
|
|
144
|
-
}
|
|
145
|
-
function resolveRequireMention(cfg, groupOpenid, accountId) {
|
|
146
|
-
return resolveGroupConfig(cfg, groupOpenid, accountId).requireMention;
|
|
147
|
-
}
|
|
148
|
-
function resolveIgnoreOtherMentions(cfg, groupOpenid, accountId) {
|
|
149
|
-
return resolveGroupConfig(cfg, groupOpenid, accountId).ignoreOtherMentions;
|
|
150
|
-
}
|
|
151
|
-
function resolveToolPolicy(cfg, groupOpenid, accountId) {
|
|
152
|
-
return resolveGroupConfig(cfg, groupOpenid, accountId).toolPolicy;
|
|
153
|
-
}
|
|
154
|
-
function resolveGroupName(cfg, groupOpenid, accountId) {
|
|
155
|
-
const name = resolveGroupConfig(cfg, groupOpenid, accountId).name;
|
|
156
|
-
return name || groupOpenid.slice(0, 8);
|
|
157
|
-
}
|
|
158
|
-
function resolveUserAgentSuffix(cfg) {
|
|
159
|
-
const qqbot = cfg.channels?.qqbot;
|
|
160
|
-
return qqbot?.userAgentSuffix ? String(qqbot.userAgentSuffix).trim() : "";
|
|
53
|
+
return dir;
|
|
161
54
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
|
|
55
|
+
function getQQBotMediaDir(...subPaths) {
|
|
56
|
+
const dir = path.join(getHomeDir(), ".openclaw", "media", "qqbot", ...subPaths);
|
|
57
|
+
if (!fs.existsSync(dir)) {
|
|
58
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
return dir;
|
|
165
61
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
62
|
+
var os, path, fs;
|
|
63
|
+
var init_platform = __esm({
|
|
64
|
+
"src/utils/platform.ts"() {
|
|
65
|
+
"use strict";
|
|
66
|
+
os = __toESM(require("os"), 1);
|
|
67
|
+
path = __toESM(require("path"), 1);
|
|
68
|
+
fs = __toESM(require("fs"), 1);
|
|
169
69
|
}
|
|
170
|
-
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// src/request-context.ts
|
|
73
|
+
function runWithRequestContext(ctx, fn) {
|
|
74
|
+
return asyncLocalStorage.run(ctx, fn);
|
|
171
75
|
}
|
|
172
|
-
function
|
|
173
|
-
return
|
|
76
|
+
function getRequestContext() {
|
|
77
|
+
return asyncLocalStorage.getStore();
|
|
174
78
|
}
|
|
175
|
-
function
|
|
176
|
-
return
|
|
79
|
+
function getRequestTarget() {
|
|
80
|
+
return asyncLocalStorage.getStore()?.target;
|
|
177
81
|
}
|
|
178
|
-
function
|
|
179
|
-
|
|
180
|
-
const qqbot = cfg.channels?.qqbot;
|
|
181
|
-
if (qqbot?.appId || resolveQQBotEnvAppId()) {
|
|
182
|
-
ids.add(DEFAULT_ACCOUNT_ID);
|
|
183
|
-
}
|
|
184
|
-
if (qqbot?.accounts) {
|
|
185
|
-
for (const accountId of Object.keys(qqbot.accounts)) {
|
|
186
|
-
if (qqbot.accounts[accountId]?.appId) {
|
|
187
|
-
ids.add(accountId);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return Array.from(ids);
|
|
82
|
+
function getRequestAccountId() {
|
|
83
|
+
return asyncLocalStorage.getStore()?.accountId;
|
|
192
84
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const ids = Object.keys(qqbot.accounts);
|
|
200
|
-
if (ids.length > 0) {
|
|
201
|
-
return ids[0];
|
|
202
|
-
}
|
|
85
|
+
var import_node_async_hooks, asyncLocalStorage;
|
|
86
|
+
var init_request_context = __esm({
|
|
87
|
+
"src/request-context.ts"() {
|
|
88
|
+
"use strict";
|
|
89
|
+
import_node_async_hooks = require("async_hooks");
|
|
90
|
+
asyncLocalStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
203
91
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
let appId = "";
|
|
211
|
-
let clientSecret = "";
|
|
212
|
-
let secretSource = "none";
|
|
213
|
-
if (resolvedAccountId === DEFAULT_ACCOUNT_ID) {
|
|
214
|
-
const { accounts: _accounts, ...topLevelConfig } = qqbot ?? {};
|
|
215
|
-
accountConfig = {
|
|
216
|
-
...topLevelConfig,
|
|
217
|
-
markdownSupport: qqbot?.markdownSupport ?? true
|
|
218
|
-
};
|
|
219
|
-
appId = normalizeAppId(qqbot?.appId);
|
|
220
|
-
} else {
|
|
221
|
-
const account = qqbot?.accounts?.[resolvedAccountId];
|
|
222
|
-
accountConfig = account ?? {};
|
|
223
|
-
appId = normalizeAppId(account?.appId);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// node_modules/@tencent-connect/qqbot-nodejs/dist/middleware/types.js
|
|
95
|
+
function resolvePolicy(ctx, path21, explicit, defaultValue) {
|
|
96
|
+
if (explicit !== void 0 && explicit !== null) {
|
|
97
|
+
return explicit;
|
|
224
98
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
clientSecret = resolveQQBotEnvClientSecret();
|
|
232
|
-
secretSource = "env";
|
|
99
|
+
const keys = path21.split(".");
|
|
100
|
+
let value = ctx.state.policy;
|
|
101
|
+
for (const key2 of keys) {
|
|
102
|
+
if (value === null || value === void 0)
|
|
103
|
+
break;
|
|
104
|
+
value = value[key2];
|
|
233
105
|
}
|
|
234
|
-
if (
|
|
235
|
-
|
|
106
|
+
if (value !== void 0 && value !== null) {
|
|
107
|
+
return value;
|
|
236
108
|
}
|
|
237
|
-
return
|
|
238
|
-
accountId: resolvedAccountId,
|
|
239
|
-
name: accountConfig.name,
|
|
240
|
-
enabled: accountConfig.enabled !== false,
|
|
241
|
-
appId,
|
|
242
|
-
clientSecret,
|
|
243
|
-
secretSource,
|
|
244
|
-
systemPrompt: accountConfig.systemPrompt,
|
|
245
|
-
markdownSupport: accountConfig.markdownSupport !== false,
|
|
246
|
-
commandPanelNative: accountConfig.commands?.native !== false,
|
|
247
|
-
userAgentSuffix: resolveUserAgentSuffix(cfg),
|
|
248
|
-
config: accountConfig
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
function applyQQBotAccountConfig(cfg, accountId, input) {
|
|
252
|
-
const next = { ...cfg };
|
|
253
|
-
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
254
|
-
const existingConfig = next.channels?.qqbot || {};
|
|
255
|
-
const allowFrom = existingConfig.allowFrom ?? ["*"];
|
|
256
|
-
next.channels = {
|
|
257
|
-
...next.channels,
|
|
258
|
-
qqbot: {
|
|
259
|
-
...next.channels?.qqbot || {},
|
|
260
|
-
enabled: true,
|
|
261
|
-
allowFrom,
|
|
262
|
-
...input.appId ? { appId: input.appId } : {},
|
|
263
|
-
...input.clientSecret ? { clientSecret: input.clientSecret } : input.clientSecretFile ? { clientSecretFile: input.clientSecretFile } : {},
|
|
264
|
-
...input.name ? { name: input.name } : {}
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
} else {
|
|
268
|
-
const existingAccountConfig = next.channels?.qqbot?.accounts?.[accountId] || {};
|
|
269
|
-
const allowFrom = existingAccountConfig.allowFrom ?? ["*"];
|
|
270
|
-
next.channels = {
|
|
271
|
-
...next.channels,
|
|
272
|
-
qqbot: {
|
|
273
|
-
...next.channels?.qqbot || {},
|
|
274
|
-
enabled: true,
|
|
275
|
-
accounts: {
|
|
276
|
-
...next.channels?.qqbot?.accounts || {},
|
|
277
|
-
[accountId]: {
|
|
278
|
-
...next.channels?.qqbot?.accounts?.[accountId] || {},
|
|
279
|
-
enabled: true,
|
|
280
|
-
allowFrom,
|
|
281
|
-
...input.appId ? { appId: input.appId } : {},
|
|
282
|
-
...input.clientSecret ? { clientSecret: input.clientSecret } : input.clientSecretFile ? { clientSecretFile: input.clientSecretFile } : {},
|
|
283
|
-
...input.name ? { name: input.name } : {}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
return next;
|
|
290
|
-
}
|
|
291
|
-
function resolveGroupCoalesceConfig(cfg, groupOpenid, accountId) {
|
|
292
|
-
return resolveGroupConfig(cfg, groupOpenid, accountId).coalesce;
|
|
293
|
-
}
|
|
294
|
-
function resolveGroupCoalesceEnabled(cfg, groupOpenid, accountId) {
|
|
295
|
-
return resolveGroupCoalesceConfig(cfg, groupOpenid, accountId).enabled;
|
|
296
|
-
}
|
|
297
|
-
var DEFAULT_ACCOUNT_ID, DEFAULT_GROUP_POLICY, DEFAULT_GROUP_HISTORY_LIMIT, DEFAULT_GROUP_COALESCE_CONFIG, DEFAULT_GROUP_CONFIG, DEFAULT_GROUP_PROMPT;
|
|
298
|
-
var init_config = __esm({
|
|
299
|
-
"src/config.ts"() {
|
|
300
|
-
"use strict";
|
|
301
|
-
DEFAULT_ACCOUNT_ID = "default";
|
|
302
|
-
DEFAULT_GROUP_POLICY = "open";
|
|
303
|
-
DEFAULT_GROUP_HISTORY_LIMIT = 20;
|
|
304
|
-
DEFAULT_GROUP_COALESCE_CONFIG = {
|
|
305
|
-
enabled: true
|
|
306
|
-
};
|
|
307
|
-
DEFAULT_GROUP_CONFIG = {
|
|
308
|
-
requireMention: true,
|
|
309
|
-
ignoreOtherMentions: false,
|
|
310
|
-
toolPolicy: "restricted",
|
|
311
|
-
name: "",
|
|
312
|
-
historyLimit: DEFAULT_GROUP_HISTORY_LIMIT,
|
|
313
|
-
historyMode: "clear",
|
|
314
|
-
unmentionedInbound: "user_request",
|
|
315
|
-
coalesce: DEFAULT_GROUP_COALESCE_CONFIG
|
|
316
|
-
};
|
|
317
|
-
DEFAULT_GROUP_PROMPT = [
|
|
318
|
-
"\u82E5\u53D1\u9001\u8005\u4E3A\u673A\u5668\u4EBA\uFF0C\u4EC5\u5728\u5BF9\u65B9\u660E\u786E@\u4F60\u63D0\u95EE\u6216\u8BF7\u6C42\u534F\u52A9\u5177\u4F53\u4EFB\u52A1\u65F6\uFF0C\u4EE5\u7B80\u6D01\u660E\u4E86\u7684\u5185\u5BB9\u56DE\u590D\uFF0C",
|
|
319
|
-
"\u907F\u514D\u4E0E\u5176\u4ED6\u673A\u5668\u4EBA\u4EA7\u751F\u62A2\u7B54\u6216\u591A\u8F6E\u65E0\u610F\u4E49\u5BF9\u8BDD\u3002",
|
|
320
|
-
"\u5728\u7FA4\u804A\u4E2D\u4F18\u5148\u8BA9\u4EBA\u7C7B\u7528\u6237\u7684\u6D88\u606F\u5F97\u5230\u54CD\u5E94\uFF0C\u673A\u5668\u4EBA\u4E4B\u95F4\u4FDD\u6301\u534F\u4F5C\u800C\u975E\u7ADE\u4E89\uFF0C\u786E\u4FDD\u5BF9\u8BDD\u6709\u5E8F\u4E0D\u5237\u5C4F\u3002"
|
|
321
|
-
].join("");
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
// src/utils/platform.ts
|
|
326
|
-
function getHomeDir() {
|
|
327
|
-
try {
|
|
328
|
-
const home = os.homedir();
|
|
329
|
-
if (home && fs.existsSync(home)) return home;
|
|
330
|
-
} catch {
|
|
331
|
-
}
|
|
332
|
-
const envHome = process.env.HOME || process.env.USERPROFILE;
|
|
333
|
-
if (envHome && fs.existsSync(envHome)) return envHome;
|
|
334
|
-
return os.tmpdir();
|
|
335
|
-
}
|
|
336
|
-
function getQQBotDataDir(...subPaths) {
|
|
337
|
-
const dir = path.join(getHomeDir(), ".openclaw", "qqbot", ...subPaths);
|
|
338
|
-
if (!fs.existsSync(dir)) {
|
|
339
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
340
|
-
}
|
|
341
|
-
return dir;
|
|
342
|
-
}
|
|
343
|
-
function getQQBotMediaDir(...subPaths) {
|
|
344
|
-
const dir = path.join(getHomeDir(), ".openclaw", "media", "qqbot", ...subPaths);
|
|
345
|
-
if (!fs.existsSync(dir)) {
|
|
346
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
347
|
-
}
|
|
348
|
-
return dir;
|
|
349
|
-
}
|
|
350
|
-
var os, path, fs;
|
|
351
|
-
var init_platform = __esm({
|
|
352
|
-
"src/utils/platform.ts"() {
|
|
353
|
-
"use strict";
|
|
354
|
-
os = __toESM(require("os"), 1);
|
|
355
|
-
path = __toESM(require("path"), 1);
|
|
356
|
-
fs = __toESM(require("fs"), 1);
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
// src/request-context.ts
|
|
361
|
-
function runWithRequestContext(ctx, fn) {
|
|
362
|
-
return asyncLocalStorage.run(ctx, fn);
|
|
363
|
-
}
|
|
364
|
-
function getRequestContext() {
|
|
365
|
-
return asyncLocalStorage.getStore();
|
|
366
|
-
}
|
|
367
|
-
function getRequestTarget() {
|
|
368
|
-
return asyncLocalStorage.getStore()?.target;
|
|
369
|
-
}
|
|
370
|
-
function getRequestAccountId() {
|
|
371
|
-
return asyncLocalStorage.getStore()?.accountId;
|
|
372
|
-
}
|
|
373
|
-
var import_node_async_hooks, asyncLocalStorage;
|
|
374
|
-
var init_request_context = __esm({
|
|
375
|
-
"src/request-context.ts"() {
|
|
376
|
-
"use strict";
|
|
377
|
-
import_node_async_hooks = require("async_hooks");
|
|
378
|
-
asyncLocalStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
// node_modules/@tencent-connect/qqbot-nodejs/dist/middleware/types.js
|
|
383
|
-
function resolvePolicy(ctx, path21, explicit, defaultValue) {
|
|
384
|
-
if (explicit !== void 0 && explicit !== null) {
|
|
385
|
-
return explicit;
|
|
386
|
-
}
|
|
387
|
-
const keys = path21.split(".");
|
|
388
|
-
let value = ctx.state.policy;
|
|
389
|
-
for (const key2 of keys) {
|
|
390
|
-
if (value === null || value === void 0)
|
|
391
|
-
break;
|
|
392
|
-
value = value[key2];
|
|
393
|
-
}
|
|
394
|
-
if (value !== void 0 && value !== null) {
|
|
395
|
-
return value;
|
|
396
|
-
}
|
|
397
|
-
return defaultValue;
|
|
109
|
+
return defaultValue;
|
|
398
110
|
}
|
|
399
111
|
async function runMiddlewareChain(middlewares, ctx) {
|
|
400
112
|
let index = -1;
|
|
@@ -8272,7 +7984,10 @@ var outbound_service_exports = {};
|
|
|
8272
7984
|
__export(outbound_service_exports, {
|
|
8273
7985
|
OutboundService: () => OutboundService,
|
|
8274
7986
|
getGateway: () => getGateway,
|
|
7987
|
+
getRegisteredAccountIds: () => getRegisteredAccountIds,
|
|
7988
|
+
notRunningError: () => notRunningError,
|
|
8275
7989
|
registerGateway: () => registerGateway,
|
|
7990
|
+
resolveGatewayForSend: () => resolveGatewayForSend,
|
|
8276
7991
|
rollbackPassiveSlot: () => rollbackPassiveSlot,
|
|
8277
7992
|
sendMedia: () => sendMedia,
|
|
8278
7993
|
sendText: () => sendText,
|
|
@@ -8281,6 +7996,13 @@ __export(outbound_service_exports, {
|
|
|
8281
7996
|
tryAcquirePassiveSlot: () => tryAcquirePassiveSlot,
|
|
8282
7997
|
unregisterGateway: () => unregisterGateway
|
|
8283
7998
|
});
|
|
7999
|
+
function logFallbackInfo(msg) {
|
|
8000
|
+
try {
|
|
8001
|
+
svcLog ??= createPluginLogger({ prefix: "[outbound]" });
|
|
8002
|
+
svcLog.info(msg);
|
|
8003
|
+
} catch {
|
|
8004
|
+
}
|
|
8005
|
+
}
|
|
8284
8006
|
function reservePassiveReply(params) {
|
|
8285
8007
|
if (!params.replyToId) return { rollback: () => {
|
|
8286
8008
|
} };
|
|
@@ -8310,26 +8032,57 @@ function rollbackPassiveSlot(accountId, msgId) {
|
|
|
8310
8032
|
function registerGateway(accountId, gw) {
|
|
8311
8033
|
gateways.set(accountId, gw);
|
|
8312
8034
|
}
|
|
8313
|
-
function unregisterGateway(accountId) {
|
|
8035
|
+
function unregisterGateway(accountId, expectGw) {
|
|
8036
|
+
if (expectGw) {
|
|
8037
|
+
if (gateways.get(accountId) !== expectGw) return;
|
|
8038
|
+
gateways.delete(accountId);
|
|
8039
|
+
clearQuotaCacheForAccount(accountId);
|
|
8040
|
+
return;
|
|
8041
|
+
}
|
|
8314
8042
|
gateways.delete(accountId);
|
|
8315
8043
|
clearQuotaCacheForAccount(accountId);
|
|
8316
8044
|
}
|
|
8317
8045
|
function getGateway(accountId) {
|
|
8318
8046
|
return gateways.get(accountId);
|
|
8319
8047
|
}
|
|
8048
|
+
function getRegisteredAccountIds() {
|
|
8049
|
+
return [...gateways.keys()];
|
|
8050
|
+
}
|
|
8051
|
+
function resolveGatewayForSend(accountId) {
|
|
8052
|
+
const gw = gateways.get(accountId);
|
|
8053
|
+
if (gw) return { gw, accountId };
|
|
8054
|
+
const running = getRegisteredAccountIds();
|
|
8055
|
+
if (running.length === 1) {
|
|
8056
|
+
const soleAccountId = running[0];
|
|
8057
|
+
const soleGw = gateways.get(soleAccountId);
|
|
8058
|
+
if (!soleGw) return void 0;
|
|
8059
|
+
if (!gatewayFallbackLogged.has(accountId)) {
|
|
8060
|
+
gatewayFallbackLogged.add(accountId);
|
|
8061
|
+
logFallbackInfo(
|
|
8062
|
+
`account "${accountId}" not running; falling back to sole running account "${soleAccountId}"`
|
|
8063
|
+
);
|
|
8064
|
+
}
|
|
8065
|
+
return { gw: soleGw, accountId: soleAccountId, fallbackFrom: accountId };
|
|
8066
|
+
}
|
|
8067
|
+
return void 0;
|
|
8068
|
+
}
|
|
8069
|
+
function notRunningError(accountId) {
|
|
8070
|
+
const running = getRegisteredAccountIds();
|
|
8071
|
+
return `Bot "${accountId}" not running${running.length ? ` (running accounts: ${running.join(", ")})` : ""}`;
|
|
8072
|
+
}
|
|
8320
8073
|
async function sendText(params) {
|
|
8321
8074
|
const accountId = params.account.accountId;
|
|
8322
|
-
const
|
|
8323
|
-
if (!
|
|
8075
|
+
const resolved = resolveGatewayForSend(accountId);
|
|
8076
|
+
if (!resolved) return { error: notRunningError(accountId) };
|
|
8324
8077
|
const target = parseTarget(params.to);
|
|
8325
8078
|
const reservation = reservePassiveReply({
|
|
8326
8079
|
replyToId: params.replyToId,
|
|
8327
|
-
accountId,
|
|
8080
|
+
accountId: resolved.accountId,
|
|
8328
8081
|
scope: target.scope,
|
|
8329
8082
|
quotaReserved: params.quotaReserved
|
|
8330
8083
|
});
|
|
8331
8084
|
try {
|
|
8332
|
-
const result = await gw.sendText(target, params.text, { msgId: reservation.msgId });
|
|
8085
|
+
const result = await resolved.gw.sendText(target, params.text, { msgId: reservation.msgId });
|
|
8333
8086
|
return { messageId: result.id };
|
|
8334
8087
|
} catch (err) {
|
|
8335
8088
|
reservation.rollback();
|
|
@@ -8338,12 +8091,12 @@ async function sendText(params) {
|
|
|
8338
8091
|
}
|
|
8339
8092
|
async function sendMedia(params) {
|
|
8340
8093
|
const accountId = params.account.accountId;
|
|
8341
|
-
const
|
|
8342
|
-
if (!
|
|
8094
|
+
const resolved = resolveGatewayForSend(accountId);
|
|
8095
|
+
if (!resolved) return { error: notRunningError(accountId) };
|
|
8343
8096
|
const target = parseTarget(params.to);
|
|
8344
8097
|
const reservation = reservePassiveReply({
|
|
8345
8098
|
replyToId: params.replyToId,
|
|
8346
|
-
accountId,
|
|
8099
|
+
accountId: resolved.accountId,
|
|
8347
8100
|
scope: target.scope,
|
|
8348
8101
|
quotaReserved: params.quotaReserved
|
|
8349
8102
|
});
|
|
@@ -8352,19 +8105,19 @@ async function sendMedia(params) {
|
|
|
8352
8105
|
const msgId = reservation.msgId;
|
|
8353
8106
|
if (kind === "voice") {
|
|
8354
8107
|
const source = resolveVoiceSource(params.mediaUrl);
|
|
8355
|
-
const result2 = await gw.sendVoice(target, source, { text: params.text, msgId });
|
|
8108
|
+
const result2 = await resolved.gw.sendVoice(target, source, { text: params.text, msgId });
|
|
8356
8109
|
return { messageId: result2.id };
|
|
8357
8110
|
}
|
|
8358
8111
|
if (kind === "video") {
|
|
8359
|
-
const result2 = await gw.sendVideo(target, params.mediaUrl, { text: params.text, msgId });
|
|
8112
|
+
const result2 = await resolved.gw.sendVideo(target, params.mediaUrl, { text: params.text, msgId });
|
|
8360
8113
|
return { messageId: result2.id };
|
|
8361
8114
|
}
|
|
8362
8115
|
if (kind === "file") {
|
|
8363
|
-
const result2 = await gw.sendFile(target, params.mediaUrl, { text: params.text, msgId });
|
|
8116
|
+
const result2 = await resolved.gw.sendFile(target, params.mediaUrl, { text: params.text, msgId });
|
|
8364
8117
|
return { messageId: result2.id };
|
|
8365
8118
|
}
|
|
8366
8119
|
const fileType = MEDIA_KIND_TO_FILE_TYPE[kind];
|
|
8367
|
-
const result = await gw.sendMedia(target, params.mediaUrl, { text: params.text, msgId, fileType });
|
|
8120
|
+
const result = await resolved.gw.sendMedia(target, params.mediaUrl, { text: params.text, msgId, fileType });
|
|
8368
8121
|
return { messageId: result.id };
|
|
8369
8122
|
} catch (err) {
|
|
8370
8123
|
reservation.rollback();
|
|
@@ -8373,17 +8126,17 @@ async function sendMedia(params) {
|
|
|
8373
8126
|
}
|
|
8374
8127
|
async function sendVoice(params) {
|
|
8375
8128
|
const accountId = params.account.accountId;
|
|
8376
|
-
const
|
|
8377
|
-
if (!
|
|
8129
|
+
const resolved = resolveGatewayForSend(accountId);
|
|
8130
|
+
if (!resolved) return { error: notRunningError(accountId) };
|
|
8378
8131
|
const target = parseTarget(params.to);
|
|
8379
8132
|
const reservation = reservePassiveReply({
|
|
8380
8133
|
replyToId: params.replyToId,
|
|
8381
|
-
accountId,
|
|
8134
|
+
accountId: resolved.accountId,
|
|
8382
8135
|
scope: target.scope,
|
|
8383
8136
|
quotaReserved: params.quotaReserved
|
|
8384
8137
|
});
|
|
8385
8138
|
try {
|
|
8386
|
-
const result = await gw.sendVoice(target, params.source, { msgId: reservation.msgId });
|
|
8139
|
+
const result = await resolved.gw.sendVoice(target, params.source, { msgId: reservation.msgId });
|
|
8387
8140
|
return { messageId: result.id };
|
|
8388
8141
|
} catch (err) {
|
|
8389
8142
|
reservation.rollback();
|
|
@@ -8392,17 +8145,17 @@ async function sendVoice(params) {
|
|
|
8392
8145
|
}
|
|
8393
8146
|
async function sendVideo(params) {
|
|
8394
8147
|
const accountId = params.account.accountId;
|
|
8395
|
-
const
|
|
8396
|
-
if (!
|
|
8148
|
+
const resolved = resolveGatewayForSend(accountId);
|
|
8149
|
+
if (!resolved) return { error: notRunningError(accountId) };
|
|
8397
8150
|
const target = parseTarget(params.to);
|
|
8398
8151
|
const reservation = reservePassiveReply({
|
|
8399
8152
|
replyToId: params.replyToId,
|
|
8400
|
-
accountId,
|
|
8153
|
+
accountId: resolved.accountId,
|
|
8401
8154
|
scope: target.scope,
|
|
8402
8155
|
quotaReserved: params.quotaReserved
|
|
8403
8156
|
});
|
|
8404
8157
|
try {
|
|
8405
|
-
const result = await gw.sendVideo(target, params.videoUrl, { msgId: reservation.msgId });
|
|
8158
|
+
const result = await resolved.gw.sendVideo(target, params.videoUrl, { msgId: reservation.msgId });
|
|
8406
8159
|
return { messageId: result.id };
|
|
8407
8160
|
} catch (err) {
|
|
8408
8161
|
reservation.rollback();
|
|
@@ -8427,15 +8180,20 @@ function formatError(err) {
|
|
|
8427
8180
|
}
|
|
8428
8181
|
return { error: String(err) };
|
|
8429
8182
|
}
|
|
8430
|
-
var path4, gateways, MEDIA_KIND_TO_FILE_TYPE, OutboundService;
|
|
8183
|
+
var path4, GATEWAYS_REGISTRY_KEY, globalRegistry, gateways, svcLog, gatewayFallbackLogged, MEDIA_KIND_TO_FILE_TYPE, OutboundService;
|
|
8431
8184
|
var init_outbound_service = __esm({
|
|
8432
8185
|
"src/outbound/outbound-service.ts"() {
|
|
8433
8186
|
"use strict";
|
|
8434
8187
|
path4 = __toESM(require("path"), 1);
|
|
8435
8188
|
init_dist();
|
|
8189
|
+
init_plugin_logger();
|
|
8436
8190
|
init_target();
|
|
8437
8191
|
init_quota_manager();
|
|
8438
|
-
|
|
8192
|
+
GATEWAYS_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("openclaw-qqbot.gateways");
|
|
8193
|
+
globalRegistry = globalThis;
|
|
8194
|
+
gateways = globalRegistry[GATEWAYS_REGISTRY_KEY] ?? /* @__PURE__ */ new Map();
|
|
8195
|
+
globalRegistry[GATEWAYS_REGISTRY_KEY] = gateways;
|
|
8196
|
+
gatewayFallbackLogged = /* @__PURE__ */ new Set();
|
|
8439
8197
|
MEDIA_KIND_TO_FILE_TYPE = {
|
|
8440
8198
|
image: MediaFileType.IMAGE,
|
|
8441
8199
|
voice: MediaFileType.VOICE,
|
|
@@ -8501,7 +8259,7 @@ var init_outbound_service = __esm({
|
|
|
8501
8259
|
|
|
8502
8260
|
// src/utils/pkg-version.ts
|
|
8503
8261
|
function getPackageVersion() {
|
|
8504
|
-
return true ? "1.0.
|
|
8262
|
+
return true ? "1.0.7" : "unknown";
|
|
8505
8263
|
}
|
|
8506
8264
|
function getOpenclawVersion(runtimeVersion) {
|
|
8507
8265
|
return runtimeVersion && runtimeVersion !== "unknown" ? runtimeVersion : "unknown";
|
|
@@ -8772,86 +8530,460 @@ function getQQBotRuntime() {
|
|
|
8772
8530
|
if (!runtime) throw new Error("QQBot runtime not initialized");
|
|
8773
8531
|
return runtime;
|
|
8774
8532
|
}
|
|
8775
|
-
function tryGetQQBotRuntime() {
|
|
8776
|
-
return runtime;
|
|
8533
|
+
function tryGetQQBotRuntime() {
|
|
8534
|
+
return runtime;
|
|
8535
|
+
}
|
|
8536
|
+
var runtime, exitHooksInstalled;
|
|
8537
|
+
var init_runtime = __esm({
|
|
8538
|
+
"src/runtime.ts"() {
|
|
8539
|
+
"use strict";
|
|
8540
|
+
init_bot_instance();
|
|
8541
|
+
init_ref_index_store();
|
|
8542
|
+
init_pkg_version();
|
|
8543
|
+
runtime = null;
|
|
8544
|
+
exitHooksInstalled = false;
|
|
8545
|
+
}
|
|
8546
|
+
});
|
|
8547
|
+
|
|
8548
|
+
// src/utils/plugin-logger.ts
|
|
8549
|
+
function consoleSink() {
|
|
8550
|
+
const C2 = "\x1B[36m", Y = "\x1B[33m", R = "\x1B[31m", G = "\x1B[90m", X = "\x1B[0m";
|
|
8551
|
+
return {
|
|
8552
|
+
debug: (m3) => console.debug(`${G}[qqbot]${X}`, m3),
|
|
8553
|
+
info: (m3) => console.log(`${C2}[qqbot]${X}`, m3),
|
|
8554
|
+
warn: (m3) => console.warn(`${Y}[qqbot]${X}`, m3),
|
|
8555
|
+
error: (m3) => console.error(`${R}[qqbot]${X}`, m3)
|
|
8556
|
+
};
|
|
8557
|
+
}
|
|
8558
|
+
function enrichMeta(meta) {
|
|
8559
|
+
const ctx = getRequestContext();
|
|
8560
|
+
if (!ctx) return meta;
|
|
8561
|
+
const trace = {};
|
|
8562
|
+
if (ctx.accountId) trace.accountId = ctx.accountId;
|
|
8563
|
+
if (ctx.messageId) trace.messageId = ctx.messageId;
|
|
8564
|
+
if (ctx.openId) trace.openId = ctx.openId;
|
|
8565
|
+
if (Object.keys(trace).length === 0) return meta;
|
|
8566
|
+
return meta ? { ...trace, ...meta } : trace;
|
|
8567
|
+
}
|
|
8568
|
+
function frameworkSink() {
|
|
8569
|
+
const resolve2 = () => {
|
|
8570
|
+
try {
|
|
8571
|
+
const r = tryGetQQBotRuntime();
|
|
8572
|
+
if (r?.logging) {
|
|
8573
|
+
const child = r.logging.getChildLogger({ subsystem: "qqbot/core" });
|
|
8574
|
+
return {
|
|
8575
|
+
debug: child.debug?.bind(child),
|
|
8576
|
+
info: child.info.bind(child),
|
|
8577
|
+
warn: child.warn.bind(child),
|
|
8578
|
+
error: child.error.bind(child)
|
|
8579
|
+
};
|
|
8580
|
+
}
|
|
8581
|
+
} catch {
|
|
8582
|
+
}
|
|
8583
|
+
return consoleSink();
|
|
8584
|
+
};
|
|
8585
|
+
return {
|
|
8586
|
+
debug: (msg, meta) => resolve2().debug?.(msg, meta),
|
|
8587
|
+
info: (msg, meta) => resolve2().info(msg, meta),
|
|
8588
|
+
warn: (msg, meta) => resolve2().warn(msg, meta),
|
|
8589
|
+
error: (msg, meta) => resolve2().error(msg, meta)
|
|
8590
|
+
};
|
|
8591
|
+
}
|
|
8592
|
+
function createPluginLogger(opts = {}) {
|
|
8593
|
+
const output = opts.output ?? (opts.forceConsole ? consoleSink() : frameworkSink());
|
|
8594
|
+
const prefix = opts.prefix ?? "";
|
|
8595
|
+
const fmt = (msg) => prefix ? `${prefix} ${msg}` : msg;
|
|
8596
|
+
const buildChild = (parentPrefix, tag) => createPluginLogger({
|
|
8597
|
+
output,
|
|
8598
|
+
prefix: parentPrefix ? `${parentPrefix}[${tag}]` : `[${tag}]`
|
|
8599
|
+
});
|
|
8600
|
+
return {
|
|
8601
|
+
info: (msg, meta) => output.info(fmt(msg), enrichMeta(meta)),
|
|
8602
|
+
warn: (msg, meta) => output.warn(fmt(msg), enrichMeta(meta)),
|
|
8603
|
+
error: (msg, meta) => output.error(fmt(msg), enrichMeta(meta)),
|
|
8604
|
+
debug: (msg, meta) => output.debug(fmt(msg), enrichMeta(meta)),
|
|
8605
|
+
child: (tag) => buildChild(prefix, tag)
|
|
8606
|
+
};
|
|
8607
|
+
}
|
|
8608
|
+
var init_plugin_logger = __esm({
|
|
8609
|
+
"src/utils/plugin-logger.ts"() {
|
|
8610
|
+
"use strict";
|
|
8611
|
+
init_request_context();
|
|
8612
|
+
init_runtime();
|
|
8613
|
+
}
|
|
8614
|
+
});
|
|
8615
|
+
|
|
8616
|
+
// src/features/credential-backup.ts
|
|
8617
|
+
function getBackupPath() {
|
|
8618
|
+
return import_node_path3.default.join(getQQBotDataDir("data"), BACKUP_DIR, BACKUP_FILENAME);
|
|
8619
|
+
}
|
|
8620
|
+
function saveCredentialBackup(accountId, appId, clientSecret) {
|
|
8621
|
+
if (!appId || !clientSecret) return;
|
|
8622
|
+
try {
|
|
8623
|
+
const backupPath = getBackupPath();
|
|
8624
|
+
const dir = import_node_path3.default.dirname(backupPath);
|
|
8625
|
+
if (!import_node_fs3.default.existsSync(dir)) {
|
|
8626
|
+
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
8627
|
+
}
|
|
8628
|
+
const data = {
|
|
8629
|
+
accountId,
|
|
8630
|
+
appId,
|
|
8631
|
+
clientSecret,
|
|
8632
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8633
|
+
};
|
|
8634
|
+
const tmpPath = backupPath + ".tmp";
|
|
8635
|
+
import_node_fs3.default.writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
8636
|
+
import_node_fs3.default.renameSync(tmpPath, backupPath);
|
|
8637
|
+
} catch (err) {
|
|
8638
|
+
backupLog.debug(`save failed: ${err instanceof Error ? err.message : String(err)}`, { accountId });
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
function loadCredentialBackup(accountId) {
|
|
8642
|
+
try {
|
|
8643
|
+
const backupPath = getBackupPath();
|
|
8644
|
+
if (import_node_fs3.default.existsSync(backupPath)) {
|
|
8645
|
+
return readBackupFile(backupPath, accountId);
|
|
8646
|
+
}
|
|
8647
|
+
return null;
|
|
8648
|
+
} catch (err) {
|
|
8649
|
+
backupLog.debug(`load failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
8650
|
+
return null;
|
|
8651
|
+
}
|
|
8652
|
+
}
|
|
8653
|
+
function readBackupFile(filePath, accountId) {
|
|
8654
|
+
const raw = import_node_fs3.default.readFileSync(filePath, "utf8");
|
|
8655
|
+
const data = JSON.parse(raw);
|
|
8656
|
+
if (!data.appId || !data.clientSecret) return null;
|
|
8657
|
+
if (accountId && data.accountId !== accountId) return null;
|
|
8658
|
+
return data;
|
|
8659
|
+
}
|
|
8660
|
+
var import_node_fs3, import_node_path3, backupLog, BACKUP_DIR, BACKUP_FILENAME;
|
|
8661
|
+
var init_credential_backup = __esm({
|
|
8662
|
+
"src/features/credential-backup.ts"() {
|
|
8663
|
+
"use strict";
|
|
8664
|
+
import_node_fs3 = __toESM(require("fs"), 1);
|
|
8665
|
+
import_node_path3 = __toESM(require("path"), 1);
|
|
8666
|
+
init_platform();
|
|
8667
|
+
init_plugin_logger();
|
|
8668
|
+
backupLog = createPluginLogger({ prefix: "[credential-backup]" });
|
|
8669
|
+
BACKUP_DIR = "credential-backup";
|
|
8670
|
+
BACKUP_FILENAME = "current.json";
|
|
8671
|
+
}
|
|
8672
|
+
});
|
|
8673
|
+
|
|
8674
|
+
// src/config.ts
|
|
8675
|
+
var config_exports = {};
|
|
8676
|
+
__export(config_exports, {
|
|
8677
|
+
DEFAULT_ACCOUNT_ID: () => DEFAULT_ACCOUNT_ID,
|
|
8678
|
+
applyQQBotAccountConfig: () => applyQQBotAccountConfig,
|
|
8679
|
+
isGroupAllowed: () => isGroupAllowed,
|
|
8680
|
+
listQQBotAccountIds: () => listQQBotAccountIds,
|
|
8681
|
+
resolveDefaultQQBotAccountId: () => resolveDefaultQQBotAccountId,
|
|
8682
|
+
resolveGroupAllowFrom: () => resolveGroupAllowFrom,
|
|
8683
|
+
resolveGroupCoalesceConfig: () => resolveGroupCoalesceConfig,
|
|
8684
|
+
resolveGroupCoalesceEnabled: () => resolveGroupCoalesceEnabled,
|
|
8685
|
+
resolveGroupConfig: () => resolveGroupConfig,
|
|
8686
|
+
resolveGroupConfigFromAccount: () => resolveGroupConfigFromAccount,
|
|
8687
|
+
resolveGroupName: () => resolveGroupName,
|
|
8688
|
+
resolveGroupPolicy: () => resolveGroupPolicy,
|
|
8689
|
+
resolveGroupPrompt: () => resolveGroupPrompt,
|
|
8690
|
+
resolveHistoryLimit: () => resolveHistoryLimit,
|
|
8691
|
+
resolveIgnoreOtherMentions: () => resolveIgnoreOtherMentions,
|
|
8692
|
+
resolveMentionPatterns: () => resolveMentionPatterns,
|
|
8693
|
+
resolveQQBotAccount: () => resolveQQBotAccount,
|
|
8694
|
+
resolveQQBotEnvAppId: () => resolveQQBotEnvAppId,
|
|
8695
|
+
resolveQQBotEnvClientSecret: () => resolveQQBotEnvClientSecret,
|
|
8696
|
+
resolveRequireMention: () => resolveRequireMention,
|
|
8697
|
+
resolveToolPolicy: () => resolveToolPolicy,
|
|
8698
|
+
resolveUserAgentSuffix: () => resolveUserAgentSuffix
|
|
8699
|
+
});
|
|
8700
|
+
function resolveMentionPatterns(cfg, agentId) {
|
|
8701
|
+
if (agentId) {
|
|
8702
|
+
const agents = cfg.agents;
|
|
8703
|
+
const entry = agents?.list?.find((a) => a.id?.trim().toLowerCase() === agentId.trim().toLowerCase());
|
|
8704
|
+
const agentGroupChat = entry?.groupChat;
|
|
8705
|
+
if (agentGroupChat && Object.hasOwn(agentGroupChat, "mentionPatterns")) {
|
|
8706
|
+
return agentGroupChat.mentionPatterns ?? [];
|
|
8707
|
+
}
|
|
8708
|
+
}
|
|
8709
|
+
const globalGroupChat = cfg?.messages?.groupChat;
|
|
8710
|
+
if (globalGroupChat && typeof globalGroupChat === "object" && Object.hasOwn(globalGroupChat, "mentionPatterns")) {
|
|
8711
|
+
return globalGroupChat.mentionPatterns ?? [];
|
|
8712
|
+
}
|
|
8713
|
+
return [];
|
|
8714
|
+
}
|
|
8715
|
+
function evaluateMatchedGroupAccessForPolicy(params) {
|
|
8716
|
+
if (params.groupPolicy === "disabled") {
|
|
8717
|
+
return { allowed: false, groupPolicy: params.groupPolicy, reason: "disabled" };
|
|
8718
|
+
}
|
|
8719
|
+
if (params.groupPolicy === "allowlist") {
|
|
8720
|
+
if (params.requireMatchInput && !params.hasMatchInput) {
|
|
8721
|
+
return { allowed: false, groupPolicy: params.groupPolicy, reason: "missing_match_input" };
|
|
8722
|
+
}
|
|
8723
|
+
if (!params.allowlistConfigured) {
|
|
8724
|
+
return { allowed: false, groupPolicy: params.groupPolicy, reason: "empty_allowlist" };
|
|
8725
|
+
}
|
|
8726
|
+
if (!params.allowlistMatched) {
|
|
8727
|
+
return { allowed: false, groupPolicy: params.groupPolicy, reason: "not_allowlisted" };
|
|
8728
|
+
}
|
|
8729
|
+
}
|
|
8730
|
+
return { allowed: true, groupPolicy: params.groupPolicy, reason: "allowed" };
|
|
8731
|
+
}
|
|
8732
|
+
function resolveGroupPolicy(cfg, accountId) {
|
|
8733
|
+
const account = resolveQQBotAccount(cfg, accountId);
|
|
8734
|
+
return account.config?.groupPolicy ?? DEFAULT_GROUP_POLICY;
|
|
8735
|
+
}
|
|
8736
|
+
function resolveGroupAllowFrom(cfg, accountId) {
|
|
8737
|
+
const account = resolveQQBotAccount(cfg, accountId);
|
|
8738
|
+
return (account.config?.groupAllowFrom ?? []).map((id) => String(id).trim().toUpperCase());
|
|
8739
|
+
}
|
|
8740
|
+
function isGroupAllowed(cfg, groupOpenid, accountId) {
|
|
8741
|
+
const account = resolveQQBotAccount(cfg, accountId);
|
|
8742
|
+
const policy = account.config?.groupPolicy ?? DEFAULT_GROUP_POLICY;
|
|
8743
|
+
const allowList = (account.config?.groupAllowFrom ?? []).map((id) => String(id).trim().toUpperCase());
|
|
8744
|
+
const allowlistConfigured = allowList.length > 0;
|
|
8745
|
+
const allowlistMatched = allowList.some((id) => id === "*" || id === groupOpenid.toUpperCase());
|
|
8746
|
+
return evaluateMatchedGroupAccessForPolicy({
|
|
8747
|
+
groupPolicy: policy,
|
|
8748
|
+
allowlistConfigured,
|
|
8749
|
+
allowlistMatched
|
|
8750
|
+
}).allowed;
|
|
8751
|
+
}
|
|
8752
|
+
function resolveGroupConfigFromAccount(account, groupOpenid) {
|
|
8753
|
+
const groups = account.config?.groups ?? {};
|
|
8754
|
+
const wildcardCfg = groups["*"] ?? {};
|
|
8755
|
+
const specificCfg = groups[groupOpenid] ?? {};
|
|
8756
|
+
const accountDefaultRequireMention = account.config?.defaultRequireMention ?? DEFAULT_GROUP_CONFIG.requireMention;
|
|
8757
|
+
const accountDefaultCoalesce = account.config?.groupCoalesce ?? DEFAULT_GROUP_COALESCE_CONFIG;
|
|
8758
|
+
const coalesce = {
|
|
8759
|
+
enabled: specificCfg.coalesce?.enabled ?? wildcardCfg.coalesce?.enabled ?? accountDefaultCoalesce.enabled ?? DEFAULT_GROUP_COALESCE_CONFIG.enabled
|
|
8760
|
+
};
|
|
8761
|
+
return {
|
|
8762
|
+
requireMention: specificCfg.requireMention ?? wildcardCfg.requireMention ?? accountDefaultRequireMention,
|
|
8763
|
+
ignoreOtherMentions: specificCfg.ignoreOtherMentions ?? wildcardCfg.ignoreOtherMentions ?? DEFAULT_GROUP_CONFIG.ignoreOtherMentions,
|
|
8764
|
+
toolPolicy: specificCfg.toolPolicy ?? wildcardCfg.toolPolicy ?? DEFAULT_GROUP_CONFIG.toolPolicy,
|
|
8765
|
+
name: specificCfg.name ?? wildcardCfg.name ?? DEFAULT_GROUP_CONFIG.name,
|
|
8766
|
+
prompt: specificCfg.prompt ?? wildcardCfg.prompt ?? DEFAULT_GROUP_PROMPT,
|
|
8767
|
+
historyLimit: specificCfg.historyLimit ?? wildcardCfg.historyLimit ?? DEFAULT_GROUP_CONFIG.historyLimit,
|
|
8768
|
+
historyMode: specificCfg.historyMode ?? wildcardCfg.historyMode ?? DEFAULT_GROUP_CONFIG.historyMode,
|
|
8769
|
+
unmentionedInbound: specificCfg.unmentionedInbound ?? wildcardCfg.unmentionedInbound ?? DEFAULT_GROUP_CONFIG.unmentionedInbound,
|
|
8770
|
+
coalesce
|
|
8771
|
+
};
|
|
8772
|
+
}
|
|
8773
|
+
function resolveGroupConfig(cfg, groupOpenid, accountId) {
|
|
8774
|
+
return resolveGroupConfigFromAccount(resolveQQBotAccount(cfg, accountId), groupOpenid);
|
|
8775
|
+
}
|
|
8776
|
+
function resolveHistoryLimit(cfg, groupOpenid, accountId) {
|
|
8777
|
+
return Math.max(0, resolveGroupConfig(cfg, groupOpenid, accountId).historyLimit);
|
|
8778
|
+
}
|
|
8779
|
+
function resolveGroupPrompt(cfg, groupOpenid, accountId) {
|
|
8780
|
+
return resolveGroupConfig(cfg, groupOpenid, accountId).prompt;
|
|
8781
|
+
}
|
|
8782
|
+
function resolveRequireMention(cfg, groupOpenid, accountId) {
|
|
8783
|
+
return resolveGroupConfig(cfg, groupOpenid, accountId).requireMention;
|
|
8784
|
+
}
|
|
8785
|
+
function resolveIgnoreOtherMentions(cfg, groupOpenid, accountId) {
|
|
8786
|
+
return resolveGroupConfig(cfg, groupOpenid, accountId).ignoreOtherMentions;
|
|
8787
|
+
}
|
|
8788
|
+
function resolveToolPolicy(cfg, groupOpenid, accountId) {
|
|
8789
|
+
return resolveGroupConfig(cfg, groupOpenid, accountId).toolPolicy;
|
|
8790
|
+
}
|
|
8791
|
+
function resolveGroupName(cfg, groupOpenid, accountId) {
|
|
8792
|
+
const name = resolveGroupConfig(cfg, groupOpenid, accountId).name;
|
|
8793
|
+
return name || groupOpenid.slice(0, 8);
|
|
8794
|
+
}
|
|
8795
|
+
function resolveUserAgentSuffix(cfg) {
|
|
8796
|
+
const qqbot = cfg.channels?.qqbot;
|
|
8797
|
+
return qqbot?.userAgentSuffix ? String(qqbot.userAgentSuffix).trim() : "";
|
|
8798
|
+
}
|
|
8799
|
+
function normalizeAppId(raw) {
|
|
8800
|
+
if (raw === null || raw === void 0) return "";
|
|
8801
|
+
return String(raw).trim();
|
|
8802
|
+
}
|
|
8803
|
+
function firstNonEmptyEnv(...values) {
|
|
8804
|
+
for (const value of values) {
|
|
8805
|
+
if (value?.trim()) return value.trim();
|
|
8806
|
+
}
|
|
8807
|
+
return "";
|
|
8808
|
+
}
|
|
8809
|
+
function resolveQQBotEnvAppId() {
|
|
8810
|
+
return firstNonEmptyEnv(process.env.QQBOT_APPID);
|
|
8811
|
+
}
|
|
8812
|
+
function resolveQQBotEnvClientSecret() {
|
|
8813
|
+
return firstNonEmptyEnv(process.env.QQBOT_SECRET);
|
|
8814
|
+
}
|
|
8815
|
+
function listQQBotAccountIds(cfg) {
|
|
8816
|
+
const ids = /* @__PURE__ */ new Set();
|
|
8817
|
+
const qqbot = cfg.channels?.qqbot;
|
|
8818
|
+
if (qqbot?.appId || resolveQQBotEnvAppId()) {
|
|
8819
|
+
ids.add(DEFAULT_ACCOUNT_ID);
|
|
8820
|
+
}
|
|
8821
|
+
if (qqbot?.accounts) {
|
|
8822
|
+
for (const accountId of Object.keys(qqbot.accounts)) {
|
|
8823
|
+
if (qqbot.accounts[accountId]?.appId) {
|
|
8824
|
+
ids.add(accountId);
|
|
8825
|
+
}
|
|
8826
|
+
}
|
|
8827
|
+
}
|
|
8828
|
+
return Array.from(ids);
|
|
8829
|
+
}
|
|
8830
|
+
function accountShapeRunnable(params) {
|
|
8831
|
+
if (!params.appId || !params.enabled) return false;
|
|
8832
|
+
if (params.hasSecretSource) return true;
|
|
8833
|
+
try {
|
|
8834
|
+
return loadCredentialBackup(params.accountId) !== null;
|
|
8835
|
+
} catch {
|
|
8836
|
+
return false;
|
|
8837
|
+
}
|
|
8777
8838
|
}
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8839
|
+
function resolveDefaultQQBotAccountId(cfg) {
|
|
8840
|
+
const qqbot = cfg.channels?.qqbot;
|
|
8841
|
+
if (qqbot?.appId || resolveQQBotEnvAppId()) {
|
|
8842
|
+
const runnable = accountShapeRunnable({
|
|
8843
|
+
appId: normalizeAppId(qqbot?.appId) || normalizeAppId(resolveQQBotEnvAppId()),
|
|
8844
|
+
enabled: qqbot?.enabled !== false,
|
|
8845
|
+
hasSecretSource: Boolean(
|
|
8846
|
+
qqbot?.clientSecret || qqbot?.clientSecretFile || resolveQQBotEnvClientSecret()
|
|
8847
|
+
),
|
|
8848
|
+
accountId: DEFAULT_ACCOUNT_ID
|
|
8849
|
+
});
|
|
8850
|
+
if (runnable) return DEFAULT_ACCOUNT_ID;
|
|
8851
|
+
}
|
|
8852
|
+
if (qqbot?.accounts) {
|
|
8853
|
+
for (const [accountId, account] of Object.entries(qqbot.accounts)) {
|
|
8854
|
+
if (!account) continue;
|
|
8855
|
+
const runnable = accountShapeRunnable({
|
|
8856
|
+
appId: normalizeAppId(account.appId),
|
|
8857
|
+
enabled: account.enabled !== false,
|
|
8858
|
+
hasSecretSource: Boolean(account.clientSecret || account.clientSecretFile),
|
|
8859
|
+
accountId
|
|
8860
|
+
});
|
|
8861
|
+
if (runnable) return accountId;
|
|
8862
|
+
}
|
|
8863
|
+
const ids = Object.keys(qqbot.accounts);
|
|
8864
|
+
if (ids.length > 0 && ids.every((id) => !qqbot.accounts?.[id]?.appId)) {
|
|
8865
|
+
return ids[0];
|
|
8866
|
+
}
|
|
8867
|
+
}
|
|
8868
|
+
return DEFAULT_ACCOUNT_ID;
|
|
8869
|
+
}
|
|
8870
|
+
function resolveQQBotAccount(cfg, accountId) {
|
|
8871
|
+
const resolvedAccountId = accountId ?? resolveDefaultQQBotAccountId(cfg);
|
|
8872
|
+
const qqbot = cfg.channels?.qqbot;
|
|
8873
|
+
let accountConfig = {};
|
|
8874
|
+
let appId = "";
|
|
8875
|
+
let clientSecret = "";
|
|
8876
|
+
let secretSource = "none";
|
|
8877
|
+
if (resolvedAccountId === DEFAULT_ACCOUNT_ID) {
|
|
8878
|
+
const { accounts: _accounts, ...topLevelConfig } = qqbot ?? {};
|
|
8879
|
+
accountConfig = {
|
|
8880
|
+
...topLevelConfig,
|
|
8881
|
+
markdownSupport: qqbot?.markdownSupport ?? true
|
|
8882
|
+
};
|
|
8883
|
+
appId = normalizeAppId(qqbot?.appId);
|
|
8884
|
+
} else {
|
|
8885
|
+
const account = qqbot?.accounts?.[resolvedAccountId];
|
|
8886
|
+
accountConfig = account ?? {};
|
|
8887
|
+
appId = normalizeAppId(account?.appId);
|
|
8888
|
+
}
|
|
8889
|
+
if (accountConfig.clientSecret) {
|
|
8890
|
+
clientSecret = accountConfig.clientSecret;
|
|
8891
|
+
secretSource = "config";
|
|
8892
|
+
} else if (accountConfig.clientSecretFile) {
|
|
8893
|
+
secretSource = "file";
|
|
8894
|
+
} else if (resolvedAccountId === DEFAULT_ACCOUNT_ID && resolveQQBotEnvClientSecret()) {
|
|
8895
|
+
clientSecret = resolveQQBotEnvClientSecret();
|
|
8896
|
+
secretSource = "env";
|
|
8897
|
+
}
|
|
8898
|
+
if (!appId && resolvedAccountId === DEFAULT_ACCOUNT_ID) {
|
|
8899
|
+
appId = normalizeAppId(resolveQQBotEnvAppId());
|
|
8787
8900
|
}
|
|
8788
|
-
});
|
|
8789
|
-
|
|
8790
|
-
// src/utils/plugin-logger.ts
|
|
8791
|
-
function consoleSink() {
|
|
8792
|
-
const C2 = "\x1B[36m", Y = "\x1B[33m", R = "\x1B[31m", G = "\x1B[90m", X = "\x1B[0m";
|
|
8793
8901
|
return {
|
|
8794
|
-
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
|
|
8902
|
+
accountId: resolvedAccountId,
|
|
8903
|
+
name: accountConfig.name,
|
|
8904
|
+
enabled: accountConfig.enabled !== false,
|
|
8905
|
+
appId,
|
|
8906
|
+
clientSecret,
|
|
8907
|
+
secretSource,
|
|
8908
|
+
systemPrompt: accountConfig.systemPrompt,
|
|
8909
|
+
markdownSupport: accountConfig.markdownSupport !== false,
|
|
8910
|
+
commandPanelNative: accountConfig.commands?.native !== false,
|
|
8911
|
+
userAgentSuffix: resolveUserAgentSuffix(cfg),
|
|
8912
|
+
config: accountConfig
|
|
8798
8913
|
};
|
|
8799
8914
|
}
|
|
8800
|
-
function
|
|
8801
|
-
const
|
|
8802
|
-
if (
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
if (r?.logging) {
|
|
8815
|
-
const child = r.logging.getChildLogger({ subsystem: "qqbot/core" });
|
|
8816
|
-
return {
|
|
8817
|
-
debug: child.debug?.bind(child),
|
|
8818
|
-
info: child.info.bind(child),
|
|
8819
|
-
warn: child.warn.bind(child),
|
|
8820
|
-
error: child.error.bind(child)
|
|
8821
|
-
};
|
|
8915
|
+
function applyQQBotAccountConfig(cfg, accountId, input) {
|
|
8916
|
+
const next = { ...cfg };
|
|
8917
|
+
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
8918
|
+
const existingConfig = next.channels?.qqbot || {};
|
|
8919
|
+
const allowFrom = existingConfig.allowFrom ?? ["*"];
|
|
8920
|
+
next.channels = {
|
|
8921
|
+
...next.channels,
|
|
8922
|
+
qqbot: {
|
|
8923
|
+
...next.channels?.qqbot || {},
|
|
8924
|
+
enabled: true,
|
|
8925
|
+
allowFrom,
|
|
8926
|
+
...input.appId ? { appId: input.appId } : {},
|
|
8927
|
+
...input.clientSecret ? { clientSecret: input.clientSecret } : input.clientSecretFile ? { clientSecretFile: input.clientSecretFile } : {},
|
|
8928
|
+
...input.name ? { name: input.name } : {}
|
|
8822
8929
|
}
|
|
8823
|
-
}
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8930
|
+
};
|
|
8931
|
+
} else {
|
|
8932
|
+
const existingAccountConfig = next.channels?.qqbot?.accounts?.[accountId] || {};
|
|
8933
|
+
const allowFrom = existingAccountConfig.allowFrom ?? ["*"];
|
|
8934
|
+
next.channels = {
|
|
8935
|
+
...next.channels,
|
|
8936
|
+
qqbot: {
|
|
8937
|
+
...next.channels?.qqbot || {},
|
|
8938
|
+
enabled: true,
|
|
8939
|
+
accounts: {
|
|
8940
|
+
...next.channels?.qqbot?.accounts || {},
|
|
8941
|
+
[accountId]: {
|
|
8942
|
+
...next.channels?.qqbot?.accounts?.[accountId] || {},
|
|
8943
|
+
enabled: true,
|
|
8944
|
+
allowFrom,
|
|
8945
|
+
...input.appId ? { appId: input.appId } : {},
|
|
8946
|
+
...input.clientSecret ? { clientSecret: input.clientSecret } : input.clientSecretFile ? { clientSecretFile: input.clientSecretFile } : {},
|
|
8947
|
+
...input.name ? { name: input.name } : {}
|
|
8948
|
+
}
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8951
|
+
};
|
|
8952
|
+
}
|
|
8953
|
+
return next;
|
|
8833
8954
|
}
|
|
8834
|
-
function
|
|
8835
|
-
|
|
8836
|
-
const prefix = opts.prefix ?? "";
|
|
8837
|
-
const fmt = (msg) => prefix ? `${prefix} ${msg}` : msg;
|
|
8838
|
-
const buildChild = (parentPrefix, tag) => createPluginLogger({
|
|
8839
|
-
output,
|
|
8840
|
-
prefix: parentPrefix ? `${parentPrefix}[${tag}]` : `[${tag}]`
|
|
8841
|
-
});
|
|
8842
|
-
return {
|
|
8843
|
-
info: (msg, meta) => output.info(fmt(msg), enrichMeta(meta)),
|
|
8844
|
-
warn: (msg, meta) => output.warn(fmt(msg), enrichMeta(meta)),
|
|
8845
|
-
error: (msg, meta) => output.error(fmt(msg), enrichMeta(meta)),
|
|
8846
|
-
debug: (msg, meta) => output.debug(fmt(msg), enrichMeta(meta)),
|
|
8847
|
-
child: (tag) => buildChild(prefix, tag)
|
|
8848
|
-
};
|
|
8955
|
+
function resolveGroupCoalesceConfig(cfg, groupOpenid, accountId) {
|
|
8956
|
+
return resolveGroupConfig(cfg, groupOpenid, accountId).coalesce;
|
|
8849
8957
|
}
|
|
8850
|
-
|
|
8851
|
-
|
|
8958
|
+
function resolveGroupCoalesceEnabled(cfg, groupOpenid, accountId) {
|
|
8959
|
+
return resolveGroupCoalesceConfig(cfg, groupOpenid, accountId).enabled;
|
|
8960
|
+
}
|
|
8961
|
+
var DEFAULT_ACCOUNT_ID, DEFAULT_GROUP_POLICY, DEFAULT_GROUP_HISTORY_LIMIT, DEFAULT_GROUP_COALESCE_CONFIG, DEFAULT_GROUP_CONFIG, DEFAULT_GROUP_PROMPT;
|
|
8962
|
+
var init_config = __esm({
|
|
8963
|
+
"src/config.ts"() {
|
|
8852
8964
|
"use strict";
|
|
8853
|
-
|
|
8854
|
-
|
|
8965
|
+
init_credential_backup();
|
|
8966
|
+
DEFAULT_ACCOUNT_ID = "default";
|
|
8967
|
+
DEFAULT_GROUP_POLICY = "open";
|
|
8968
|
+
DEFAULT_GROUP_HISTORY_LIMIT = 20;
|
|
8969
|
+
DEFAULT_GROUP_COALESCE_CONFIG = {
|
|
8970
|
+
enabled: true
|
|
8971
|
+
};
|
|
8972
|
+
DEFAULT_GROUP_CONFIG = {
|
|
8973
|
+
requireMention: true,
|
|
8974
|
+
ignoreOtherMentions: false,
|
|
8975
|
+
toolPolicy: "restricted",
|
|
8976
|
+
name: "",
|
|
8977
|
+
historyLimit: DEFAULT_GROUP_HISTORY_LIMIT,
|
|
8978
|
+
historyMode: "clear",
|
|
8979
|
+
unmentionedInbound: "user_request",
|
|
8980
|
+
coalesce: DEFAULT_GROUP_COALESCE_CONFIG
|
|
8981
|
+
};
|
|
8982
|
+
DEFAULT_GROUP_PROMPT = [
|
|
8983
|
+
"\u82E5\u53D1\u9001\u8005\u4E3A\u673A\u5668\u4EBA\uFF0C\u4EC5\u5728\u5BF9\u65B9\u660E\u786E@\u4F60\u63D0\u95EE\u6216\u8BF7\u6C42\u534F\u52A9\u5177\u4F53\u4EFB\u52A1\u65F6\uFF0C\u4EE5\u7B80\u6D01\u660E\u4E86\u7684\u5185\u5BB9\u56DE\u590D\uFF0C",
|
|
8984
|
+
"\u907F\u514D\u4E0E\u5176\u4ED6\u673A\u5668\u4EBA\u4EA7\u751F\u62A2\u7B54\u6216\u591A\u8F6E\u65E0\u610F\u4E49\u5BF9\u8BDD\u3002",
|
|
8985
|
+
"\u5728\u7FA4\u804A\u4E2D\u4F18\u5148\u8BA9\u4EBA\u7C7B\u7528\u6237\u7684\u6D88\u606F\u5F97\u5230\u54CD\u5E94\uFF0C\u673A\u5668\u4EBA\u4E4B\u95F4\u4FDD\u6301\u534F\u4F5C\u800C\u975E\u7ADE\u4E89\uFF0C\u786E\u4FDD\u5BF9\u8BDD\u6709\u5E8F\u4E0D\u5237\u5C4F\u3002"
|
|
8986
|
+
].join("");
|
|
8855
8987
|
}
|
|
8856
8988
|
});
|
|
8857
8989
|
|
|
@@ -10586,14 +10718,15 @@ async function sendMedia2(params) {
|
|
|
10586
10718
|
return { error: resolved.error };
|
|
10587
10719
|
}
|
|
10588
10720
|
const kind = params.mediaKind ?? (params.mimeType ? inferMediaKindFromMime(params.mimeType) : void 0) ?? inferMediaKind(resolved.path);
|
|
10589
|
-
const
|
|
10590
|
-
if (!
|
|
10591
|
-
return { error:
|
|
10721
|
+
const sendGateway = resolveGatewayForSend(accountId);
|
|
10722
|
+
if (!sendGateway) {
|
|
10723
|
+
return { error: notRunningError(accountId) };
|
|
10592
10724
|
}
|
|
10725
|
+
const gw = sendGateway.gw;
|
|
10593
10726
|
const target = parseTarget(params.to);
|
|
10594
10727
|
const reservation = params.quotaReserved || !params.replyToId ? { canReply: Boolean(params.replyToId), rollback: () => {
|
|
10595
10728
|
} } : checkAndConsumePassiveReplyQuota({
|
|
10596
|
-
accountId,
|
|
10729
|
+
accountId: sendGateway.accountId,
|
|
10597
10730
|
msgId: params.replyToId,
|
|
10598
10731
|
scope: target.scope,
|
|
10599
10732
|
log: log5
|
|
@@ -10845,58 +10978,7 @@ var import_channel_core = require("openclaw/plugin-sdk/channel-core");
|
|
|
10845
10978
|
var import_account_id = require("openclaw/plugin-sdk/account-id");
|
|
10846
10979
|
var import_core = require("openclaw/plugin-sdk/core");
|
|
10847
10980
|
init_config();
|
|
10848
|
-
|
|
10849
|
-
// src/features/credential-backup.ts
|
|
10850
|
-
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
10851
|
-
var import_node_path3 = __toESM(require("path"), 1);
|
|
10852
|
-
init_platform();
|
|
10853
|
-
init_plugin_logger();
|
|
10854
|
-
var backupLog = createPluginLogger({ prefix: "[credential-backup]" });
|
|
10855
|
-
var BACKUP_DIR = "credential-backup";
|
|
10856
|
-
var BACKUP_FILENAME = "current.json";
|
|
10857
|
-
function getBackupPath() {
|
|
10858
|
-
return import_node_path3.default.join(getQQBotDataDir("data"), BACKUP_DIR, BACKUP_FILENAME);
|
|
10859
|
-
}
|
|
10860
|
-
function saveCredentialBackup(accountId, appId, clientSecret) {
|
|
10861
|
-
if (!appId || !clientSecret) return;
|
|
10862
|
-
try {
|
|
10863
|
-
const backupPath = getBackupPath();
|
|
10864
|
-
const dir = import_node_path3.default.dirname(backupPath);
|
|
10865
|
-
if (!import_node_fs3.default.existsSync(dir)) {
|
|
10866
|
-
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
10867
|
-
}
|
|
10868
|
-
const data = {
|
|
10869
|
-
accountId,
|
|
10870
|
-
appId,
|
|
10871
|
-
clientSecret,
|
|
10872
|
-
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10873
|
-
};
|
|
10874
|
-
const tmpPath = backupPath + ".tmp";
|
|
10875
|
-
import_node_fs3.default.writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
10876
|
-
import_node_fs3.default.renameSync(tmpPath, backupPath);
|
|
10877
|
-
} catch (err) {
|
|
10878
|
-
backupLog.debug(`save failed: ${err instanceof Error ? err.message : String(err)}`, { accountId });
|
|
10879
|
-
}
|
|
10880
|
-
}
|
|
10881
|
-
function loadCredentialBackup(accountId) {
|
|
10882
|
-
try {
|
|
10883
|
-
const backupPath = getBackupPath();
|
|
10884
|
-
if (import_node_fs3.default.existsSync(backupPath)) {
|
|
10885
|
-
return readBackupFile(backupPath, accountId);
|
|
10886
|
-
}
|
|
10887
|
-
return null;
|
|
10888
|
-
} catch (err) {
|
|
10889
|
-
backupLog.debug(`load failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10890
|
-
return null;
|
|
10891
|
-
}
|
|
10892
|
-
}
|
|
10893
|
-
function readBackupFile(filePath, accountId) {
|
|
10894
|
-
const raw = import_node_fs3.default.readFileSync(filePath, "utf8");
|
|
10895
|
-
const data = JSON.parse(raw);
|
|
10896
|
-
if (!data.appId || !data.clientSecret) return null;
|
|
10897
|
-
if (accountId && data.accountId !== accountId) return null;
|
|
10898
|
-
return data;
|
|
10899
|
-
}
|
|
10981
|
+
init_credential_backup();
|
|
10900
10982
|
|
|
10901
10983
|
// src/setup/surface.ts
|
|
10902
10984
|
init_setup();
|
|
@@ -14410,6 +14492,7 @@ function mapQuote(quote) {
|
|
|
14410
14492
|
return {
|
|
14411
14493
|
content: quote.text,
|
|
14412
14494
|
senderId: quote.entry?.senderId ?? "",
|
|
14495
|
+
messageId: quote.entry?.messageId,
|
|
14413
14496
|
attachments: quote.attachments
|
|
14414
14497
|
};
|
|
14415
14498
|
}
|
|
@@ -14626,7 +14709,24 @@ function buildCtxPayload(params) {
|
|
|
14626
14709
|
},
|
|
14627
14710
|
reply: {
|
|
14628
14711
|
to: envelope.targetId,
|
|
14629
|
-
|
|
14712
|
+
/**
|
|
14713
|
+
* ReplyToId 契约语义 = 当前消息回复(引用)的那条消息的 ID —— 对齐
|
|
14714
|
+
* telegram 原生通道(replyHead?.messageId ?? visibleReplyTarget?.id),
|
|
14715
|
+
* 无引用时必须为 undefined。框架将其渲染为模型可见 Conversation info
|
|
14716
|
+
* 的 reply_to_id 字段。
|
|
14717
|
+
*
|
|
14718
|
+
* 历史版本误填 envelope.messageId(消息自身 ID),导致每条消息都呈现
|
|
14719
|
+
* message_id == reply_to_id —— 被上层 agent 的 AGENTS 规则判为「内部
|
|
14720
|
+
* 回灌、非新指令」而拒绝响应(2026-09-22 事故)。
|
|
14721
|
+
*
|
|
14722
|
+
* QQ 被动回复锚点不依赖此字段:deliverCtx.replyToId / msgid-cache 兜底
|
|
14723
|
+
* (resolvePassiveFirstReplyToId)/ attachMsgIdWithQuota 均独立取值,
|
|
14724
|
+
* threading resolveReplyToMode='off' 阻断框架隐式回复线程。
|
|
14725
|
+
*
|
|
14726
|
+
* 防御守卫:即使上游异常传入当前消息 ID(自引用),也强制置空——
|
|
14727
|
+
* 「reply_to_id == message_id」这一假回灌签名在任何路径都不允许再现。
|
|
14728
|
+
*/
|
|
14729
|
+
replyToId: envelope.quote?.messageId && envelope.quote.messageId !== envelope.messageId ? envelope.quote.messageId : void 0,
|
|
14630
14730
|
originatingTo: envelope.targetId
|
|
14631
14731
|
},
|
|
14632
14732
|
access: {
|
|
@@ -14635,7 +14735,14 @@ function buildCtxPayload(params) {
|
|
|
14635
14735
|
command: isSlashCommand ? { kind: "text-slash", body: assembled.rawBody, authorized: true } : void 0,
|
|
14636
14736
|
media: mediaFacts.length > 0 ? mediaFacts : void 0,
|
|
14637
14737
|
supplemental: {
|
|
14638
|
-
quote
|
|
14738
|
+
// quote.id 同样必须是「被引用消息」的真实 ID(ref-index 命中时),
|
|
14739
|
+
// 而非当前消息 ID——框架经 applySupplementalContext 映射为
|
|
14740
|
+
// ctx.ReplyToId / "Reply target of current user message"。
|
|
14741
|
+
quote: envelope.quote ? {
|
|
14742
|
+
...envelope.quote.messageId && envelope.quote.messageId !== envelope.messageId ? { id: envelope.quote.messageId } : {},
|
|
14743
|
+
body: envelope.quote.content,
|
|
14744
|
+
sender: envelope.quote.senderId
|
|
14745
|
+
} : void 0,
|
|
14639
14746
|
groupSystemPrompt: envelope.systemPrompt
|
|
14640
14747
|
},
|
|
14641
14748
|
extra: {
|
|
@@ -16761,6 +16868,7 @@ function resolveMediaSource(source) {
|
|
|
16761
16868
|
// src/gateway/lifecycle.ts
|
|
16762
16869
|
init_plugin_logger();
|
|
16763
16870
|
init_outbound_service();
|
|
16871
|
+
init_credential_backup();
|
|
16764
16872
|
|
|
16765
16873
|
// src/features/command-panel.ts
|
|
16766
16874
|
var import_native_command_registry = require("openclaw/plugin-sdk/native-command-registry");
|
|
@@ -17125,7 +17233,7 @@ async function stopAccountGracefully(params) {
|
|
|
17125
17233
|
log5?.error(`[qqbot:${accountId}] gateway stop error: ${err instanceof Error ? err.message : String(err)}`);
|
|
17126
17234
|
}
|
|
17127
17235
|
}
|
|
17128
|
-
unregisterGateway(accountId);
|
|
17236
|
+
unregisterGateway(accountId, gw);
|
|
17129
17237
|
}
|
|
17130
17238
|
async function logoutAndClearCredentials(params) {
|
|
17131
17239
|
const { accountId, cfg } = params;
|