evolclaw 3.0.0 → 3.1.1
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 +1 -1
- package/bin/ec.js +29 -0
- package/dist/agents/baseagent-normalize.js +19 -0
- package/dist/agents/claude-runner.js +47 -12
- package/dist/agents/codex-runner.js +2 -0
- package/dist/agents/gemini-runner.js +9 -9
- package/dist/agents/kit-renderer.js +281 -0
- package/dist/aun/aid/identity.js +28 -0
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/lifecycle-log.js +33 -0
- package/dist/aun/msg/group.js +3 -1
- package/dist/aun/msg/p2p.js +42 -1
- package/dist/channels/aun.js +427 -146
- package/dist/channels/dingtalk.js +3 -1
- package/dist/channels/feishu.js +128 -7
- package/dist/channels/qqbot.js +3 -1
- package/dist/channels/wechat.js +4 -1
- package/dist/channels/wecom.js +3 -1
- package/dist/cli/bench.js +1219 -0
- package/dist/cli/index.js +418 -40
- package/dist/cli/init.js +3 -4
- package/dist/cli/link-rules.js +245 -0
- package/dist/cli/net-check.js +640 -0
- package/dist/cli/watch-msg.js +666 -0
- package/dist/config-store.js +82 -5
- package/dist/core/channel-loader.js +23 -10
- package/dist/core/command-handler.js +127 -99
- package/dist/core/evolagent.js +5 -10
- package/dist/core/message/im-renderer.js +93 -48
- package/dist/core/message/items-formatter.js +11 -4
- package/dist/core/message/message-bridge.js +11 -2
- package/dist/core/message/message-log.js +8 -1
- package/dist/core/message/message-processor.js +194 -127
- package/dist/core/message/message-queue.js +10 -3
- package/dist/core/permission.js +95 -3
- package/dist/core/relation/peer-identity.js +161 -0
- package/dist/core/session/session-manager.js +103 -65
- package/dist/core/trigger/manager.js +16 -0
- package/dist/core/trigger/parser.js +110 -0
- package/dist/core/trigger/scheduler.js +7 -1
- package/dist/data/error-dict.json +118 -0
- package/dist/eck/baseagent-caps.js +18 -0
- package/dist/eck/detect.js +47 -0
- package/dist/eck/init.js +77 -0
- package/dist/eck/rules-loader.js +28 -0
- package/dist/index.js +186 -19
- package/dist/net-check.js +640 -0
- package/dist/paths.js +31 -40
- package/dist/utils/aid-lifecycle-log.js +33 -0
- package/dist/utils/atomic-write.js +10 -0
- package/dist/utils/cross-platform.js +17 -8
- package/dist/utils/error-utils.js +27 -15
- package/dist/utils/instance-registry.js +6 -5
- package/dist/utils/log-writer.js +2 -1
- package/dist/utils/logger.js +10 -0
- package/dist/utils/npm-ops.js +35 -3
- package/dist/utils/process-introspect.js +16 -38
- package/dist/utils/stats.js +216 -2
- package/dist/watch-msg.js +26 -11
- package/evolclaw-install-aun.md +14 -2
- package/kits/docs/GUIDE.md +20 -0
- package/kits/docs/INDEX.md +52 -0
- package/kits/docs/aun/CHEATSHEET.md +17 -0
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
- package/kits/docs/channels/feishu.md +27 -0
- package/kits/docs/eck_templates/GUIDE.template.md +22 -0
- package/kits/docs/eck_templates/INDEX.template.md +28 -0
- package/kits/docs/eck_templates/path-registry.template.md +33 -0
- package/kits/docs/eck_templates/runtime.template.md +19 -0
- package/kits/docs/evolclaw/MSG_GROUP.md +30 -0
- package/kits/docs/evolclaw/MSG_PRIVATE.md +72 -0
- package/kits/docs/identity/AID_PROFILE_SPEC.md +27 -0
- package/kits/docs/identity/PATH_OPS.md +16 -0
- package/kits/docs/identity/ROLE_DETAIL.md +20 -0
- package/kits/docs/path-registry.md +43 -0
- package/kits/eck_manifest.json +95 -0
- package/kits/rules/01-overview.md +120 -0
- package/kits/rules/02-navigation.md +75 -0
- package/kits/rules/03-identity.md +34 -0
- package/kits/rules/04-relation.md +49 -0
- package/kits/rules/05-venue.md +45 -0
- package/kits/rules/06-channel.md +73 -0
- package/kits/templates/system-fragments/baseagent.md +2 -0
- package/kits/templates/system-fragments/channel.md +10 -0
- package/kits/templates/system-fragments/identity.md +12 -0
- package/kits/templates/system-fragments/relation.md +9 -0
- package/kits/templates/system-fragments/runtime.md +19 -0
- package/kits/templates/system-fragments/venue.md +5 -0
- package/package.json +7 -5
- package/dist/agents/templates.js +0 -122
- package/dist/data/prompts.md +0 -137
- package/kits/aun/meta.md +0 -25
- package/kits/aun/role.md +0 -25
- package/kits/templates/group.md +0 -20
- package/kits/templates/private.md +0 -9
- package/kits/templates/system-fragments/personal-context.md +0 -3
- package/kits/templates/system-fragments/self-intro.md +0 -5
- package/kits/templates/system-fragments/speaker-intro.md +0 -5
- package/kits/templates/system-fragments/venue-intro.md +0 -5
- /package/kits/{channels → docs/channels}/aun.md +0 -0
- /package/kits/{evolclaw/commands.md → docs/evolclaw/AGENT_CMD.md} +0 -0
- /package/kits/{evolclaw → docs/evolclaw}/self-summary.md +0 -0
- /package/kits/{evolclaw → docs/evolclaw}/tools.md +0 -0
- /package/kits/{evolclaw → docs/identity}/identity-tools.md +0 -0
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ClaudeSessionFileAdapter } from './core/session/adapters/claude-session-file-adapter.js';
|
|
2
2
|
import { CodexSessionFileAdapter } from './core/session/adapters/codex-session-file-adapter.js';
|
|
3
3
|
import { GeminiSessionFileAdapter } from './core/session/adapters/gemini-session-file-adapter.js';
|
|
4
|
-
import { ensureDataDirs, resolvePaths,
|
|
4
|
+
import { ensureDataDirs, resolvePaths, getPackageRoot } from './paths.js';
|
|
5
5
|
import { resolveAnthropicConfig } from './agents/resolve.js';
|
|
6
|
-
import { loadDefaults, autoMigrateIfNeeded } from './config-store.js';
|
|
6
|
+
import { loadDefaults, autoMigrateIfNeeded, migrateIdentitiesIfNeeded } from './config-store.js';
|
|
7
7
|
import { CONFIG_SCHEMA_VERSION } from './types.js';
|
|
8
8
|
import { SessionManager } from './core/session/session-manager.js';
|
|
9
9
|
import { ClaudeAgentPlugin } from './agents/claude-runner.js';
|
|
@@ -33,14 +33,53 @@ import { IpcServer } from './ipc.js';
|
|
|
33
33
|
import { logger, setLogLevel } from './utils/logger.js';
|
|
34
34
|
import { writeMain, removeAll, isMainWinner, scanInstances } from './utils/instance-registry.js';
|
|
35
35
|
import { detectDuplicates } from './core/evolagent-registry.js';
|
|
36
|
-
import {
|
|
36
|
+
import { loadKitManifest, cleanEckDebug, invalidateKitCache } from './agents/kit-renderer.js';
|
|
37
|
+
import { initEck } from './eck/init.js';
|
|
37
38
|
import { TriggerManager } from './core/trigger/manager.js';
|
|
38
|
-
import { TriggerScheduler } from './core/trigger/scheduler.js';
|
|
39
|
+
import { TriggerScheduler, calcNextFireAt } from './core/trigger/scheduler.js';
|
|
39
40
|
import { agentTriggersDir } from './paths.js';
|
|
41
|
+
import { isLinkedInstall } from './utils/npm-ops.js';
|
|
40
42
|
import path from 'path';
|
|
41
43
|
import fs from 'fs';
|
|
42
44
|
import os from 'os';
|
|
43
45
|
import crypto from 'crypto';
|
|
46
|
+
import { fileURLToPath } from 'url';
|
|
47
|
+
/** 出站 payload 摘要(用于 channel-out.log) */
|
|
48
|
+
function summarizeOutboundPayload(payload) {
|
|
49
|
+
if (!payload)
|
|
50
|
+
return { kind: 'unknown' };
|
|
51
|
+
const s = { kind: payload.kind };
|
|
52
|
+
switch (payload.kind) {
|
|
53
|
+
case 'activity.batch':
|
|
54
|
+
s.itemCount = payload.items?.length ?? 0;
|
|
55
|
+
s.items = payload.items;
|
|
56
|
+
break;
|
|
57
|
+
case 'result.text':
|
|
58
|
+
s.isFinal = payload.isFinal;
|
|
59
|
+
s.text = payload.text;
|
|
60
|
+
break;
|
|
61
|
+
case 'result.file':
|
|
62
|
+
s.filePath = payload.filePath;
|
|
63
|
+
break;
|
|
64
|
+
case 'system.notice':
|
|
65
|
+
case 'system.error':
|
|
66
|
+
s.subtype = payload.subtype;
|
|
67
|
+
s.text = payload.text;
|
|
68
|
+
break;
|
|
69
|
+
case 'interaction':
|
|
70
|
+
s.interactionId = payload.interaction?.id;
|
|
71
|
+
s.interactionKind = payload.interaction?.kind?.kind;
|
|
72
|
+
break;
|
|
73
|
+
case 'status.started':
|
|
74
|
+
case 'status.completed':
|
|
75
|
+
case 'status.interrupted':
|
|
76
|
+
case 'status.error':
|
|
77
|
+
case 'status.timeout':
|
|
78
|
+
s.metadata = payload.metadata;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
return s;
|
|
82
|
+
}
|
|
44
83
|
/**
|
|
45
84
|
* 通过 adapter.send 发送系统类 payload(system.notice / system.error / 等)。
|
|
46
85
|
*
|
|
@@ -54,7 +93,77 @@ import crypto from 'crypto';
|
|
|
54
93
|
export async function sendSystemPayload(adapter, envelope, payload) {
|
|
55
94
|
await adapter.send(envelope, payload);
|
|
56
95
|
}
|
|
96
|
+
function readEvolclawVersion() {
|
|
97
|
+
try {
|
|
98
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(getPackageRoot(), 'package.json'), 'utf-8'));
|
|
99
|
+
return pkg.version || 'unknown';
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return 'unknown';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function readFastaunVersion() {
|
|
106
|
+
try {
|
|
107
|
+
const url = import.meta.resolve?.('@agentunion/fastaun');
|
|
108
|
+
if (!url)
|
|
109
|
+
return 'unknown';
|
|
110
|
+
let dir = path.dirname(fileURLToPath(url));
|
|
111
|
+
while (dir !== path.dirname(dir)) {
|
|
112
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
113
|
+
if (fs.existsSync(pkgPath)) {
|
|
114
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
115
|
+
if (pkg.name === '@agentunion/fastaun')
|
|
116
|
+
return pkg.version || 'unknown';
|
|
117
|
+
}
|
|
118
|
+
dir = path.dirname(dir);
|
|
119
|
+
}
|
|
120
|
+
return 'unknown';
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return 'unknown';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
57
126
|
async function main() {
|
|
127
|
+
// 启动信息:目录类型 + 版本号 + 代码最新时间戳
|
|
128
|
+
{
|
|
129
|
+
const pkgRoot = getPackageRoot();
|
|
130
|
+
const runDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1'));
|
|
131
|
+
const isDist = runDir.includes(path.join(pkgRoot, 'dist'));
|
|
132
|
+
const isLinked = fs.existsSync(path.join(pkgRoot, '.git'));
|
|
133
|
+
const dirType = isDist ? (isLinked ? '开发仓/dist' : '安装路径/dist') : '源码(tsx)';
|
|
134
|
+
const scanDir = isDist ? path.join(pkgRoot, 'dist') : path.join(pkgRoot, 'src');
|
|
135
|
+
let latestMtime = 0;
|
|
136
|
+
const scanRecursive = (dir) => {
|
|
137
|
+
try {
|
|
138
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
139
|
+
if (entry.name === 'node_modules')
|
|
140
|
+
continue;
|
|
141
|
+
const full = path.join(dir, entry.name);
|
|
142
|
+
if (entry.isDirectory()) {
|
|
143
|
+
scanRecursive(full);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (entry.name.endsWith('.js') || entry.name.endsWith('.ts')) {
|
|
147
|
+
const mt = fs.statSync(full).mtimeMs;
|
|
148
|
+
if (mt > latestMtime)
|
|
149
|
+
latestMtime = mt;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch { }
|
|
154
|
+
};
|
|
155
|
+
scanRecursive(scanDir);
|
|
156
|
+
let version = '?';
|
|
157
|
+
try {
|
|
158
|
+
version = JSON.parse(fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf-8')).version;
|
|
159
|
+
}
|
|
160
|
+
catch { }
|
|
161
|
+
const fmtTime = (ms) => { const d = new Date(ms); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`; };
|
|
162
|
+
console.error(`[EvolClaw] EvolClaw v${version}`);
|
|
163
|
+
console.error(`[EvolClaw] 执行类型: ${dirType}`);
|
|
164
|
+
console.error(`[EvolClaw] 包路径: ${pkgRoot}`);
|
|
165
|
+
console.error(`[EvolClaw] 代码时间: ${latestMtime ? fmtTime(latestMtime) : '?'}`);
|
|
166
|
+
}
|
|
58
167
|
// 过滤飞书 SDK 的 info 日志
|
|
59
168
|
const originalLog = console.log;
|
|
60
169
|
const originalInfo = console.info;
|
|
@@ -72,11 +181,9 @@ async function main() {
|
|
|
72
181
|
return;
|
|
73
182
|
originalInfo(...args);
|
|
74
183
|
};
|
|
75
|
-
logger.info(
|
|
184
|
+
logger.info(`EvolClaw v${readEvolclawVersion()} starting... (fastaun v${readFastaunVersion()})`);
|
|
76
185
|
// 确保数据目录存在
|
|
77
186
|
ensureDataDirs();
|
|
78
|
-
// 同步包内 kits/ 到 EVOLCLAW_HOME/kits/(首次启动或升级时)
|
|
79
|
-
syncKitsFromPackage();
|
|
80
187
|
// ── 单实例保护(pre-check + post-write self-check)──
|
|
81
188
|
// pre-check:发现已有活 main 直接退出,避免起任何副作用
|
|
82
189
|
{
|
|
@@ -104,16 +211,20 @@ async function main() {
|
|
|
104
211
|
process.exit(0);
|
|
105
212
|
}
|
|
106
213
|
}
|
|
107
|
-
//
|
|
108
|
-
|
|
214
|
+
// ── 自动迁移 ──
|
|
215
|
+
migrateIdentitiesIfNeeded();
|
|
216
|
+
autoMigrateIfNeeded();
|
|
217
|
+
// ── ECK 运行时初始化 ──
|
|
218
|
+
initEck();
|
|
219
|
+
// 加载 ECK manifest + 清理旧调试文件
|
|
220
|
+
cleanEckDebug();
|
|
221
|
+
loadKitManifest();
|
|
109
222
|
// 加载配置(新结构:defaults.json + per-agent config.json)
|
|
110
223
|
const defaults = loadDefaults() ?? { $schema_version: CONFIG_SCHEMA_VERSION };
|
|
111
224
|
// 应用配置中的日志级别(优先于环境变量)
|
|
112
225
|
// logLevel 现在不在新结构中——若要保留,将来可加 defaults.debug.logLevel
|
|
113
226
|
// 阶段 2c 暂跳过
|
|
114
227
|
const paths = resolvePaths();
|
|
115
|
-
// ── 自动迁移:旧 data/evolclaw.json → 新结构 ──
|
|
116
|
-
autoMigrateIfNeeded();
|
|
117
228
|
// ── EvolAgent Registry:加载 agents/<aid>/config.json ──
|
|
118
229
|
const agentRegistry = new EvolAgentRegistry(paths.agentsDir);
|
|
119
230
|
agentRegistry.loadAll();
|
|
@@ -190,16 +301,22 @@ async function main() {
|
|
|
190
301
|
// 统计收集器(近 1 小时滚动统计)
|
|
191
302
|
const statsCollector = new StatsCollector(eventBus);
|
|
192
303
|
// Per-AID 消息统计收集器(累计,供 watch aid 实时展示)
|
|
193
|
-
const aidStatsCollector = new AidStatsCollector();
|
|
304
|
+
const aidStatsCollector = new AidStatsCollector(eventBus);
|
|
305
|
+
aidStatsCollector.setSessionsDir(paths.sessionsDir);
|
|
194
306
|
// 初始化 SessionManager(文件系统后端)
|
|
195
307
|
const sessionManager = new SessionManager(paths.sessionsDir, eventBus, (channel, userId) => agentRegistry.isOwner(channel, userId), (channel, userId) => agentRegistry.isAdmin(channel, userId));
|
|
196
308
|
// sessionMode 解析:从 channel 路由到具体 agent,按 agent.config.chatmode
|
|
197
|
-
sessionManager.setSessionModeResolver((channelKey, chatType) => {
|
|
309
|
+
sessionManager.setSessionModeResolver((channelKey, chatType, peerType) => {
|
|
198
310
|
const agent = agentRegistry.resolveByChannel(channelKey);
|
|
199
311
|
const cm = agent?.config.chatmode;
|
|
200
312
|
if (!cm)
|
|
201
313
|
return undefined;
|
|
202
|
-
|
|
314
|
+
// 优先级:群聊 > nothuman > private
|
|
315
|
+
if (chatType === 'group')
|
|
316
|
+
return cm.group;
|
|
317
|
+
if (peerType && peerType !== 'human' && peerType !== 'unknown')
|
|
318
|
+
return cm.nothuman;
|
|
319
|
+
return cm.private;
|
|
203
320
|
});
|
|
204
321
|
logger.info('✓ Database initialized');
|
|
205
322
|
// 注册会话文件适配器(Claude / Codex 各自的会话文件操作)
|
|
@@ -361,6 +478,49 @@ async function main() {
|
|
|
361
478
|
if (primaryAgentForTrigger?.triggerScheduler && primaryAgentForTrigger?.triggerManager) {
|
|
362
479
|
cmdHandler.setTriggerScheduler(primaryAgentForTrigger.triggerScheduler, primaryAgentForTrigger.triggerManager);
|
|
363
480
|
}
|
|
481
|
+
// Seed default __upgrade-check trigger (daily at random time 3:00~3:59)
|
|
482
|
+
// 用户可通过 /trigger cancel __upgrade-check 永久禁用(不会再自动重建)
|
|
483
|
+
if (!isLinkedInstall() && primaryAgentForTrigger?.triggerManager && primaryAgentForTrigger?.triggerScheduler) {
|
|
484
|
+
const mgr = primaryAgentForTrigger.triggerManager;
|
|
485
|
+
const sched = primaryAgentForTrigger.triggerScheduler;
|
|
486
|
+
const UPGRADE_TRIGGER_NAME = '__upgrade-check';
|
|
487
|
+
if (!mgr.getByName(UPGRADE_TRIGGER_NAME)) {
|
|
488
|
+
// Check history: if user cancelled it before, respect that decision
|
|
489
|
+
const { history } = mgr.listAll();
|
|
490
|
+
const wasCancelled = history.some(h => h.name === UPGRADE_TRIGGER_NAME && h.doneReason === 'cancelled');
|
|
491
|
+
if (!wasCancelled) {
|
|
492
|
+
// Random minute in 3:00~3:59 to avoid all instances hitting registry simultaneously
|
|
493
|
+
const randomMinute = Math.floor(Math.random() * 60);
|
|
494
|
+
const cronExpr = `${randomMinute} 3 * * *`;
|
|
495
|
+
// Use first channel instance as target (command doesn't need real channelId)
|
|
496
|
+
const firstChannel = channelInstances[0]?.adapter?.channelName || 'system';
|
|
497
|
+
const trigger = {
|
|
498
|
+
id: crypto.randomUUID(),
|
|
499
|
+
name: UPGRADE_TRIGGER_NAME,
|
|
500
|
+
scheduleType: 'cron',
|
|
501
|
+
scheduleValue: cronExpr,
|
|
502
|
+
nextFireAt: calcNextFireAt('cron', cronExpr),
|
|
503
|
+
targetChannel: firstChannel,
|
|
504
|
+
targetChannelId: '__system__',
|
|
505
|
+
targetSessionStrategy: 'silent',
|
|
506
|
+
prompt: '检查 evolclaw 是否有新版本可用。执行 `npm view evolclaw version` 获取最新版本,与当前版本(执行 `evolclaw --version`)对比。如果有新版本,执行 /restart 进行升级。如果已是最新版本,无需任何操作。',
|
|
507
|
+
createdByPeerId: '__system__',
|
|
508
|
+
createdByChannel: '__system__',
|
|
509
|
+
fireCount: 0,
|
|
510
|
+
createdAt: Date.now(),
|
|
511
|
+
updatedAt: Date.now(),
|
|
512
|
+
};
|
|
513
|
+
try {
|
|
514
|
+
mgr.register(trigger);
|
|
515
|
+
sched.register(trigger);
|
|
516
|
+
logger.info(`[Trigger] Seeded default trigger: ${UPGRADE_TRIGGER_NAME} (cron ${cronExpr})`);
|
|
517
|
+
}
|
|
518
|
+
catch (e) {
|
|
519
|
+
logger.warn(`[Trigger] Failed to seed ${UPGRADE_TRIGGER_NAME}: ${e}`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
364
524
|
// 默认策略
|
|
365
525
|
const defaultPolicy = {
|
|
366
526
|
canSwitchProject: (chatType, role) => chatType === 'private' ? (role === 'owner' || role === 'admin') : role === 'owner',
|
|
@@ -378,6 +538,12 @@ async function main() {
|
|
|
378
538
|
msgBridge.setAgentRegistry(agentRegistry);
|
|
379
539
|
// ── Channel instance registration (shared by startup and hot-load) ──
|
|
380
540
|
function registerChannelInstance(inst) {
|
|
541
|
+
// 0. 包装 adapter.send,记录所有出站到 channel-out.log
|
|
542
|
+
const originalSend = inst.adapter.send.bind(inst.adapter);
|
|
543
|
+
inst.adapter.send = async (envelope, payload) => {
|
|
544
|
+
logger.channelOut({ channel: inst.adapter.channelName, channelId: envelope.channelId, taskId: envelope.taskId, payload: summarizeOutboundPayload(payload) });
|
|
545
|
+
return originalSend(envelope, payload);
|
|
546
|
+
};
|
|
381
547
|
// 1. 项目路径提供器
|
|
382
548
|
if (inst.onProjectPathRequest && inst.channel.onProjectPathRequest) {
|
|
383
549
|
inst.channel.onProjectPathRequest(async (channelId) => {
|
|
@@ -435,6 +601,10 @@ async function main() {
|
|
|
435
601
|
agent.status = 'running';
|
|
436
602
|
}
|
|
437
603
|
}
|
|
604
|
+
// 写入 ready 信号(核心服务已就绪,channel 连接不阻塞启动判定)
|
|
605
|
+
const readySignalPath = resolvePaths().readySignal;
|
|
606
|
+
fs.writeFileSync(readySignalPath, String(Date.now()));
|
|
607
|
+
logger.info(`✓ Ready signal written: ${readySignalPath}`);
|
|
438
608
|
// ── 连接所有渠道(异步,AUN 等 WebSocket 渠道在后台重连)──
|
|
439
609
|
const connected = await channelLoader.connectAll(channelInstances);
|
|
440
610
|
// 预填充 Feishu 已知 thread_id(重启后避免误判话题创建)
|
|
@@ -631,10 +801,6 @@ async function main() {
|
|
|
631
801
|
logger.error('[Restart] Failed to send restart notification:', e);
|
|
632
802
|
}
|
|
633
803
|
}
|
|
634
|
-
// 写入 ready 信号,供 restart-monitor 检测启动成功
|
|
635
|
-
const readySignalPath = resolvePaths().readySignal;
|
|
636
|
-
fs.writeFileSync(readySignalPath, String(Date.now()));
|
|
637
|
-
logger.info(`✓ Ready signal written: ${readySignalPath}`);
|
|
638
804
|
// IPC server — 供 CLI 查询实时状态 + Agent ctl 指令执行
|
|
639
805
|
const ipcServer = new IpcServer(resolvePaths().socket, () => {
|
|
640
806
|
const channels = {};
|
|
@@ -784,7 +950,8 @@ async function main() {
|
|
|
784
950
|
results.push(`⚠ ${cfg.aid}: ${e?.message || e}`);
|
|
785
951
|
}
|
|
786
952
|
}
|
|
787
|
-
// 重建 channel index
|
|
953
|
+
// 重建 channel index + 清除 kit 缓存
|
|
954
|
+
invalidateKitCache();
|
|
788
955
|
agentRegistry.channelIndex.clear();
|
|
789
956
|
agentRegistry.buildChannelIndex();
|
|
790
957
|
logger.info(`[Resync] Done: ${results.length} agent(s) processed`);
|