@searchfe/openclaw-baiduapp 0.1.11 → 0.1.12-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/cli.js +405 -0
- package/dist/index.js +60 -10
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +9 -3
- package/src/cli-qrcode.mjs +5 -0
package/cli.js
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {execSync, spawnSync} from 'node:child_process';
|
|
4
|
+
import {createRequire} from 'node:module';
|
|
5
|
+
import readline from 'node:readline';
|
|
6
|
+
import {Writable} from 'node:stream';
|
|
7
|
+
|
|
8
|
+
import {printQRCode} from './src/cli-qrcode.mjs';
|
|
9
|
+
|
|
10
|
+
const _require = createRequire(import.meta.url);
|
|
11
|
+
const CLI_VERSION = _require('./package.json').version;
|
|
12
|
+
|
|
13
|
+
const PLUGIN_SPEC = '@searchfe/openclaw-baiduapp';
|
|
14
|
+
const CHANNEL_ID = 'openclaw-baiduapp';
|
|
15
|
+
const QR_URL = 'https://www.baidu.com';
|
|
16
|
+
|
|
17
|
+
function parseArgs(argv) {
|
|
18
|
+
const args = argv.slice(2);
|
|
19
|
+
let command;
|
|
20
|
+
let ak;
|
|
21
|
+
let sk;
|
|
22
|
+
let agent;
|
|
23
|
+
let yes = false;
|
|
24
|
+
|
|
25
|
+
for (let index = 0; index < args.length; index++) {
|
|
26
|
+
const token = args[index];
|
|
27
|
+
|
|
28
|
+
if (token === '--help' || token === '-h') {
|
|
29
|
+
if (!command) {
|
|
30
|
+
command = token;
|
|
31
|
+
}
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (token === '--yes' || token === '-y') {
|
|
36
|
+
yes = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (token === '--ak') {
|
|
41
|
+
ak = args[index + 1];
|
|
42
|
+
index += 1;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (token.startsWith('--ak=')) {
|
|
47
|
+
ak = token.slice('--ak='.length);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (token === '--sk') {
|
|
52
|
+
sk = args[index + 1];
|
|
53
|
+
index += 1;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (token.startsWith('--sk=')) {
|
|
58
|
+
sk = token.slice('--sk='.length);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (token === '--agent') {
|
|
63
|
+
agent = args[index + 1];
|
|
64
|
+
index += 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (token.startsWith('--agent=')) {
|
|
69
|
+
agent = token.slice('--agent='.length);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!token.startsWith('--') && !command) {
|
|
74
|
+
command = token;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {command, ak, sk, agent, yes};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function prompt(question, {hidden = false} = {}) {
|
|
82
|
+
if (!process.stdin.isTTY) {
|
|
83
|
+
throw new Error('非交互环境:请通过 --ak/--sk 参数传入凭证');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const askOnce = () => new Promise(resolve => {
|
|
87
|
+
if (hidden) {
|
|
88
|
+
process.stdout.write(question);
|
|
89
|
+
const rl = readline.createInterface({
|
|
90
|
+
input: process.stdin,
|
|
91
|
+
output: new Writable({write(_chunk, _enc, cb) { cb(); }}),
|
|
92
|
+
terminal: true,
|
|
93
|
+
});
|
|
94
|
+
rl.on('SIGINT', () => { rl.close(); process.stdout.write('\n'); process.exit(1); });
|
|
95
|
+
rl.question('', answer => {
|
|
96
|
+
rl.close();
|
|
97
|
+
process.stdout.write('\n');
|
|
98
|
+
resolve(String(answer || '').trim());
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const rl = readline.createInterface({
|
|
104
|
+
input: process.stdin,
|
|
105
|
+
output: process.stdout,
|
|
106
|
+
terminal: true,
|
|
107
|
+
});
|
|
108
|
+
rl.on('SIGINT', () => { rl.close(); process.exit(1); });
|
|
109
|
+
rl.question(question, answer => {
|
|
110
|
+
rl.close();
|
|
111
|
+
resolve(String(answer || '').trim());
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return (async () => {
|
|
116
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
117
|
+
const answer = await askOnce();
|
|
118
|
+
if (answer) {
|
|
119
|
+
return answer;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (attempt < 2) {
|
|
123
|
+
error('输入不能为空,请重试');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
throw new Error('输入不能为空,已超过最大重试次数');
|
|
128
|
+
})();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function promptOptional(question) {
|
|
132
|
+
if (!process.stdin.isTTY) {
|
|
133
|
+
return Promise.resolve('');
|
|
134
|
+
}
|
|
135
|
+
return new Promise(resolve => {
|
|
136
|
+
const rl = readline.createInterface({
|
|
137
|
+
input: process.stdin,
|
|
138
|
+
output: process.stdout,
|
|
139
|
+
terminal: true,
|
|
140
|
+
});
|
|
141
|
+
rl.on('SIGINT', () => {
|
|
142
|
+
rl.close();
|
|
143
|
+
process.exit(1);
|
|
144
|
+
});
|
|
145
|
+
rl.question(question, answer => {
|
|
146
|
+
rl.close();
|
|
147
|
+
resolve(String(answer || '').trim());
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function checkAndCreateAgent(agentId, {yes = false} = {}) {
|
|
153
|
+
let agentsList;
|
|
154
|
+
try {
|
|
155
|
+
const agentsJson = run('openclaw', ['agents', 'list', '--json']);
|
|
156
|
+
agentsList = JSON.parse(agentsJson);
|
|
157
|
+
} catch {
|
|
158
|
+
// 解析失败时假设 agent 不存在,继续后续流程
|
|
159
|
+
agentsList = [];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const exists = Array.isArray(agentsList) && agentsList.some(a => a.id === agentId);
|
|
163
|
+
if (exists) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
log(`Agent "${agentId}" 不存在`);
|
|
168
|
+
console.log(` 你可以手动执行以下命令新建:`);
|
|
169
|
+
console.log(` openclaw agents add ${agentId}`);
|
|
170
|
+
console.log();
|
|
171
|
+
|
|
172
|
+
let confirm;
|
|
173
|
+
if (yes) {
|
|
174
|
+
confirm = 'y';
|
|
175
|
+
} else {
|
|
176
|
+
try {
|
|
177
|
+
confirm = await prompt(`是否立即自动新建 agent "${agentId}"?[y/N]: `);
|
|
178
|
+
} catch {
|
|
179
|
+
confirm = '';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (confirm.toLowerCase() !== 'y') {
|
|
184
|
+
error('已取消,请手动新建 agent 后重试');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
log(`正在新建 agent "${agentId}"...`);
|
|
189
|
+
try {
|
|
190
|
+
run('openclaw', ['agents', 'add', agentId], {silent: false});
|
|
191
|
+
} catch {
|
|
192
|
+
error('新建 agent 失败,请手动执行:');
|
|
193
|
+
console.log(` openclaw agents add ${agentId}`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function run(cmd, args = [], {silent = true} = {}) {
|
|
199
|
+
const stdio = silent ? ['pipe', 'pipe', 'pipe'] : 'inherit';
|
|
200
|
+
const result = spawnSync(cmd, args, {encoding: 'utf-8', stdio});
|
|
201
|
+
|
|
202
|
+
if (result.error) {
|
|
203
|
+
const err = new Error(`Command failed: ${cmd}`);
|
|
204
|
+
err.stderr = silent ? String(result.stderr || result.error.message || '') : '';
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (result.status !== 0) {
|
|
209
|
+
const err = new Error(`Command failed with exit code ${result.status}: ${cmd}`);
|
|
210
|
+
err.stderr = silent ? String(result.stderr || '') : '';
|
|
211
|
+
throw err;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return silent ? String(result.stdout || '').trim() : '';
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function which(bin) {
|
|
218
|
+
const cmd = process.platform === 'win32' ? `where ${bin}` : `which ${bin}`;
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
return execSync(cmd, {
|
|
222
|
+
encoding: 'utf-8',
|
|
223
|
+
shell: true,
|
|
224
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
225
|
+
}).trim();
|
|
226
|
+
} catch {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function log(msg) {
|
|
232
|
+
console.log(`\x1b[36m[openclaw-baiduapp]\x1b[0m ${msg}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function error(msg) {
|
|
236
|
+
console.error(`\x1b[31m[openclaw-baiduapp]\x1b[0m ${msg}`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function install() {
|
|
240
|
+
let {ak, sk, agent, yes} = parseArgs(process.argv);
|
|
241
|
+
|
|
242
|
+
if ((!ak || !sk) && !process.stdin.isTTY) {
|
|
243
|
+
error('非交互环境:请通过 --ak/--sk 参数传入凭证');
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (agent !== undefined && !agent.trim()) {
|
|
248
|
+
error('--agent 参数不能为空');
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
let agentId = agent?.trim();
|
|
252
|
+
|
|
253
|
+
if (!which('openclaw')) {
|
|
254
|
+
error('未找到 openclaw,请先安装:');
|
|
255
|
+
console.log(' npm install -g openclaw');
|
|
256
|
+
console.log(' 详见 https://docs.openclaw.ai/install');
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
log('已找到本地安装的 openclaw');
|
|
260
|
+
|
|
261
|
+
log('正在检查插件版本...');
|
|
262
|
+
let installedVersion = null;
|
|
263
|
+
try {
|
|
264
|
+
const infoJson = run('openclaw', ['config', 'get', `plugins.installs.${CHANNEL_ID}`, '--json']);
|
|
265
|
+
const info = JSON.parse(infoJson);
|
|
266
|
+
installedVersion = info?.version ?? null;
|
|
267
|
+
} catch {
|
|
268
|
+
// 未安装或无法读取,后续走安装流程
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (installedVersion === null) {
|
|
272
|
+
log(`插件未安装,正在安装 ${PLUGIN_SPEC}@${CLI_VERSION}...`);
|
|
273
|
+
try {
|
|
274
|
+
run('openclaw', ['plugins', 'install', `${PLUGIN_SPEC}@${CLI_VERSION}`], {silent: false});
|
|
275
|
+
} catch (installErr) {
|
|
276
|
+
error('插件安装失败,请手动执行:');
|
|
277
|
+
console.log(` openclaw plugins install "${PLUGIN_SPEC}@${CLI_VERSION}"`);
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
} else if (installedVersion !== CLI_VERSION) {
|
|
281
|
+
log(`插件版本不一致(已安装: ${installedVersion},当前 CLI: ${CLI_VERSION}),正在更新...`);
|
|
282
|
+
try {
|
|
283
|
+
run('openclaw', ['config', 'set', `plugins.installs.${CHANNEL_ID}.spec`, `${PLUGIN_SPEC}@${CLI_VERSION}`]);
|
|
284
|
+
run('openclaw', ['config', 'unset', `plugins.installs.${CHANNEL_ID}.integrity`]);
|
|
285
|
+
run('openclaw', ['config', 'unset', `plugins.installs.${CHANNEL_ID}.shasum`]);
|
|
286
|
+
run('openclaw', ['plugins', 'update', CHANNEL_ID], {silent: false});
|
|
287
|
+
run('openclaw', ['gateway', 'restart'], {silent: false});
|
|
288
|
+
} catch (updateErr) {
|
|
289
|
+
error('插件更新失败,请手动执行:');
|
|
290
|
+
console.log(` openclaw config set plugins.installs.${CHANNEL_ID}.spec ${PLUGIN_SPEC}@${CLI_VERSION}`);
|
|
291
|
+
console.log(` openclaw config unset plugins.installs.${CHANNEL_ID}.integrity`);
|
|
292
|
+
console.log(` openclaw config unset plugins.installs.${CHANNEL_ID}.shasum`);
|
|
293
|
+
console.log(` openclaw plugins update ${CHANNEL_ID}`);
|
|
294
|
+
console.log(` openclaw gateway restart`);
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
log(`插件版本已是最新(${CLI_VERSION}),跳过更新`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
if (!ak) {
|
|
303
|
+
ak = await prompt('请输入 App Key (appKey): ');
|
|
304
|
+
}
|
|
305
|
+
if (!sk) {
|
|
306
|
+
sk = await prompt('请输入 App Secret (appSecret): ', {hidden: true});
|
|
307
|
+
}
|
|
308
|
+
} catch (promptErr) {
|
|
309
|
+
error(promptErr instanceof Error ? promptErr.message : String(promptErr));
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (!ak.trim() || !sk.trim()) {
|
|
314
|
+
error('appKey 和 appSecret 不能为空');
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 插件已确认安装,再询问/校验 agent
|
|
319
|
+
if (!agentId && process.stdin.isTTY) {
|
|
320
|
+
agentId = await promptOptional('请输入 Agent ID(可选,用于多 agent 配置,直接回车跳过):') || undefined;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (agentId) {
|
|
324
|
+
await checkAndCreateAgent(agentId, {yes});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
log('正在写入配置...');
|
|
328
|
+
const akPath = agentId
|
|
329
|
+
? `channels.${CHANNEL_ID}.accounts.${agentId}.appKey`
|
|
330
|
+
: `channels.${CHANNEL_ID}.appKey`;
|
|
331
|
+
const skPath = agentId
|
|
332
|
+
? `channels.${CHANNEL_ID}.accounts.${agentId}.appSecret`
|
|
333
|
+
: `channels.${CHANNEL_ID}.appSecret`;
|
|
334
|
+
try {
|
|
335
|
+
run('openclaw', ['config', 'set', akPath, ak.trim()]);
|
|
336
|
+
run('openclaw', ['config', 'set', skPath, sk.trim()]);
|
|
337
|
+
} catch {
|
|
338
|
+
error('配置写入失败,请手动执行:');
|
|
339
|
+
console.log(` openclaw config set ${akPath} <your-app-key>`);
|
|
340
|
+
console.log(` openclaw config set ${skPath} <your-app-secret>`);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
if (agentId) {
|
|
344
|
+
log(`配置写入成功(agent: ${agentId})`);
|
|
345
|
+
} else {
|
|
346
|
+
log('配置写入成功');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
log('正在重启 OpenClaw Gateway...');
|
|
350
|
+
try {
|
|
351
|
+
run('openclaw', ['gateway', 'restart'], {silent: false});
|
|
352
|
+
} catch {
|
|
353
|
+
error('重启失败,可手动执行:');
|
|
354
|
+
console.log(' openclaw gateway restart');
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
console.log();
|
|
358
|
+
log('安装完成!扫描下方二维码访问:');
|
|
359
|
+
console.log();
|
|
360
|
+
printQRCode(QR_URL);
|
|
361
|
+
console.log();
|
|
362
|
+
console.log(` ${QR_URL}`);
|
|
363
|
+
console.log();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function help() {
|
|
367
|
+
console.log(`用法: npx @searchfe/openclaw-baiduapp <命令> [选项]
|
|
368
|
+
|
|
369
|
+
命令:
|
|
370
|
+
install 安装百度App插件并配置 AK/SK
|
|
371
|
+
|
|
372
|
+
选项:
|
|
373
|
+
--ak <appKey> App Key(必填,缺省时交互输入)
|
|
374
|
+
--sk <appSecret> App Secret(必填,缺省时交互输入,不回显)
|
|
375
|
+
--agent <agentId> Agent ID(可选,指定后写入 accounts.<agentId> 以支持多 agent 配置)
|
|
376
|
+
交互模式下也会提示输入,直接回车跳过(写入根路径)
|
|
377
|
+
指定后自动校验 agent 是否存在,不存在时提示确认新建
|
|
378
|
+
--yes, -y 自动确认所有交互提示(如 agent 不存在时自动新建,适合 CI/脚本环境)
|
|
379
|
+
--help, -h 显示帮助信息
|
|
380
|
+
|
|
381
|
+
示例:
|
|
382
|
+
npx @searchfe/openclaw-baiduapp install --ak your-key --sk your-secret
|
|
383
|
+
npx @searchfe/openclaw-baiduapp install --agent my-agent --ak your-key --sk your-secret
|
|
384
|
+
npx @searchfe/openclaw-baiduapp install --agent my-agent --ak your-key --sk your-secret --yes
|
|
385
|
+
npx @searchfe/openclaw-baiduapp install`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const {command} = parseArgs(process.argv);
|
|
389
|
+
|
|
390
|
+
switch (command) {
|
|
391
|
+
case 'install':
|
|
392
|
+
await install();
|
|
393
|
+
break;
|
|
394
|
+
case 'help':
|
|
395
|
+
case '--help':
|
|
396
|
+
case '-h':
|
|
397
|
+
help();
|
|
398
|
+
break;
|
|
399
|
+
default:
|
|
400
|
+
if (command) {
|
|
401
|
+
error(`未知命令: ${command}`);
|
|
402
|
+
}
|
|
403
|
+
help();
|
|
404
|
+
process.exit(command ? 1 : 0);
|
|
405
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -28254,7 +28254,18 @@ function parseV2MsgToInbound(inner, outer) {
|
|
|
28254
28254
|
(item) => item && typeof item === "object" && item.type === "file"
|
|
28255
28255
|
);
|
|
28256
28256
|
const textContent = textItem?.data?.text?.content ?? "";
|
|
28257
|
-
const files = fileItems.map((f) =>
|
|
28257
|
+
const files = fileItems.map((f) => {
|
|
28258
|
+
const fileData = f.data?.file;
|
|
28259
|
+
if (!fileData) {
|
|
28260
|
+
return null;
|
|
28261
|
+
}
|
|
28262
|
+
const url = typeof fileData.url === "string" && fileData.url.trim() ? fileData.url.trim() : fileData.fileId;
|
|
28263
|
+
if (!url) {
|
|
28264
|
+
return null;
|
|
28265
|
+
}
|
|
28266
|
+
const fileType = typeof fileData.fileType === "string" && fileData.fileType.trim() ? fileData.fileType.trim() : "file";
|
|
28267
|
+
return { url, fileType };
|
|
28268
|
+
}).filter((f) => f !== null);
|
|
28258
28269
|
return {
|
|
28259
28270
|
msgtype: "text",
|
|
28260
28271
|
msgid: typeof outer.msgid === "string" ? outer.msgid : void 0,
|
|
@@ -28495,6 +28506,7 @@ async function handleBaiduAppWebhookRequest(req, res) {
|
|
|
28495
28506
|
// src/poller.ts
|
|
28496
28507
|
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
28497
28508
|
var DEFAULT_POLL_REQUEST_TIMEOUT_MS = 1e4;
|
|
28509
|
+
var pollerLogger = createLogger("openclaw-baiduapp:poller");
|
|
28498
28510
|
var accountPollers = /* @__PURE__ */ new Map();
|
|
28499
28511
|
function buildPollingTextInboundMessage(content) {
|
|
28500
28512
|
return {
|
|
@@ -28509,9 +28521,17 @@ function parseTextAndFilesFromList(list) {
|
|
|
28509
28521
|
const fileItems = list.filter((entry) => entry.type === "file");
|
|
28510
28522
|
const content = textItem?.type === "text" ? textItem.data.text.content : void 0;
|
|
28511
28523
|
const files = fileItems.map((file) => {
|
|
28512
|
-
|
|
28513
|
-
|
|
28514
|
-
|
|
28524
|
+
if (file.type !== "file") {
|
|
28525
|
+
return null;
|
|
28526
|
+
}
|
|
28527
|
+
const fileData = file.data.file;
|
|
28528
|
+
const url = typeof fileData.url === "string" && fileData.url.trim() ? fileData.url.trim() : fileData.fileId;
|
|
28529
|
+
if (!url || !url.trim()) {
|
|
28530
|
+
return null;
|
|
28531
|
+
}
|
|
28532
|
+
const fileType = typeof fileData.fileType === "string" && fileData.fileType.trim() ? fileData.fileType.trim() : "file";
|
|
28533
|
+
return { url, fileType };
|
|
28534
|
+
}).filter((file) => file !== null);
|
|
28515
28535
|
return { content, files };
|
|
28516
28536
|
}
|
|
28517
28537
|
async function dispatchPendingPollingMessages(data, target) {
|
|
@@ -28522,8 +28542,10 @@ async function dispatchPendingPollingMessages(data, target) {
|
|
|
28522
28542
|
const list = Array.isArray(item.list) ? item.list : [];
|
|
28523
28543
|
const { content, files } = parseTextAndFilesFromList(list);
|
|
28524
28544
|
if (typeof content !== "string" && files.length === 0) {
|
|
28545
|
+
pollerLogger.debug(`dispatch skip: msgId=${item.msgId ?? "?"} agentId=${item.agentId ?? "none"} reason=no-content`);
|
|
28525
28546
|
continue;
|
|
28526
28547
|
}
|
|
28548
|
+
pollerLogger.info(`dispatch msg: msgId=${item.msgId ?? "?"} agentId=${item.agentId ?? "none"} files=${files.length} hasText=${typeof content === "string"}`);
|
|
28527
28549
|
await processBaiduAppInboundMessage({
|
|
28528
28550
|
target,
|
|
28529
28551
|
msg: {
|
|
@@ -28608,6 +28630,7 @@ async function pollBaiduAppChatlistOnce(account, loggerOptions, requestOptions)
|
|
|
28608
28630
|
version: PLUGIN_VERSION
|
|
28609
28631
|
};
|
|
28610
28632
|
const body = JSON.stringify(payload);
|
|
28633
|
+
logger3.debug(`poll request: accountId=${account.accountId} url=${endpoint} sessionId=${payload.sessionId}`);
|
|
28611
28634
|
const requestSignal = createAbortSignalController({
|
|
28612
28635
|
signal: requestOptions?.signal,
|
|
28613
28636
|
timeoutMs: requestOptions?.timeoutMs
|
|
@@ -28626,6 +28649,7 @@ async function pollBaiduAppChatlistOnce(account, loggerOptions, requestOptions)
|
|
|
28626
28649
|
} catch (error) {
|
|
28627
28650
|
requestSignal.cleanup();
|
|
28628
28651
|
if (requestSignal.didTimeout()) {
|
|
28652
|
+
logger3.warn(`poll timeout: accountId=${account.accountId} timeoutMs=${requestOptions?.timeoutMs}`);
|
|
28629
28653
|
return buildPollResult({
|
|
28630
28654
|
ok: false,
|
|
28631
28655
|
error: {
|
|
@@ -28635,6 +28659,7 @@ async function pollBaiduAppChatlistOnce(account, loggerOptions, requestOptions)
|
|
|
28635
28659
|
});
|
|
28636
28660
|
}
|
|
28637
28661
|
if (isAbortError2(error)) {
|
|
28662
|
+
logger3.debug(`poll aborted: accountId=${account.accountId}`);
|
|
28638
28663
|
return buildPollResult({
|
|
28639
28664
|
ok: false,
|
|
28640
28665
|
error: {
|
|
@@ -28643,17 +28668,20 @@ async function pollBaiduAppChatlistOnce(account, loggerOptions, requestOptions)
|
|
|
28643
28668
|
}
|
|
28644
28669
|
});
|
|
28645
28670
|
}
|
|
28671
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
28672
|
+
logger3.error(`poll request failed: accountId=${account.accountId} error=${errMsg}`);
|
|
28646
28673
|
return buildPollResult({
|
|
28647
28674
|
ok: false,
|
|
28648
28675
|
error: {
|
|
28649
28676
|
kind: "request-failed",
|
|
28650
|
-
message:
|
|
28677
|
+
message: errMsg
|
|
28651
28678
|
}
|
|
28652
28679
|
});
|
|
28653
28680
|
}
|
|
28654
28681
|
const responseText = await response.text();
|
|
28655
28682
|
requestSignal.cleanup();
|
|
28656
28683
|
if (!responseText) {
|
|
28684
|
+
logger3.warn(`poll empty response: accountId=${account.accountId} status=${response.status}`);
|
|
28657
28685
|
return buildPollResult({
|
|
28658
28686
|
ok: false,
|
|
28659
28687
|
error: {
|
|
@@ -28666,6 +28694,7 @@ async function pollBaiduAppChatlistOnce(account, loggerOptions, requestOptions)
|
|
|
28666
28694
|
try {
|
|
28667
28695
|
parsed = JSON.parse(responseText);
|
|
28668
28696
|
} catch {
|
|
28697
|
+
logger3.warn(`poll invalid json: accountId=${account.accountId} status=${response.status}`);
|
|
28669
28698
|
return buildPollResult({
|
|
28670
28699
|
ok: false,
|
|
28671
28700
|
error: {
|
|
@@ -28674,10 +28703,12 @@ async function pollBaiduAppChatlistOnce(account, loggerOptions, requestOptions)
|
|
|
28674
28703
|
}
|
|
28675
28704
|
});
|
|
28676
28705
|
}
|
|
28706
|
+
const msgList = Array.isArray(parsed.data?.msgList) ? parsed.data.msgList : [];
|
|
28677
28707
|
if (parsed.code !== 0) {
|
|
28678
|
-
logger3.debug(`
|
|
28708
|
+
logger3.debug(`poll non-zero code: accountId=${account.accountId} code=${String(parsed.code)} message=${parsed.message}`);
|
|
28709
|
+
} else {
|
|
28710
|
+
logger3.debug(`poll ok: accountId=${account.accountId} status=${response.status} msgCount=${msgList.length}`);
|
|
28679
28711
|
}
|
|
28680
|
-
const msgList = Array.isArray(parsed.data?.msgList) ? parsed.data.msgList : [];
|
|
28681
28712
|
return buildPollResult({
|
|
28682
28713
|
ok: true,
|
|
28683
28714
|
data: msgList
|
|
@@ -28687,6 +28718,7 @@ function scheduleNextPoll(account, state) {
|
|
|
28687
28718
|
if (state.stopped) {
|
|
28688
28719
|
return;
|
|
28689
28720
|
}
|
|
28721
|
+
pollerLogger.debug(`schedule next poll: accountId=${account.accountId} intervalMs=${state.intervalMs}`);
|
|
28690
28722
|
state.timer = setTimeout(() => {
|
|
28691
28723
|
void runPollCycle(account, state);
|
|
28692
28724
|
}, state.intervalMs);
|
|
@@ -28695,6 +28727,9 @@ async function runPollCycle(account, state) {
|
|
|
28695
28727
|
if (state.stopped || state.pending) {
|
|
28696
28728
|
return;
|
|
28697
28729
|
}
|
|
28730
|
+
state.cycleCount += 1;
|
|
28731
|
+
const cycle = state.cycleCount;
|
|
28732
|
+
pollerLogger.debug(`poll cycle #${cycle} start: accountId=${account.accountId}`);
|
|
28698
28733
|
const controller = new AbortController();
|
|
28699
28734
|
state.activeController = controller;
|
|
28700
28735
|
const pending = (async () => {
|
|
@@ -28704,9 +28739,18 @@ async function runPollCycle(account, state) {
|
|
|
28704
28739
|
fetchImpl: state.fetchImpl,
|
|
28705
28740
|
timeoutMs: state.requestTimeoutMs
|
|
28706
28741
|
});
|
|
28742
|
+
if (!result2.ok && result2.error) {
|
|
28743
|
+
if (result2.error.kind !== "aborted") {
|
|
28744
|
+
pollerLogger.warn(`poll cycle #${cycle} error: accountId=${account.accountId} kind=${result2.error.kind} msg=${result2.error.message}`);
|
|
28745
|
+
}
|
|
28746
|
+
} else if (result2.data.length > 0) {
|
|
28747
|
+
pollerLogger.info(`poll cycle #${cycle} msgs: accountId=${account.accountId} count=${result2.data.length}`);
|
|
28748
|
+
}
|
|
28707
28749
|
await dispatchPendingPollingMessages(result2.data, state.dispatchTarget);
|
|
28708
28750
|
} catch (error) {
|
|
28709
28751
|
if (!(state.stopped && isAbortError2(error))) {
|
|
28752
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
28753
|
+
pollerLogger.error(`poll cycle #${cycle} unhandled error: accountId=${account.accountId} error=${errMsg}`);
|
|
28710
28754
|
state.onError?.(error);
|
|
28711
28755
|
}
|
|
28712
28756
|
} finally {
|
|
@@ -28724,18 +28768,23 @@ async function runPollCycle(account, state) {
|
|
|
28724
28768
|
}
|
|
28725
28769
|
function startAccountPolling(params) {
|
|
28726
28770
|
if (accountPollers.has(params.account.accountId)) {
|
|
28771
|
+
pollerLogger.debug(`polling already running: accountId=${params.account.accountId}, skip`);
|
|
28727
28772
|
return;
|
|
28728
28773
|
}
|
|
28774
|
+
const intervalMs = params.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
28775
|
+
const requestTimeoutMs = params.requestTimeoutMs ?? DEFAULT_POLL_REQUEST_TIMEOUT_MS;
|
|
28776
|
+
pollerLogger.info(`start polling: accountId=${params.account.accountId} intervalMs=${intervalMs} timeoutMs=${requestTimeoutMs} apiBase=${params.account.apiBase}`);
|
|
28729
28777
|
const state = {
|
|
28730
28778
|
stopped: false,
|
|
28731
28779
|
timer: null,
|
|
28732
28780
|
activeController: null,
|
|
28733
28781
|
pending: null,
|
|
28734
|
-
intervalMs
|
|
28735
|
-
requestTimeoutMs
|
|
28782
|
+
intervalMs,
|
|
28783
|
+
requestTimeoutMs,
|
|
28736
28784
|
fetchImpl: params.fetchImpl,
|
|
28737
28785
|
onError: params.onError,
|
|
28738
|
-
dispatchTarget: params.dispatchTarget
|
|
28786
|
+
dispatchTarget: params.dispatchTarget,
|
|
28787
|
+
cycleCount: 0
|
|
28739
28788
|
};
|
|
28740
28789
|
accountPollers.set(params.account.accountId, state);
|
|
28741
28790
|
void runPollCycle(params.account, state);
|
|
@@ -28745,6 +28794,7 @@ function stopAccountPolling(accountId) {
|
|
|
28745
28794
|
if (!state) {
|
|
28746
28795
|
return;
|
|
28747
28796
|
}
|
|
28797
|
+
pollerLogger.info(`stop polling: accountId=${accountId} totalCycles=${state.cycleCount}`);
|
|
28748
28798
|
state.stopped = true;
|
|
28749
28799
|
if (state.timer) {
|
|
28750
28800
|
clearTimeout(state.timer);
|