evolclaw 2.6.0 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channels/aun.js +127 -17
- package/dist/channels/feishu.js +4 -3
- package/dist/cli.js +104 -7
- package/dist/config.js +1 -1
- package/dist/core/command-handler.js +111 -8
- package/dist/core/message/message-processor.js +64 -50
- package/dist/core/message/message-queue.js +10 -2
- package/dist/core/message/stream-debouncer.js +9 -1
- package/dist/core/message/thought-emitter.js +153 -0
- package/dist/index.js +51 -30
- package/dist/templates/skills.md +5 -3
- package/dist/utils/init-channel.js +78 -5
- package/dist/utils/init.js +3 -3
- package/dist/utils/upgrade.js +100 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -204,9 +204,11 @@ async function main() {
|
|
|
204
204
|
showIdleMonitor: () => true,
|
|
205
205
|
accumulateErrors: () => true,
|
|
206
206
|
};
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
// ── MessageBridge:Channel ↔ Core 消息桥梁 ──
|
|
208
|
+
const msgBridge = new MessageBridge(config, sessionManager, processor, messageQueue, cmdHandler, eventBus);
|
|
209
|
+
// ── Channel instance registration (shared by startup and hot-load) ──
|
|
210
|
+
function registerChannelInstance(inst) {
|
|
211
|
+
// 1. 项目路径提供器
|
|
210
212
|
if (inst.onProjectPathRequest && inst.channel.onProjectPathRequest) {
|
|
211
213
|
inst.channel.onProjectPathRequest(async (channelId) => {
|
|
212
214
|
const session = await sessionManager.getOrCreateSession(inst.adapter.channelName, channelId, config.projects?.defaultPath || process.cwd(), undefined, undefined, undefined, undefined);
|
|
@@ -215,7 +217,7 @@ async function main() {
|
|
|
215
217
|
: path.resolve(process.cwd(), session.projectPath);
|
|
216
218
|
});
|
|
217
219
|
}
|
|
218
|
-
// 注册 adapter、policy 和 options(注入 channelType)
|
|
220
|
+
// 2. 注册 adapter、policy 和 options(注入 channelType)
|
|
219
221
|
const opts = inst.channelType
|
|
220
222
|
? { ...inst.options, channelType: inst.channelType }
|
|
221
223
|
: inst.options;
|
|
@@ -225,18 +227,13 @@ async function main() {
|
|
|
225
227
|
if (inst.policy) {
|
|
226
228
|
cmdHandler.registerPolicy(inst.adapter.channelName, inst.policy);
|
|
227
229
|
}
|
|
228
|
-
//
|
|
230
|
+
// 3. 交互回调
|
|
229
231
|
if (inst.adapter.onInteraction) {
|
|
230
232
|
inst.adapter.onInteraction((response) => {
|
|
231
233
|
interactionRouter.handle(response);
|
|
232
234
|
});
|
|
233
235
|
}
|
|
234
|
-
|
|
235
|
-
// ── MessageBridge:Channel ↔ Core 消息桥梁 ──
|
|
236
|
-
const msgBridge = new MessageBridge(config, sessionManager, processor, messageQueue, cmdHandler, eventBus);
|
|
237
|
-
// ── 渠道消息注册 ──
|
|
238
|
-
// 连接插件系统的渠道
|
|
239
|
-
for (const inst of channelInstances) {
|
|
236
|
+
// 4. MessageBridge 注册(按 channelType 分发)
|
|
240
237
|
const channelType = inst.channelType || inst.adapter.channelName;
|
|
241
238
|
if (channelType === 'feishu') {
|
|
242
239
|
msgBridge.register(inst.adapter.channelName, (handler) => inst.channel.onMessage(async ({ channelId: chatId, content, images, peerId, peerName, messageId, mentions, threadId, rootId, chatType }) => {
|
|
@@ -251,7 +248,6 @@ async function main() {
|
|
|
251
248
|
}), inst.adapter, channelType);
|
|
252
249
|
}
|
|
253
250
|
if (channelType === 'wechat') {
|
|
254
|
-
// 注入 EventBus(用于 channel:health 事件)
|
|
255
251
|
if (inst.channel.setEventBus) {
|
|
256
252
|
inst.channel.setEventBus(eventBus);
|
|
257
253
|
}
|
|
@@ -281,6 +277,19 @@ async function main() {
|
|
|
281
277
|
replyContext: opts.replyContext,
|
|
282
278
|
});
|
|
283
279
|
}), (channelId, text, replyContext) => inst.channel.sendMessage(channelId, text, replyContext), inst.adapter, channelType);
|
|
280
|
+
// AUN 重连失败通知
|
|
281
|
+
if (inst.channel.setOnChannelDown) {
|
|
282
|
+
inst.channel.setOnChannelDown(() => {
|
|
283
|
+
eventBus.publish({
|
|
284
|
+
type: 'channel:health',
|
|
285
|
+
channel: channelType,
|
|
286
|
+
channelName: inst.adapter.channelName,
|
|
287
|
+
status: 'auth_error',
|
|
288
|
+
message: `⚠️ AUN 渠道 ${inst.adapter.channelName} 断连,自动重试已用尽。\n使用 /check rty aun 手动重连`,
|
|
289
|
+
timestamp: Date.now(),
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
284
293
|
}
|
|
285
294
|
if (channelType === 'dingtalk') {
|
|
286
295
|
msgBridge.register(inst.adapter.channelName, (handler) => inst.channel.onMessage(async (event) => {
|
|
@@ -310,11 +319,40 @@ async function main() {
|
|
|
310
319
|
});
|
|
311
320
|
}), (channelId, text) => inst.channel.sendMessage(channelId, text), inst.adapter, channelType);
|
|
312
321
|
}
|
|
313
|
-
|
|
322
|
+
if (channelType === 'wecom') {
|
|
323
|
+
msgBridge.register(inst.adapter.channelName, (handler) => inst.channel.onMessage(async (event) => {
|
|
324
|
+
handler({
|
|
325
|
+
channel: channelType,
|
|
326
|
+
channelId: event.channelId,
|
|
327
|
+
content: event.content,
|
|
328
|
+
chatType: event.chatType || 'private',
|
|
329
|
+
peerId: event.peerId || '',
|
|
330
|
+
peerName: event.peerName,
|
|
331
|
+
messageId: event.messageId,
|
|
332
|
+
});
|
|
333
|
+
}), (channelId, text) => inst.channel.sendMessage(channelId, text), inst.adapter, channelType);
|
|
334
|
+
}
|
|
335
|
+
// 5. 撤回消息 → 中断执行中任务
|
|
314
336
|
inst.channel.onRecall?.((messageId) => {
|
|
315
337
|
msgBridge.cancel(messageId);
|
|
316
338
|
});
|
|
317
339
|
}
|
|
340
|
+
// ── 注册所有渠道实例 ──
|
|
341
|
+
for (const inst of channelInstances) {
|
|
342
|
+
registerChannelInstance(inst);
|
|
343
|
+
}
|
|
344
|
+
// ── 设置热加载回调 ──
|
|
345
|
+
cmdHandler.setHotLoadChannel(async (inst) => {
|
|
346
|
+
registerChannelInstance(inst);
|
|
347
|
+
channelInstances.push(inst);
|
|
348
|
+
await inst.connect();
|
|
349
|
+
eventBus.publish({
|
|
350
|
+
type: 'channel:connected',
|
|
351
|
+
channel: (inst.channelType || inst.adapter.channelName).toLowerCase(),
|
|
352
|
+
channelName: inst.adapter.channelName,
|
|
353
|
+
timestamp: Date.now(),
|
|
354
|
+
});
|
|
355
|
+
});
|
|
318
356
|
// ── 连接所有渠道 ──
|
|
319
357
|
const connected = await channelLoader.connectAll(channelInstances);
|
|
320
358
|
// 预填充 Feishu 已知 thread_id(重启后避免误判话题创建)
|
|
@@ -326,7 +364,6 @@ async function main() {
|
|
|
326
364
|
}
|
|
327
365
|
}
|
|
328
366
|
for (const name of connected) {
|
|
329
|
-
// 查找对应实例以获取 channelType
|
|
330
367
|
const inst = channelInstances.find(i => i.adapter.channelName === name);
|
|
331
368
|
const type = inst?.channelType || name;
|
|
332
369
|
eventBus.publish({
|
|
@@ -336,22 +373,6 @@ async function main() {
|
|
|
336
373
|
timestamp: Date.now()
|
|
337
374
|
});
|
|
338
375
|
}
|
|
339
|
-
// AUN 重连失败通知:通过 channel:health 事件
|
|
340
|
-
for (const inst of channelInstances) {
|
|
341
|
-
const channelType = inst.channelType || inst.adapter.channelName;
|
|
342
|
-
if (channelType === 'aun' && inst.channel.setOnChannelDown) {
|
|
343
|
-
inst.channel.setOnChannelDown(() => {
|
|
344
|
-
eventBus.publish({
|
|
345
|
-
type: 'channel:health',
|
|
346
|
-
channel: channelType,
|
|
347
|
-
channelName: inst.adapter.channelName,
|
|
348
|
-
status: 'auth_error',
|
|
349
|
-
message: `⚠️ AUN 渠道 ${inst.adapter.channelName} 断连,自动重试已用尽。\n使用 /check rty aun 手动重连`,
|
|
350
|
-
timestamp: Date.now(),
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
376
|
// 统一 channel:health 跨通道通知(仅 auth_error)
|
|
356
377
|
// 按 (channelType, ownerId) 去重,避免同类型多实例重复通知
|
|
357
378
|
eventBus.subscribe('channel:health', (event) => {
|
package/dist/templates/skills.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: evolclaw-ctl
|
|
3
|
-
version: 1.
|
|
4
|
-
description:
|
|
5
|
-
trigger:
|
|
3
|
+
version: 1.1.0
|
|
4
|
+
description: 仅在 evolclaw 运行时可用
|
|
5
|
+
trigger: 用户询问或需要切换模型、调整推理强度、查看运行状态、压缩上下文、检查通道健康、管理权限模式、重启服务、重连渠道等
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# EvolClaw Ctl
|
|
@@ -35,6 +35,8 @@ trigger: 用户询问或需要切换模型、调整推理强度、查看运行
|
|
|
35
35
|
- `evolclaw ctl agentmd` — 查看当前 agent.md
|
|
36
36
|
- `evolclaw ctl agentmd put` — 发布本地 agent.md
|
|
37
37
|
- `evolclaw ctl agentmd set <内容>` — 直接设置 agent.md 内容
|
|
38
|
+
- `evolclaw ctl aid` — 列出所有 AUN 实例及连接状态
|
|
39
|
+
- `evolclaw ctl aid new <aid>` — 创建新 AID 并热加载(仅 AUN 通道)
|
|
38
40
|
|
|
39
41
|
## 使用示例
|
|
40
42
|
|
|
@@ -580,9 +580,9 @@ export async function cmdInitWechat() {
|
|
|
580
580
|
process.exit(1);
|
|
581
581
|
}
|
|
582
582
|
// ==================== AUN ====================
|
|
583
|
-
// 最低 @agentunion/
|
|
584
|
-
const MIN_AUN_CORE_SDK = [0, 2,
|
|
585
|
-
const AUN_CORE_SDK_PKG = '@agentunion/
|
|
583
|
+
// 最低 @agentunion/fastaun 版本要求
|
|
584
|
+
const MIN_AUN_CORE_SDK = [0, 2, 14];
|
|
585
|
+
const AUN_CORE_SDK_PKG = '@agentunion/fastaun';
|
|
586
586
|
function compareVersion(a, min) {
|
|
587
587
|
const parts = a.split('.').map(n => parseInt(n, 10));
|
|
588
588
|
if (parts.length < 3 || parts.some(isNaN))
|
|
@@ -711,10 +711,83 @@ export async function checkAunEnvironment(rl) {
|
|
|
711
711
|
console.log('');
|
|
712
712
|
return true;
|
|
713
713
|
}
|
|
714
|
-
function isValidAid(name) {
|
|
714
|
+
export function isValidAid(name) {
|
|
715
715
|
const labels = name.split('.');
|
|
716
716
|
return labels.length >= 3 && labels.every(l => /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(l));
|
|
717
717
|
}
|
|
718
|
+
/**
|
|
719
|
+
* Non-interactive AID creation + agent.md publish.
|
|
720
|
+
* Reuses the same logic as `evolclaw init --non-interactive --channel aun`.
|
|
721
|
+
*
|
|
722
|
+
* Returns the created AID string, or throws on failure.
|
|
723
|
+
*/
|
|
724
|
+
export async function createAidSilent(opts) {
|
|
725
|
+
const aunPath = path.join(os.homedir(), '.aun');
|
|
726
|
+
const aidDir = path.join(aunPath, 'AIDs', opts.aid);
|
|
727
|
+
// Skip creation if AID already exists locally
|
|
728
|
+
if (fs.existsSync(aidDir) && fs.existsSync(path.join(aidDir, 'private'))) {
|
|
729
|
+
return { aid: opts.aid, alreadyExisted: true };
|
|
730
|
+
}
|
|
731
|
+
const { AUNClient } = await import('@agentunion/fastaun');
|
|
732
|
+
let client = new AUNClient({ aun_path: aunPath });
|
|
733
|
+
const result = await client.auth.createAid({ aid: opts.aid });
|
|
734
|
+
// Download CA root cert (if not already present)
|
|
735
|
+
const caDownloaded = await downloadCaRoot(aunPath, result.gateway || '');
|
|
736
|
+
// Rebuild client with CA cert + AID identity for uploadAgentMd
|
|
737
|
+
const caCertPath = path.join(aunPath, 'CA', 'root', 'root.crt');
|
|
738
|
+
if (caDownloaded && fs.existsSync(caCertPath)) {
|
|
739
|
+
try {
|
|
740
|
+
await client.close();
|
|
741
|
+
}
|
|
742
|
+
catch { /* ignore */ }
|
|
743
|
+
client = new AUNClient({ aun_path: aunPath, root_ca_path: caCertPath, aid: opts.aid });
|
|
744
|
+
}
|
|
745
|
+
// Write initial agent.md (initialized: false, name = aid first label)
|
|
746
|
+
const agentName = opts.aid.split('.')[0];
|
|
747
|
+
const agentMdContent = `---\naid: "${opts.aid}"\nname: "${agentName}"\ntype: "ai"\nversion: "1.0.0"\ndescription: ""\ntags:\n - evolclaw\ninitialized: false\n---\n`;
|
|
748
|
+
const agentMdPath = path.join(aidDir, 'agent.md');
|
|
749
|
+
try {
|
|
750
|
+
await client.auth.uploadAgentMd(agentMdContent);
|
|
751
|
+
}
|
|
752
|
+
catch (e) {
|
|
753
|
+
// Non-fatal: first connection will auto-retry
|
|
754
|
+
}
|
|
755
|
+
fs.writeFileSync(agentMdPath, agentMdContent, 'utf-8');
|
|
756
|
+
try {
|
|
757
|
+
await client.close();
|
|
758
|
+
}
|
|
759
|
+
catch { /* ignore */ }
|
|
760
|
+
if (!fs.existsSync(agentMdPath)) {
|
|
761
|
+
throw new Error(`agent.md write verification failed: ${agentMdPath}`);
|
|
762
|
+
}
|
|
763
|
+
return { aid: opts.aid, alreadyExisted: false };
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Append a new AUN instance to the config's channels.aun array and save.
|
|
767
|
+
* Handles upgrade from single-object to array format.
|
|
768
|
+
*/
|
|
769
|
+
export function appendAunInstance(config, inst) {
|
|
770
|
+
if (!config.channels)
|
|
771
|
+
config.channels = {};
|
|
772
|
+
const newInst = {
|
|
773
|
+
name: inst.name,
|
|
774
|
+
enabled: inst.enabled ?? true,
|
|
775
|
+
aid: inst.aid,
|
|
776
|
+
...(inst.owner && { owner: inst.owner }),
|
|
777
|
+
};
|
|
778
|
+
if (Array.isArray(config.channels.aun)) {
|
|
779
|
+
config.channels.aun.push(newInst);
|
|
780
|
+
}
|
|
781
|
+
else if (config.channels.aun) {
|
|
782
|
+
const oldInst = { ...config.channels.aun, name: config.channels.aun.name || 'aun' };
|
|
783
|
+
config.channels.aun = [oldInst, newInst];
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
config.channels.aun = [newInst];
|
|
787
|
+
}
|
|
788
|
+
const p = resolvePaths();
|
|
789
|
+
fs.writeFileSync(p.config, JSON.stringify(config, null, 2) + '\n');
|
|
790
|
+
}
|
|
718
791
|
export async function setupAunAid(rl, _config) {
|
|
719
792
|
let aid = '';
|
|
720
793
|
let gatewayPort; // only used locally for AID creation, not written to config
|
|
@@ -755,7 +828,7 @@ export async function setupAunAid(rl, _config) {
|
|
|
755
828
|
console.log(' 正在创建 AID...');
|
|
756
829
|
let failed = false;
|
|
757
830
|
try {
|
|
758
|
-
const { AUNClient } = await import('@agentunion/
|
|
831
|
+
const { AUNClient } = await import('@agentunion/fastaun');
|
|
759
832
|
let client = new AUNClient({ aun_path: aunPath });
|
|
760
833
|
// 如果用户指定了自定义端口,手动设置 gateway URL;否则让 SDK 自动发现
|
|
761
834
|
if (gatewayPort) {
|
package/dist/utils/init.js
CHANGED
|
@@ -408,14 +408,14 @@ export async function cmdInit(options) {
|
|
|
408
408
|
// 自动安装 AUN SDK
|
|
409
409
|
const { resolveAunCoreSdkPkg, npmInstallGlobal, downloadCaRoot } = await import('./init-channel.js');
|
|
410
410
|
if (!resolveAunCoreSdkPkg()) {
|
|
411
|
-
console.log('正在安装 @agentunion/
|
|
412
|
-
await npmInstallGlobal('@agentunion/
|
|
411
|
+
console.log('正在安装 @agentunion/fastaun...');
|
|
412
|
+
await npmInstallGlobal('@agentunion/fastaun@latest');
|
|
413
413
|
}
|
|
414
414
|
// 创建 AID(如果本地不存在)
|
|
415
415
|
const aunPath = path.join(os.homedir(), '.aun');
|
|
416
416
|
const aidDir = path.join(aunPath, 'AIDs', options.aunAid);
|
|
417
417
|
if (!fs.existsSync(path.join(aidDir, 'private'))) {
|
|
418
|
-
const { AUNClient } = await import('@agentunion/
|
|
418
|
+
const { AUNClient } = await import('@agentunion/fastaun');
|
|
419
419
|
let client = new AUNClient({ aun_path: aunPath });
|
|
420
420
|
// 让 SDK 通过 well-known 自动发现网关
|
|
421
421
|
const result = await client.auth.createAid({ aid: options.aunAid });
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execFile } from 'child_process';
|
|
4
|
+
import { getPackageRoot } from '../paths.js';
|
|
5
|
+
/**
|
|
6
|
+
* 比较两个 semver 版本号 (a.b.c 格式)
|
|
7
|
+
* 返回 -1 (a < b), 0 (a == b), 1 (a > b)
|
|
8
|
+
* 自动剥离 pre-release 标签 (e.g. 2.6.0-beta.1 → 2.6.0)
|
|
9
|
+
*/
|
|
10
|
+
export function compareVersions(a, b) {
|
|
11
|
+
const pa = a.split('-')[0].split('.').map(Number);
|
|
12
|
+
const pb = b.split('-')[0].split('.').map(Number);
|
|
13
|
+
const len = Math.max(pa.length, pb.length);
|
|
14
|
+
for (let i = 0; i < len; i++) {
|
|
15
|
+
const na = pa[i] ?? 0;
|
|
16
|
+
const nb = pb[i] ?? 0;
|
|
17
|
+
if (na < nb)
|
|
18
|
+
return -1;
|
|
19
|
+
if (na > nb)
|
|
20
|
+
return 1;
|
|
21
|
+
}
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 检查当前安装是否为 npm link 开发模式。
|
|
26
|
+
* 正式全局安装的路径结构为 .../node_modules/evolclaw,
|
|
27
|
+
* 而 npm link 指向项目源码目录,其父目录不是 node_modules。
|
|
28
|
+
*/
|
|
29
|
+
export function isLinkedInstall() {
|
|
30
|
+
const pkgRoot = getPackageRoot();
|
|
31
|
+
return path.basename(path.dirname(pkgRoot)) !== 'node_modules';
|
|
32
|
+
}
|
|
33
|
+
/** 获取本地 package.json 中的版本号 */
|
|
34
|
+
export function getLocalVersion() {
|
|
35
|
+
const pkgPath = path.join(getPackageRoot(), 'package.json');
|
|
36
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
37
|
+
return pkg.version;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 查询 npm registry 上 evolclaw 的最新版本。
|
|
41
|
+
* 超时 15 秒,失败返回 null。
|
|
42
|
+
*/
|
|
43
|
+
export function checkLatestVersion() {
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
execFile('npm', ['view', 'evolclaw', 'version'], { timeout: 15000 }, (err, stdout) => {
|
|
46
|
+
if (err) {
|
|
47
|
+
resolve(null);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const ver = stdout.trim();
|
|
51
|
+
resolve(ver || null);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 执行 npm install -g evolclaw@latest
|
|
57
|
+
*/
|
|
58
|
+
function runInstall() {
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
execFile('npm', ['install', '-g', 'evolclaw@latest'], { timeout: 120000 }, (err, _stdout, stderr) => {
|
|
61
|
+
if (err) {
|
|
62
|
+
resolve({ ok: false, error: stderr || err.message });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
resolve({ ok: true });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 完整升级流程:检查 → 比较 → 安装(失败重试一次)
|
|
72
|
+
*/
|
|
73
|
+
export async function tryUpgrade() {
|
|
74
|
+
// 开发模式跳过
|
|
75
|
+
if (isLinkedInstall()) {
|
|
76
|
+
return { status: 'skipped' };
|
|
77
|
+
}
|
|
78
|
+
const localVer = getLocalVersion();
|
|
79
|
+
// 查询 registry
|
|
80
|
+
const remoteVer = await checkLatestVersion();
|
|
81
|
+
if (!remoteVer) {
|
|
82
|
+
return { status: 'skipped', error: 'Failed to check remote version' };
|
|
83
|
+
}
|
|
84
|
+
// 版本比较
|
|
85
|
+
if (compareVersions(localVer, remoteVer) >= 0) {
|
|
86
|
+
return { status: 'no-update', from: localVer };
|
|
87
|
+
}
|
|
88
|
+
// 有新版本,执行升级(失败重试一次)
|
|
89
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
90
|
+
const result = await runInstall();
|
|
91
|
+
if (result.ok) {
|
|
92
|
+
return { status: 'upgraded', from: localVer, to: remoteVer };
|
|
93
|
+
}
|
|
94
|
+
if (attempt === 1) {
|
|
95
|
+
return { status: 'failed', from: localVer, to: remoteVer, error: result.error };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// unreachable
|
|
99
|
+
return { status: 'failed', from: localVer, to: remoteVer };
|
|
100
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evolclaw",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.2",
|
|
4
4
|
"description": "Lightweight AI Agent gateway connecting Claude Agent SDK to messaging channels (Feishu, ACP) with multi-project session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"prepublishOnly": "npm run build && npm test"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@agentunion/fastaun": "^0.2.15",
|
|
26
27
|
"@anthropic-ai/claude-agent-sdk": "^0.2.100",
|
|
27
|
-
"@agentunion/aun-node": "^0.2.12",
|
|
28
28
|
"image-type": "^6.0.0",
|
|
29
29
|
"qrcode-terminal": "^0.12.0"
|
|
30
30
|
},
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"pure-qqbot": "^2.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^25.5.0",
|
|
41
40
|
"@types/form-data": "^2.2.1",
|
|
41
|
+
"@types/node": "^25.5.0",
|
|
42
42
|
"@types/qrcode-terminal": "^0.12.2",
|
|
43
43
|
"@vitest/coverage-v8": "^4.1.0",
|
|
44
44
|
"tsx": "^4.19.0",
|