evolclaw 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -27
- package/data/evolclaw.sample.json +6 -3
- package/dist/agents/claude-runner.js +125 -52
- package/dist/agents/codex-runner.js +10 -5
- package/dist/agents/gemini-runner.js +425 -0
- package/dist/channels/aun.js +247 -84
- package/dist/channels/feishu.js +556 -96
- package/dist/channels/wechat.js +98 -74
- package/dist/cli.js +132 -50
- package/dist/config.js +185 -31
- package/dist/core/channel-loader.js +11 -4
- package/dist/core/command-handler.js +750 -209
- package/dist/core/interaction-router.js +68 -0
- package/dist/core/message/message-bridge.js +216 -0
- package/dist/core/{message-processor.js → message/message-processor.js} +386 -105
- package/dist/core/{message-queue.js → message/message-queue.js} +1 -1
- package/dist/{utils → core/message}/stream-debouncer.js +1 -1
- package/dist/{utils → core/message}/stream-flusher.js +73 -13
- package/dist/core/permission.js +212 -11
- package/dist/core/{adapters → session/adapters}/claude-session-file-adapter.js +2 -2
- package/dist/core/{adapters → session/adapters}/codex-session-file-adapter.js +117 -52
- package/dist/core/session/adapters/gemini-session-file-adapter.js +177 -0
- package/dist/{utils → core/session}/session-file-health.js +1 -1
- package/dist/core/{session-manager.js → session/session-manager.js} +57 -11
- package/dist/index.js +138 -54
- package/dist/{core/ipc-server.js → ipc.js} +36 -1
- package/dist/types.js +3 -0
- package/dist/utils/cross-platform.js +38 -1
- package/dist/utils/error-utils.js +130 -5
- package/dist/utils/init-channel.js +649 -0
- package/dist/utils/init.js +55 -150
- package/dist/utils/logger.js +8 -3
- package/dist/utils/media-cache.js +207 -0
- package/dist/{core → utils}/stats-collector.js +16 -0
- package/package.json +3 -3
- package/dist/core/message-bridge.js +0 -187
- package/dist/utils/init-feishu.js +0 -263
- package/dist/utils/init-wechat.js +0 -172
- package/dist/utils/ipc-client.js +0 -36
- package/dist/utils/permission-utils.js +0 -71
- /package/dist/{utils → core/message}/message-cache.js +0 -0
- /package/dist/{utils → core/message}/stream-idle-monitor.js +0 -0
- /package/dist/core/{session-file-adapter.js → session/session-file-adapter.js} +0 -0
package/dist/channels/aun.js
CHANGED
|
@@ -1,10 +1,74 @@
|
|
|
1
|
-
import { AUNClient } from '@aun
|
|
2
|
-
import
|
|
1
|
+
import { AUNClient } from '@eleans/aun-core-node';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { logger, localTimestamp } from '../utils/logger.js';
|
|
5
|
+
import { normalizeChannelInstances } from '../config.js';
|
|
6
|
+
import { resolvePaths } from '../paths.js';
|
|
3
7
|
export class AUNChannel {
|
|
4
8
|
config;
|
|
5
9
|
client = null;
|
|
6
10
|
messageHandler;
|
|
7
11
|
connected = false;
|
|
12
|
+
traceStream = null;
|
|
13
|
+
trace(dir, event, data) {
|
|
14
|
+
if (!this.traceStream)
|
|
15
|
+
return;
|
|
16
|
+
const line = JSON.stringify({ ts: localTimestamp(), dir, event, data });
|
|
17
|
+
this.traceStream.write(line + '\n');
|
|
18
|
+
}
|
|
19
|
+
getShortAid(aid) {
|
|
20
|
+
if (!aid)
|
|
21
|
+
return undefined;
|
|
22
|
+
const trimmed = aid.trim();
|
|
23
|
+
if (!trimmed)
|
|
24
|
+
return undefined;
|
|
25
|
+
return trimmed.split('.')[0] || trimmed;
|
|
26
|
+
}
|
|
27
|
+
extractTextPayload(payload) {
|
|
28
|
+
if (typeof payload === 'string')
|
|
29
|
+
return payload;
|
|
30
|
+
if (payload && typeof payload === 'object') {
|
|
31
|
+
const text = payload.text;
|
|
32
|
+
if (typeof text === 'string')
|
|
33
|
+
return text;
|
|
34
|
+
return JSON.stringify(payload);
|
|
35
|
+
}
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
hasExplicitMention(text, target) {
|
|
39
|
+
const escaped = target.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
40
|
+
return new RegExp(`(^|\\s)@${escaped}(?=$|\\s|[.,!?;:,。!?;:]|[\\u4e00-\\u9fff])`).test(text);
|
|
41
|
+
}
|
|
42
|
+
stripTriggerMentions(text, selfAid) {
|
|
43
|
+
let result = text;
|
|
44
|
+
if (selfAid) {
|
|
45
|
+
const escapedAid = selfAid.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
46
|
+
result = result.replace(new RegExp(`(^|\\s)@${escapedAid}(?=$|\\s|[.,!?;:,。!?;:]|[\\u4e00-\\u9fff])`, 'g'), '$1');
|
|
47
|
+
}
|
|
48
|
+
result = result.replace(/(^|\s)@all(?=$|\s|[.,!?;:,。!?;:]|[\u4e00-\u9fff])/gi, '$1');
|
|
49
|
+
return result.replace(/[ \t]+/g, ' ').trim();
|
|
50
|
+
}
|
|
51
|
+
buildGroupReplyContext(taskId, senderAid, text) {
|
|
52
|
+
const replyContext = {};
|
|
53
|
+
if (taskId)
|
|
54
|
+
replyContext.threadId = taskId;
|
|
55
|
+
if (this.hasExplicitMention(text, 'all')) {
|
|
56
|
+
replyContext.mentionUserIds = ['all'];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
replyContext.mentionUserIds = [senderAid];
|
|
60
|
+
}
|
|
61
|
+
return replyContext;
|
|
62
|
+
}
|
|
63
|
+
acknowledgeImmediately(messageId, seq) {
|
|
64
|
+
if (seq != null && this.client) {
|
|
65
|
+
this.client.call('message.ack', { seq }).catch(e => {
|
|
66
|
+
logger.debug(`[AUN] Immediate ack failed: ${e}`);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (messageId)
|
|
70
|
+
this.messageSeqMap.delete(messageId);
|
|
71
|
+
}
|
|
8
72
|
_aid;
|
|
9
73
|
seenMessages = new Map();
|
|
10
74
|
messageSeqMap = new Map(); // messageId → seq (for ack)
|
|
@@ -17,6 +81,11 @@ export class AUNChannel {
|
|
|
17
81
|
onChannelDown;
|
|
18
82
|
constructor(config) {
|
|
19
83
|
this.config = config;
|
|
84
|
+
if (config.aunTrace) {
|
|
85
|
+
const logPath = path.join(resolvePaths().logs, 'aun-trace.log');
|
|
86
|
+
this.traceStream = fs.createWriteStream(logPath, { flags: 'a' });
|
|
87
|
+
logger.info(`[AUN] Trace logging enabled: ${logPath}`);
|
|
88
|
+
}
|
|
20
89
|
}
|
|
21
90
|
async connect() {
|
|
22
91
|
this.intentionalDisconnect = false;
|
|
@@ -53,21 +122,39 @@ export class AUNChannel {
|
|
|
53
122
|
logger.info(`[AUN] Initializing: aid=${aidName}, gateway=${gateway}, aun_path=${aunPath}`);
|
|
54
123
|
// Create client with FileSecretStore (AES-256-GCM)
|
|
55
124
|
// 不传 encryption_seed 时,SDK 自动从 {aun_path}/.seed 文件派生密钥(与 aun_cli.py 对齐)
|
|
125
|
+
const rootCaPath = `${aunPath}/CA/root/root.crt`;
|
|
56
126
|
this.client = new AUNClient({
|
|
57
127
|
aun_path: aunPath,
|
|
128
|
+
root_ca_path: rootCaPath,
|
|
58
129
|
...(encryptionSeed && { encryption_seed: encryptionSeed }),
|
|
59
130
|
});
|
|
60
131
|
// Set gateway URL (internal property, same as Python SDK)
|
|
61
132
|
this.client._gatewayUrl = gateway;
|
|
62
133
|
// Register event handlers before connecting
|
|
63
|
-
this.client.on('message.received', (data) =>
|
|
64
|
-
|
|
65
|
-
|
|
134
|
+
this.client.on('message.received', (data) => {
|
|
135
|
+
this.trace('IN', 'message.received', data);
|
|
136
|
+
const kind = (data && typeof data === 'object') ? data.kind ?? '' : '';
|
|
137
|
+
const keys = (data && typeof data === 'object') ? Object.keys(data).join(',') : typeof data;
|
|
138
|
+
logger.info(`[AUN][DIAG] message.received: kind=${kind} keys=${keys}`);
|
|
139
|
+
this.handleIncomingPrivateMessage(data);
|
|
140
|
+
});
|
|
141
|
+
this.client.on('group.message_created', (data) => {
|
|
142
|
+
this.trace('IN', 'group.message_created', data);
|
|
143
|
+
const gid = (data && typeof data === 'object') ? data.group_id ?? '' : '';
|
|
144
|
+
const sender = (data && typeof data === 'object') ? data.sender_aid ?? '' : '';
|
|
145
|
+
logger.info(`[AUN][DIAG] group.message_created: group_id=${gid} sender=${sender}`);
|
|
146
|
+
this.handleIncomingGroupMessage(data);
|
|
147
|
+
});
|
|
148
|
+
this.client.on('connection.state', (data) => {
|
|
149
|
+
this.trace('IN', 'connection.state', data);
|
|
150
|
+
this.handleConnectionState(data);
|
|
151
|
+
});
|
|
66
152
|
// Authenticate
|
|
67
153
|
let accessToken;
|
|
68
154
|
try {
|
|
69
155
|
logger.info(`[AUN] Authenticating as ${aidName}...`);
|
|
70
156
|
const auth = await this.client.auth.authenticate(aidName ? { aid: aidName } : undefined);
|
|
157
|
+
this.trace('IN', 'auth.result', { aid: auth.aid, gateway: auth.gateway, hasToken: !!auth.access_token });
|
|
71
158
|
accessToken = auth.access_token;
|
|
72
159
|
const resolvedGateway = auth.gateway || gateway;
|
|
73
160
|
this.client._gatewayUrl = resolvedGateway;
|
|
@@ -107,7 +194,7 @@ export class AUNChannel {
|
|
|
107
194
|
const msg = data;
|
|
108
195
|
const fromAid = msg.from ?? '';
|
|
109
196
|
const payload = msg.payload ?? '';
|
|
110
|
-
const text =
|
|
197
|
+
const text = this.extractTextPayload(payload);
|
|
111
198
|
const taskId = msg.task_id;
|
|
112
199
|
const messageId = msg.message_id ?? '';
|
|
113
200
|
const seq = msg.seq;
|
|
@@ -134,24 +221,42 @@ export class AUNChannel {
|
|
|
134
221
|
const groupId = msg.group_id ?? '';
|
|
135
222
|
const senderAid = msg.sender_aid ?? msg.from ?? '';
|
|
136
223
|
const payload = msg.payload ?? '';
|
|
137
|
-
const text =
|
|
224
|
+
const text = this.extractTextPayload(payload);
|
|
138
225
|
const taskId = msg.task_id;
|
|
139
226
|
const messageId = msg.message_id ?? '';
|
|
140
227
|
const seq = msg.seq;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
228
|
+
logger.info(`[AUN][DIAG-GRP] full_msg=${JSON.stringify(msg).substring(0, 500)}`);
|
|
229
|
+
if (!groupId || !senderAid) {
|
|
230
|
+
this.acknowledgeImmediately(messageId, seq);
|
|
231
|
+
return;
|
|
145
232
|
}
|
|
233
|
+
if (this._aid && senderAid === this._aid) {
|
|
234
|
+
this.acknowledgeImmediately(messageId, seq);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const mentionedSelf = this._aid ? this.hasExplicitMention(text, this._aid) : false;
|
|
238
|
+
const mentionedAll = this.hasExplicitMention(text, 'all');
|
|
239
|
+
if (!mentionedSelf && !mentionedAll) {
|
|
240
|
+
this.acknowledgeImmediately(messageId, seq);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const strippedText = this.stripTriggerMentions(text, this._aid);
|
|
244
|
+
if (!strippedText) {
|
|
245
|
+
this.acknowledgeImmediately(messageId, seq);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const mentions = mentionedAll ? ['all'] : (this._aid ? [this._aid] : []);
|
|
146
249
|
this.dispatchMessage({
|
|
147
250
|
channelId: groupId,
|
|
148
251
|
userId: senderAid,
|
|
149
|
-
|
|
252
|
+
peerName: this.getShortAid(senderAid),
|
|
253
|
+
text: strippedText,
|
|
150
254
|
chatType: 'group',
|
|
151
255
|
messageId,
|
|
152
256
|
seq,
|
|
153
257
|
taskId,
|
|
154
258
|
mentions,
|
|
259
|
+
replyContext: this.buildGroupReplyContext(taskId, senderAid, text),
|
|
155
260
|
});
|
|
156
261
|
}
|
|
157
262
|
dispatchMessage(event) {
|
|
@@ -169,8 +274,10 @@ export class AUNChannel {
|
|
|
169
274
|
if (!this.messageHandler)
|
|
170
275
|
return;
|
|
171
276
|
const mentionObjects = event.mentions?.map(aid => ({ userId: aid }));
|
|
172
|
-
|
|
173
|
-
|
|
277
|
+
// Use caller-supplied replyContext (group path builds mentionUserIds);
|
|
278
|
+
// fall back to simple threadId-only context for private messages
|
|
279
|
+
let replyContext = event.replyContext;
|
|
280
|
+
if (!replyContext && event.taskId) {
|
|
174
281
|
replyContext = { threadId: event.taskId };
|
|
175
282
|
}
|
|
176
283
|
this.messageHandler({
|
|
@@ -178,6 +285,7 @@ export class AUNChannel {
|
|
|
178
285
|
content: event.text || '',
|
|
179
286
|
chatType: event.chatType,
|
|
180
287
|
peerId: event.userId || event.channelId || '',
|
|
288
|
+
peerName: event.peerName,
|
|
181
289
|
messageId: event.messageId,
|
|
182
290
|
threadId: event.taskId,
|
|
183
291
|
mentions: mentionObjects,
|
|
@@ -230,20 +338,30 @@ export class AUNChannel {
|
|
|
230
338
|
finalText = '最终回复\n' + text;
|
|
231
339
|
}
|
|
232
340
|
this.sentCount.set(channelId, (this.sentCount.get(channelId) || 0) + 1);
|
|
233
|
-
|
|
341
|
+
// Render outbound mentions for group sends
|
|
342
|
+
if (channelId.startsWith('grp_') && context?.mentionUserIds?.length) {
|
|
343
|
+
const mentionPrefix = context.mentionUserIds.includes('all')
|
|
344
|
+
? '@all '
|
|
345
|
+
: context.mentionUserIds.map(id => `@${id}`).join(' ') + ' ';
|
|
346
|
+
finalText = mentionPrefix + finalText;
|
|
347
|
+
}
|
|
348
|
+
const params = { payload: { text: finalText }, encrypt: true };
|
|
234
349
|
if (context?.threadId)
|
|
235
350
|
params.task_id = context.threadId;
|
|
236
351
|
try {
|
|
237
352
|
if (channelId.startsWith('grp_')) {
|
|
238
353
|
params.group_id = channelId;
|
|
354
|
+
this.trace('OUT', 'group.send', params);
|
|
239
355
|
await this.client.call('group.send', params);
|
|
240
356
|
}
|
|
241
357
|
else {
|
|
242
358
|
params.to = channelId;
|
|
359
|
+
this.trace('OUT', 'message.send', params);
|
|
243
360
|
await this.client.call('message.send', params);
|
|
244
361
|
}
|
|
245
362
|
}
|
|
246
363
|
catch (e) {
|
|
364
|
+
this.trace('OUT', 'send.error', { channelId, error: String(e) });
|
|
247
365
|
logger.error(`[AUN] Send failed to ${channelId}: ${e}`);
|
|
248
366
|
}
|
|
249
367
|
}
|
|
@@ -261,29 +379,52 @@ export class AUNChannel {
|
|
|
261
379
|
this.sentCount.delete(channelId); // 新任务开始,重置计数
|
|
262
380
|
if (!this.client || !this.connected)
|
|
263
381
|
return;
|
|
264
|
-
const payload =
|
|
382
|
+
const payload = {
|
|
265
383
|
type: 'processing',
|
|
266
384
|
status,
|
|
267
385
|
sessionId,
|
|
268
386
|
timestamp: Math.floor(Date.now() / 1000),
|
|
269
|
-
}
|
|
387
|
+
};
|
|
270
388
|
const params = {
|
|
271
|
-
|
|
389
|
+
payload,
|
|
272
390
|
encrypt: true, persist: false,
|
|
273
391
|
};
|
|
274
392
|
if (context?.threadId)
|
|
275
393
|
params.task_id = context.threadId;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
394
|
+
if (channelId.startsWith('grp_')) {
|
|
395
|
+
params.group_id = channelId;
|
|
396
|
+
this.trace('OUT', 'group.send.status', params);
|
|
397
|
+
this.client.call('group.send', params).catch(e => {
|
|
398
|
+
logger.debug(`[AUN] Processing status failed: ${e}`);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
params.to = channelId;
|
|
403
|
+
this.trace('OUT', 'message.send.status', params);
|
|
404
|
+
this.client.call('message.send', params).catch(e => {
|
|
405
|
+
logger.debug(`[AUN] Processing status failed: ${e}`);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
279
408
|
}
|
|
280
409
|
sendCustomPayload(channelId, payload) {
|
|
281
410
|
if (!this.client || !this.connected)
|
|
282
411
|
return;
|
|
283
|
-
|
|
284
|
-
|
|
412
|
+
// SDK 0.3.0 E2EE requires payload to be an object
|
|
413
|
+
let payloadObj;
|
|
414
|
+
try {
|
|
415
|
+
const parsed = JSON.parse(payload);
|
|
416
|
+
payloadObj = (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
|
|
417
|
+
? parsed : { text: payload };
|
|
418
|
+
}
|
|
419
|
+
catch {
|
|
420
|
+
payloadObj = { text: payload };
|
|
421
|
+
}
|
|
422
|
+
const sendParams = {
|
|
423
|
+
to: channelId, payload: payloadObj,
|
|
285
424
|
encrypt: true, persist: false,
|
|
286
|
-
}
|
|
425
|
+
};
|
|
426
|
+
this.trace('OUT', 'message.send.custom', sendParams);
|
|
427
|
+
this.client.call('message.send', sendParams).catch(e => {
|
|
287
428
|
logger.debug(`[AUN] Custom payload failed: ${e}`);
|
|
288
429
|
});
|
|
289
430
|
}
|
|
@@ -301,6 +442,10 @@ export class AUNChannel {
|
|
|
301
442
|
this.client = null;
|
|
302
443
|
}
|
|
303
444
|
this.connected = false;
|
|
445
|
+
if (this.traceStream) {
|
|
446
|
+
this.traceStream.end();
|
|
447
|
+
this.traceStream = null;
|
|
448
|
+
}
|
|
304
449
|
logger.info('[AUN] Disconnected');
|
|
305
450
|
}
|
|
306
451
|
// ── TS-layer reconnect (fallback when SDK auto_reconnect exhausted) ──
|
|
@@ -367,69 +512,87 @@ export class AUNChannel {
|
|
|
367
512
|
export class AUNChannelPlugin {
|
|
368
513
|
name = 'aun';
|
|
369
514
|
isEnabled(config) {
|
|
370
|
-
|
|
515
|
+
const raw = config.channels?.aun;
|
|
516
|
+
if (!raw)
|
|
517
|
+
return false;
|
|
518
|
+
if (Array.isArray(raw)) {
|
|
519
|
+
return raw.some(inst => inst.enabled !== false && !!inst.aid);
|
|
520
|
+
}
|
|
521
|
+
return raw.enabled !== false && !!raw.aid;
|
|
522
|
+
}
|
|
523
|
+
async createChannels(config) {
|
|
524
|
+
const instances = normalizeChannelInstances(config.channels?.aun, 'aun');
|
|
525
|
+
const result = [];
|
|
526
|
+
for (const inst of instances) {
|
|
527
|
+
if (inst.enabled === false || !inst.aid)
|
|
528
|
+
continue;
|
|
529
|
+
const channel = new AUNChannel({
|
|
530
|
+
aid: inst.aid,
|
|
531
|
+
keystorePath: inst.keystorePath,
|
|
532
|
+
gatewayPort: inst.gatewayPort,
|
|
533
|
+
gatewayUrl: inst.gatewayUrl,
|
|
534
|
+
accessToken: inst.accessToken,
|
|
535
|
+
flushDelay: inst.flushDelay,
|
|
536
|
+
encryptionSeed: inst.encryptionSeed,
|
|
537
|
+
aunTrace: config.debug?.aunTrace,
|
|
538
|
+
});
|
|
539
|
+
const adapter = {
|
|
540
|
+
channelName: inst.name,
|
|
541
|
+
sendText: (id, text, context) => channel.sendMessage(id, text, context),
|
|
542
|
+
acknowledge: (messageId) => { channel.acknowledge(messageId); return Promise.resolve(); },
|
|
543
|
+
sendProcessingStatus: (id, status, sessionId, context) => channel.sendProcessingStatus(id, status, sessionId, context),
|
|
544
|
+
sendCustomPayload: (id, payload) => channel.sendCustomPayload(id, payload),
|
|
545
|
+
};
|
|
546
|
+
const policy = {
|
|
547
|
+
canSwitchProject: (chatType, identity) => identity === 'owner',
|
|
548
|
+
canListProjects: (chatType, identity) => identity === 'owner',
|
|
549
|
+
canCreateSession: (chatType, identity) => true,
|
|
550
|
+
canDeleteSession: (chatType, identity) => true,
|
|
551
|
+
canImportCliSession: (chatType, identity) => identity === 'owner',
|
|
552
|
+
messagePrefix: () => '',
|
|
553
|
+
showMiddleResult: (chatType, identity) => {
|
|
554
|
+
const mode = inst.showActivities ?? config.showActivities ?? 'all';
|
|
555
|
+
if (mode === 'none')
|
|
556
|
+
return false;
|
|
557
|
+
if (mode === 'dm-only')
|
|
558
|
+
return chatType === 'private';
|
|
559
|
+
if (mode === 'owner-dm-only')
|
|
560
|
+
return chatType === 'private' && identity === 'owner';
|
|
561
|
+
return true;
|
|
562
|
+
},
|
|
563
|
+
showIdleMonitor: (chatType, identity) => {
|
|
564
|
+
const mode = inst.showActivities ?? config.showActivities ?? 'all';
|
|
565
|
+
if (mode === 'none')
|
|
566
|
+
return false;
|
|
567
|
+
if (mode === 'dm-only')
|
|
568
|
+
return chatType === 'private';
|
|
569
|
+
if (mode === 'owner-dm-only')
|
|
570
|
+
return chatType === 'private' && identity === 'owner';
|
|
571
|
+
return true;
|
|
572
|
+
},
|
|
573
|
+
accumulateErrors: (chatType, identity) => true,
|
|
574
|
+
};
|
|
575
|
+
const options = {
|
|
576
|
+
flushDelay: inst.flushDelay ?? 3,
|
|
577
|
+
fileMarkerPattern: /\[SEND_FILE:(?:(\w+):)?([^\]]+)\]/g,
|
|
578
|
+
};
|
|
579
|
+
result.push({
|
|
580
|
+
channelType: 'aun',
|
|
581
|
+
adapter,
|
|
582
|
+
channel,
|
|
583
|
+
policy,
|
|
584
|
+
options,
|
|
585
|
+
connect: () => channel.connect(),
|
|
586
|
+
disconnect: () => channel.disconnect(),
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
return result;
|
|
371
590
|
}
|
|
372
591
|
async createChannel(config) {
|
|
373
|
-
const
|
|
374
|
-
if (
|
|
592
|
+
const instances = await this.createChannels(config);
|
|
593
|
+
if (instances.length === 0) {
|
|
375
594
|
throw new Error('AUN config missing (aid required, e.g. "mybot.agentid.pub")');
|
|
376
595
|
}
|
|
377
|
-
|
|
378
|
-
aid: aunConfig.aid,
|
|
379
|
-
keystorePath: aunConfig.keystorePath,
|
|
380
|
-
gatewayPort: aunConfig.gatewayPort,
|
|
381
|
-
gatewayUrl: aunConfig.gatewayUrl,
|
|
382
|
-
accessToken: aunConfig.accessToken,
|
|
383
|
-
flushDelay: aunConfig.flushDelay,
|
|
384
|
-
encryptionSeed: aunConfig.encryptionSeed,
|
|
385
|
-
});
|
|
386
|
-
const adapter = {
|
|
387
|
-
name: 'aun',
|
|
388
|
-
sendText: (id, text, context) => channel.sendMessage(id, text, context),
|
|
389
|
-
acknowledge: (messageId) => { channel.acknowledge(messageId); return Promise.resolve(); },
|
|
390
|
-
sendProcessingStatus: (id, status, sessionId, context) => channel.sendProcessingStatus(id, status, sessionId, context),
|
|
391
|
-
sendCustomPayload: (id, payload) => channel.sendCustomPayload(id, payload),
|
|
392
|
-
};
|
|
393
|
-
const policy = {
|
|
394
|
-
canSwitchProject: (chatType, identity) => identity === 'owner',
|
|
395
|
-
canListProjects: (chatType, identity) => identity === 'owner',
|
|
396
|
-
canCreateSession: (chatType, identity) => true,
|
|
397
|
-
canDeleteSession: (chatType, identity) => true,
|
|
398
|
-
canImportCliSession: (chatType, identity) => identity === 'owner',
|
|
399
|
-
messagePrefix: (chatType, peerName) => (chatType === 'group' && peerName) ? `[${peerName}] ` : '',
|
|
400
|
-
showMiddleResult: (chatType, identity) => {
|
|
401
|
-
const mode = aunConfig.showActivities ?? config.showActivities ?? 'all';
|
|
402
|
-
if (mode === 'none')
|
|
403
|
-
return false;
|
|
404
|
-
if (mode === 'dm-only')
|
|
405
|
-
return chatType === 'private';
|
|
406
|
-
if (mode === 'owner-dm-only')
|
|
407
|
-
return chatType === 'private' && identity === 'owner';
|
|
408
|
-
return true;
|
|
409
|
-
},
|
|
410
|
-
showIdleMonitor: (chatType, identity) => {
|
|
411
|
-
const mode = aunConfig.showActivities ?? config.showActivities ?? 'all';
|
|
412
|
-
if (mode === 'none')
|
|
413
|
-
return false;
|
|
414
|
-
if (mode === 'dm-only')
|
|
415
|
-
return chatType === 'private';
|
|
416
|
-
if (mode === 'owner-dm-only')
|
|
417
|
-
return chatType === 'private' && identity === 'owner';
|
|
418
|
-
return true;
|
|
419
|
-
},
|
|
420
|
-
accumulateErrors: (chatType, identity) => true,
|
|
421
|
-
};
|
|
422
|
-
const options = {
|
|
423
|
-
flushDelay: aunConfig.flushDelay ?? 3,
|
|
424
|
-
fileMarkerPattern: /\[SEND_FILE:(?:(\w+):)?([^\]]+)\]/g,
|
|
425
|
-
};
|
|
426
|
-
return {
|
|
427
|
-
adapter,
|
|
428
|
-
channel,
|
|
429
|
-
policy,
|
|
430
|
-
options,
|
|
431
|
-
connect: () => channel.connect(),
|
|
432
|
-
disconnect: () => channel.disconnect(),
|
|
433
|
-
};
|
|
596
|
+
return instances[0];
|
|
434
597
|
}
|
|
435
598
|
}
|