evolclaw 3.1.11 → 3.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/CHANGELOG.md +41 -0
- package/README.md +27 -2
- package/dist/agents/{resolve.js → baseagent.js} +34 -5
- package/dist/agents/claude-runner.js +120 -27
- package/dist/agents/codex-app-server-client.js +364 -0
- package/dist/agents/codex-runner.js +1069 -141
- package/dist/agents/gemini-runner.js +2 -2
- package/dist/agents/runner-types.js +28 -0
- package/dist/aun/aid/control-aid.js +67 -0
- package/dist/aun/aid/identity.js +20 -7
- package/dist/aun/aid/store.js +2 -2
- package/dist/aun/storage/download.js +1 -1
- package/dist/aun/storage/upload.js +13 -1
- package/dist/channels/aun.js +538 -325
- package/dist/channels/dingtalk.js +77 -140
- package/dist/channels/feishu.js +98 -151
- package/dist/channels/qqbot.js +75 -138
- package/dist/channels/wechat.js +75 -136
- package/dist/channels/wecom.js +75 -138
- package/dist/cli/agent.js +44 -13
- package/dist/cli/index.js +207 -46
- package/dist/cli/init-channel.js +38 -148
- package/dist/cli/init.js +192 -85
- package/dist/cli/model.js +1 -1
- package/dist/cli/stats.js +558 -0
- package/dist/cli/version.js +87 -0
- package/dist/cli/watch-msg.js +5 -2
- package/dist/config-store.js +48 -11
- package/dist/core/channel-loader.js +84 -82
- package/dist/core/command-handler.js +754 -172
- package/dist/core/daemon-file-cache.js +216 -0
- package/dist/core/evolagent-registry.js +4 -0
- package/dist/core/evolagent.js +28 -23
- package/dist/core/interaction-router.js +8 -0
- package/dist/core/message/command-handler-agent-control.js +215 -0
- package/dist/core/message/create-status.js +67 -0
- package/dist/core/message/im-renderer.js +35 -13
- package/dist/core/message/items-formatter.js +9 -1
- package/dist/core/message/message-bridge.js +52 -22
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-processor.js +336 -68
- package/dist/core/message/message-queue.js +15 -8
- package/dist/core/message/pending-hints.js +232 -0
- package/dist/core/message/response-depth.js +56 -0
- package/dist/core/model/model-catalog.js +1 -1
- package/dist/core/model/model-scope.js +40 -7
- package/dist/core/permission.js +9 -12
- package/dist/core/relation/peer-identity.js +16 -1
- package/dist/core/session/adapters/claude-session-file-adapter.js +48 -5
- package/dist/core/session/adapters/codex-session-file-adapter.js +4 -2
- package/dist/core/session/session-manager.js +27 -13
- package/dist/core/session/session-title.js +26 -0
- package/dist/core/stats/billing.js +151 -0
- package/dist/core/stats/budget.js +93 -0
- package/dist/core/stats/db.js +314 -0
- package/dist/core/stats/eck-vars.js +84 -0
- package/dist/core/stats/index.js +10 -0
- package/dist/core/stats/normalizer.js +78 -0
- package/dist/core/stats/query.js +760 -0
- package/dist/core/stats/writer.js +115 -0
- package/dist/core/trigger/manager.js +34 -0
- package/dist/core/trigger/parser.js +9 -3
- package/dist/core/trigger/scheduler.js +20 -17
- package/dist/{agents → eck}/kit-renderer.js +5 -1
- package/dist/{agents → eck}/manifest-engine.js +127 -35
- package/dist/{agents → eck}/message-renderer.js +26 -1
- package/dist/index.js +185 -8
- package/dist/ipc.js +22 -0
- package/dist/paths.js +7 -3
- package/dist/utils/cross-platform.js +23 -5
- package/dist/utils/ecweb-pair.js +20 -0
- package/dist/utils/stats.js +14 -0
- package/kits/docs/evolclaw/INDEX.md +3 -1
- package/kits/docs/evolclaw/fs-architecture.md +1215 -0
- package/kits/docs/evolclaw/fs.md +131 -0
- package/kits/docs/evolclaw/group-fs.md +209 -0
- package/kits/docs/evolclaw/stats.md +70 -0
- package/kits/docs/venues/aun-group.md +29 -6
- package/kits/docs/venues/group.md +5 -4
- package/kits/eck_manifest.json +12 -0
- package/kits/eck_message_manifest.json +30 -3
- package/kits/rules/05-venue.md +1 -1
- package/kits/templates/message-fragments/inject-default.md +2 -0
- package/kits/templates/message-fragments/item.md +1 -1
- package/kits/templates/system-fragments/response-depth.md +16 -0
- package/package.json +4 -4
- package/dist/agents/baseagent-normalize.js +0 -19
- package/dist/core/relation/peer-key.js +0 -16
- package/dist/utils/channel-helpers.js +0 -46
package/dist/channels/wecom.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import { logger } from '../utils/logger.js';
|
|
3
3
|
import { requireOptional } from '../utils/npm-ops.js';
|
|
4
|
-
import {
|
|
4
|
+
import { resolveShowActivities, showActivitiesPolicy } from '../core/channel-loader.js';
|
|
5
5
|
import { formatItemsAsText } from '../core/message/items-formatter.js';
|
|
6
6
|
// ── WecomChannel ───────────────────────────────────────────────────────────────
|
|
7
7
|
export class WecomChannel {
|
|
@@ -465,143 +465,80 @@ function isValidCredential(value) {
|
|
|
465
465
|
}
|
|
466
466
|
export class WecomChannelPlugin {
|
|
467
467
|
name = 'wecom';
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
await channel.sendMessage(channelId, payload.text);
|
|
506
|
-
return;
|
|
507
|
-
case 'result.file':
|
|
508
|
-
await channel.sendFile(channelId, payload.filePath);
|
|
509
|
-
return;
|
|
510
|
-
case 'result.image':
|
|
511
|
-
await channel.sendImage(channelId, payload.data);
|
|
512
|
-
return;
|
|
513
|
-
case 'activity.batch': {
|
|
514
|
-
const filtered = payload.items.filter((i) => !(i.kind === 'tool_result' && i.ok));
|
|
515
|
-
const text = formatItemsAsText(filtered);
|
|
516
|
-
if (text)
|
|
517
|
-
await channel.sendMessage(channelId, text);
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
case 'interaction':
|
|
521
|
-
if (payload.fallbackText)
|
|
522
|
-
await channel.sendMessage(channelId, payload.fallbackText);
|
|
523
|
-
return;
|
|
524
|
-
case 'status.started':
|
|
525
|
-
case 'status.completed':
|
|
526
|
-
case 'status.interrupted':
|
|
527
|
-
case 'status.error':
|
|
528
|
-
case 'status.timeout':
|
|
529
|
-
case 'status.progress':
|
|
530
|
-
case 'custom':
|
|
531
|
-
return;
|
|
532
|
-
default:
|
|
533
|
-
logger.warn(`[WeCom] Unhandled payload kind: ${payload.kind}`);
|
|
468
|
+
async createInstance(inst, ctx) {
|
|
469
|
+
if (inst.enabled === false)
|
|
470
|
+
return null;
|
|
471
|
+
if (!isValidCredential(inst.botId) || !isValidCredential(inst.secret))
|
|
472
|
+
return null;
|
|
473
|
+
const channel = new WecomChannel({
|
|
474
|
+
botId: inst.botId,
|
|
475
|
+
secret: inst.secret,
|
|
476
|
+
});
|
|
477
|
+
const mode = resolveShowActivities(inst);
|
|
478
|
+
const adapter = {
|
|
479
|
+
channelName: inst.name,
|
|
480
|
+
channelKey: inst.name,
|
|
481
|
+
capabilities: { file: true, image: true, interaction: false, markdown: true, thought: false, status: false, thread: false },
|
|
482
|
+
send: async (envelope, payload) => {
|
|
483
|
+
const channelId = envelope.channelId;
|
|
484
|
+
switch (payload.kind) {
|
|
485
|
+
case 'result.text':
|
|
486
|
+
case 'command.result':
|
|
487
|
+
case 'command.error':
|
|
488
|
+
case 'system.notice':
|
|
489
|
+
case 'system.error':
|
|
490
|
+
case 'result.error':
|
|
491
|
+
await channel.sendMessage(channelId, payload.text);
|
|
492
|
+
return;
|
|
493
|
+
case 'result.file':
|
|
494
|
+
await channel.sendFile(channelId, payload.filePath);
|
|
495
|
+
return;
|
|
496
|
+
case 'result.image':
|
|
497
|
+
await channel.sendImage(channelId, payload.data);
|
|
498
|
+
return;
|
|
499
|
+
case 'activity.batch': {
|
|
500
|
+
const filtered = payload.items.filter((i) => !(i.kind === 'tool_result' && i.ok));
|
|
501
|
+
const text = formatItemsAsText(filtered);
|
|
502
|
+
if (text)
|
|
503
|
+
await channel.sendMessage(channelId, text);
|
|
504
|
+
return;
|
|
534
505
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
channelType: 'wecom',
|
|
573
|
-
adapter,
|
|
574
|
-
channel,
|
|
575
|
-
policy,
|
|
576
|
-
options,
|
|
577
|
-
connect: () => channel.connect(),
|
|
578
|
-
disconnect: () => channel.disconnect(),
|
|
579
|
-
onProjectPathRequest: () => Promise.resolve(config.projects?.defaultPath || process.cwd()),
|
|
580
|
-
registerBridge(bridge, channelType) {
|
|
581
|
-
bridge.register(adapter.channelName, (handler) => channel.onMessage(async (event) => {
|
|
582
|
-
handler({
|
|
583
|
-
channel: adapter.channelName,
|
|
584
|
-
channelType,
|
|
585
|
-
channelId: event.channelId,
|
|
586
|
-
selfAID: inst.agentName,
|
|
587
|
-
content: event.content,
|
|
588
|
-
images: event.images,
|
|
589
|
-
chatType: event.chatType || 'private',
|
|
590
|
-
peerId: event.peerId || '',
|
|
591
|
-
peerName: event.peerName,
|
|
592
|
-
messageId: event.messageId,
|
|
593
|
-
});
|
|
594
|
-
}), (channelId, text) => channel.sendMessage(channelId, text), adapter, channelType);
|
|
595
|
-
},
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
return result;
|
|
599
|
-
}
|
|
600
|
-
async createChannel(config) {
|
|
601
|
-
const instances = await this.createChannels(config);
|
|
602
|
-
if (instances.length === 0) {
|
|
603
|
-
throw new Error('WeCom config missing or invalid');
|
|
604
|
-
}
|
|
605
|
-
return instances[0];
|
|
506
|
+
case 'interaction':
|
|
507
|
+
if (payload.fallbackText)
|
|
508
|
+
await channel.sendMessage(channelId, payload.fallbackText);
|
|
509
|
+
return;
|
|
510
|
+
default: return;
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
};
|
|
514
|
+
const policy = {
|
|
515
|
+
canSwitchProject: (_, identity) => identity === 'owner' || identity === 'admin',
|
|
516
|
+
canListProjects: (_, identity) => identity === 'owner' || identity === 'admin',
|
|
517
|
+
canCreateSession: () => true,
|
|
518
|
+
canDeleteSession: () => true,
|
|
519
|
+
canImportCliSession: (_, identity) => identity === 'owner' || identity === 'admin',
|
|
520
|
+
messagePrefix: (chatType, peerName) => (chatType === 'group' && peerName) ? `[${peerName}] ` : '',
|
|
521
|
+
showMiddleResult: (chatType, identity) => showActivitiesPolicy(mode, chatType, identity),
|
|
522
|
+
showIdleMonitor: (chatType, identity) => showActivitiesPolicy(mode, chatType, identity),
|
|
523
|
+
accumulateErrors: () => true,
|
|
524
|
+
};
|
|
525
|
+
return {
|
|
526
|
+
channelType: 'wecom', adapter, channel,
|
|
527
|
+
policy,
|
|
528
|
+
options: { fileMarkerPattern: /\[SEND_FILE:(?:(\w+):)?([^\]]+)\]/g, supportsImages: true, flushDelay: inst.flushDelay },
|
|
529
|
+
connect: () => channel.connect(),
|
|
530
|
+
disconnect: () => channel.disconnect(),
|
|
531
|
+
onProjectPathRequest: () => Promise.resolve(ctx.defaultProjectPath),
|
|
532
|
+
registerBridge(bridge, channelType) {
|
|
533
|
+
bridge.register(adapter.channelName, (handler) => channel.onMessage(async (event) => {
|
|
534
|
+
handler({
|
|
535
|
+
channel: adapter.channelName, channelType, channelId: event.channelId,
|
|
536
|
+
selfAID: ctx.agentName, content: event.content, images: event.images,
|
|
537
|
+
chatType: event.chatType || 'private', peerId: event.peerId || '',
|
|
538
|
+
peerName: event.peerName, messageId: event.messageId,
|
|
539
|
+
});
|
|
540
|
+
}), (channelId, text) => channel.sendMessage(channelId, text), adapter, channelType);
|
|
541
|
+
},
|
|
542
|
+
};
|
|
606
543
|
}
|
|
607
544
|
}
|
package/dist/cli/agent.js
CHANGED
|
@@ -7,12 +7,12 @@ import { ipcQuery } from '../ipc.js';
|
|
|
7
7
|
import { CONFIG_SCHEMA_VERSION } from '../types.js';
|
|
8
8
|
import { isValidChannelName } from '../core/channel-loader.js';
|
|
9
9
|
import { commandExists } from '../utils/cross-platform.js';
|
|
10
|
-
import {
|
|
10
|
+
import { getCodexAppServerAvailability, isCodexAppServerAvailable } from '../agents/codex-runner.js';
|
|
11
11
|
// ==================== Helpers ====================
|
|
12
12
|
const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
|
|
13
13
|
function isBaseagentAvailable(baseagent) {
|
|
14
14
|
if (baseagent === 'codex')
|
|
15
|
-
return
|
|
15
|
+
return isCodexAppServerAvailable();
|
|
16
16
|
return commandExists(baseagent);
|
|
17
17
|
}
|
|
18
18
|
function detectAvailableBaseagents() {
|
|
@@ -313,7 +313,7 @@ export async function agentCreateInteractive(opts = {}) {
|
|
|
313
313
|
// Baseagent
|
|
314
314
|
const available = detectAvailableBaseagents();
|
|
315
315
|
if (available.length === 0) {
|
|
316
|
-
return { ok: false, error: `No usable baseagent detected. Install claude/gemini CLI or
|
|
316
|
+
return { ok: false, error: `No usable baseagent detected. Install claude/gemini CLI or codex CLI with app-server.` };
|
|
317
317
|
}
|
|
318
318
|
const defaultBa = pickDefaultBaseagent(available);
|
|
319
319
|
let baseagent;
|
|
@@ -450,26 +450,35 @@ export async function agentCreateInteractive(opts = {}) {
|
|
|
450
450
|
export async function agentCreateNonInteractive(opts) {
|
|
451
451
|
const p = resolvePaths();
|
|
452
452
|
const { isValidAid, aidCreate } = await import('../aun/aid/index.js');
|
|
453
|
+
opts.onPhase?.('validating', 'begin');
|
|
454
|
+
/** 校验失败:透出 failed 进度并返回原结构(控制流不变)。 */
|
|
455
|
+
const failValidating = (error) => {
|
|
456
|
+
opts.onPhase?.('validating', 'failed', error);
|
|
457
|
+
return { ok: false, error };
|
|
458
|
+
};
|
|
453
459
|
if (!isValidAid(opts.aid)) {
|
|
454
|
-
return
|
|
460
|
+
return failValidating(`Invalid AID "${opts.aid}": must be a valid multi-level domain (e.g. mybot.agentid.pub)`);
|
|
455
461
|
}
|
|
456
462
|
const agentDirPath = path.join(p.agentsDir, opts.aid);
|
|
457
463
|
const configExists = fs.existsSync(path.join(agentDirPath, 'config.json'));
|
|
458
464
|
if (configExists && !opts.force) {
|
|
459
|
-
return
|
|
465
|
+
return failValidating(`Agent "${opts.aid}" already exists: ${agentDirPath}/config.json (use --force to overwrite)`);
|
|
460
466
|
}
|
|
461
467
|
// Baseagent
|
|
462
468
|
const available = detectAvailableBaseagents();
|
|
463
469
|
if (available.length === 0) {
|
|
464
|
-
return
|
|
470
|
+
return failValidating(`No usable baseagent detected. Install claude/gemini CLI or codex CLI with app-server.`);
|
|
465
471
|
}
|
|
466
472
|
let baseagent;
|
|
467
473
|
if (opts.baseagent) {
|
|
468
474
|
if (!BASEAGENT_CANDIDATES.includes(opts.baseagent)) {
|
|
469
|
-
return
|
|
475
|
+
return failValidating(`Invalid baseagent: ${opts.baseagent} (options: ${BASEAGENT_CANDIDATES.join('/')})`);
|
|
470
476
|
}
|
|
471
477
|
if (!available.includes(opts.baseagent)) {
|
|
472
|
-
|
|
478
|
+
const reason = opts.baseagent === 'codex'
|
|
479
|
+
? getCodexAppServerAvailability().reason
|
|
480
|
+
: undefined;
|
|
481
|
+
return failValidating(reason || `${opts.baseagent} is not available in the current environment (available: ${available.join('/')})`);
|
|
473
482
|
}
|
|
474
483
|
baseagent = opts.baseagent;
|
|
475
484
|
}
|
|
@@ -477,20 +486,22 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
477
486
|
baseagent = pickDefaultBaseagent(available);
|
|
478
487
|
}
|
|
479
488
|
if (!path.isAbsolute(opts.project)) {
|
|
480
|
-
return
|
|
489
|
+
return failValidating(`--project must be absolute: ${opts.project}`);
|
|
481
490
|
}
|
|
482
491
|
if (!fs.existsSync(opts.project)) {
|
|
483
492
|
try {
|
|
484
493
|
fs.mkdirSync(opts.project, { recursive: true });
|
|
485
494
|
}
|
|
486
495
|
catch (e) {
|
|
487
|
-
return
|
|
496
|
+
return failValidating(`Failed to create ${opts.project}: ${e?.message || e}`);
|
|
488
497
|
}
|
|
489
498
|
}
|
|
490
499
|
if (opts.owner && !isValidAid(opts.owner)) {
|
|
491
|
-
return
|
|
500
|
+
return failValidating(`Invalid owner: ${opts.owner}`);
|
|
492
501
|
}
|
|
502
|
+
opts.onPhase?.('validating', 'done');
|
|
493
503
|
// Register AID
|
|
504
|
+
opts.onPhase?.('registering_aid', 'begin');
|
|
494
505
|
let aidCreated = false;
|
|
495
506
|
try {
|
|
496
507
|
const result = await aidCreate(opts.aid);
|
|
@@ -499,9 +510,12 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
499
510
|
}
|
|
500
511
|
catch { /* ignore */ }
|
|
501
512
|
aidCreated = !result.alreadyExisted;
|
|
513
|
+
opts.onPhase?.('registering_aid', 'done', aidCreated ? 'created' : 'existed');
|
|
502
514
|
}
|
|
503
515
|
catch (e) {
|
|
504
|
-
|
|
516
|
+
const error = `AID creation failed: ${e?.message || e}`;
|
|
517
|
+
opts.onPhase?.('registering_aid', 'failed', error);
|
|
518
|
+
return { ok: false, error };
|
|
505
519
|
}
|
|
506
520
|
// Force 模式下若 agent 已存在且已 initialized,保留该状态(避免重复发欢迎)
|
|
507
521
|
let preservedInitialized = false;
|
|
@@ -526,9 +540,12 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
526
540
|
chatmode: { ...DEFAULT_CHATMODE },
|
|
527
541
|
dispatch: DEFAULT_DISPATCH,
|
|
528
542
|
};
|
|
543
|
+
opts.onPhase?.('config_saved', 'begin');
|
|
529
544
|
saveAgent(agentConfig);
|
|
530
545
|
ensureAgentDirSkeleton(opts.aid);
|
|
546
|
+
opts.onPhase?.('config_saved', 'done');
|
|
531
547
|
// Generate and upload agent.md
|
|
548
|
+
opts.onPhase?.('uploading_agentmd', 'begin');
|
|
532
549
|
let agentmdUploaded = false;
|
|
533
550
|
try {
|
|
534
551
|
const { buildInitialAgentMd, agentmdPut } = await import('../aun/aid/index.js');
|
|
@@ -550,6 +567,7 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
550
567
|
await new Promise(r => setTimeout(r, RETRY_DELAY_MS));
|
|
551
568
|
await agentmdPut(content, { aid: opts.aid, aunPath });
|
|
552
569
|
agentmdUploaded = true;
|
|
570
|
+
opts.onPhase?.('uploading_agentmd', 'done');
|
|
553
571
|
break;
|
|
554
572
|
}
|
|
555
573
|
catch (e) {
|
|
@@ -559,11 +577,13 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
559
577
|
if (!agentmdUploaded) {
|
|
560
578
|
console.warn(`⚠ agent.md upload failed: ${lastError?.message || lastError}`);
|
|
561
579
|
console.warn(` Retry later with: evolclaw aid agentmd put ${opts.aid}`);
|
|
580
|
+
opts.onPhase?.('uploading_agentmd', 'warn', `upload failed: ${lastError?.message || lastError}`);
|
|
562
581
|
}
|
|
563
582
|
await new Promise(r => setTimeout(r, 0));
|
|
564
583
|
}
|
|
565
584
|
catch (e) {
|
|
566
585
|
console.warn(`⚠ agent.md generation failed: ${e?.message || e}`);
|
|
586
|
+
opts.onPhase?.('uploading_agentmd', 'warn', `generation failed: ${e?.message || e}`);
|
|
567
587
|
}
|
|
568
588
|
// Attempt hot-load via IPC (if daemon is running).
|
|
569
589
|
// Cold-starting a new agent (connecting AUN WebSocket) routinely takes
|
|
@@ -571,16 +591,24 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
571
591
|
// report while the daemon actually finishes bringing the agent online.
|
|
572
592
|
let hotLoaded = false;
|
|
573
593
|
let hotLoadError;
|
|
594
|
+
opts.onPhase?.('hot_loading', 'begin');
|
|
574
595
|
try {
|
|
575
596
|
const ipcResult = await ipcQuery(p.socket, { type: 'evolagent.load', aid: opts.aid }, 30_000);
|
|
576
597
|
if (ipcResult?.ok) {
|
|
577
598
|
hotLoaded = true;
|
|
599
|
+
opts.onPhase?.('hot_loading', 'done');
|
|
578
600
|
}
|
|
579
601
|
else if (ipcResult) {
|
|
580
602
|
hotLoadError = ipcResult.error;
|
|
603
|
+
opts.onPhase?.('hot_loading', 'warn', hotLoadError);
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
opts.onPhase?.('hot_loading', 'warn', 'daemon not running');
|
|
581
607
|
}
|
|
582
608
|
}
|
|
583
|
-
catch {
|
|
609
|
+
catch {
|
|
610
|
+
opts.onPhase?.('hot_loading', 'warn', 'daemon not running'); /* daemon not running */
|
|
611
|
+
}
|
|
584
612
|
return {
|
|
585
613
|
ok: true,
|
|
586
614
|
aid: opts.aid,
|
|
@@ -858,6 +886,9 @@ export async function agentDelete(aid, purge = false) {
|
|
|
858
886
|
}
|
|
859
887
|
else {
|
|
860
888
|
fs.unlinkSync(configPath);
|
|
889
|
+
// 清理构建进度文件(非 purge 删除只移除 config.json,需显式清理 create-status.json)
|
|
890
|
+
const { removeCreateStatus } = await import('../core/message/create-status.js');
|
|
891
|
+
removeCreateStatus(agentDir);
|
|
861
892
|
}
|
|
862
893
|
// Trigger resync so daemon drops the agent
|
|
863
894
|
try {
|