evolcore 0.0.26 → 0.0.28
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 +36 -0
- package/bin/codex-managed-acl.ps1 +43 -0
- package/dist/agents/baseagent-availability.js +68 -0
- package/dist/agents/baseagent.js +10 -5
- package/dist/agents/claude-runner.js +123 -22
- package/dist/agents/codex/app-server-client.js +70 -26
- package/dist/agents/codex/catalog.js +7 -1
- package/dist/agents/codex-runner.js +363 -421
- package/dist/agents/ecagent-runner.js +170 -25
- package/dist/agents/gemini-runner.js +6 -0
- package/dist/agents/runner-types.js +50 -2
- package/dist/aun/aid/agentmd.js +73 -31
- package/dist/aun/aid/client.js +1 -1
- package/dist/aun/aid/control-aid.js +180 -1
- package/dist/aun/aid/identity.js +3 -3
- package/dist/aun/group/history.js +303 -0
- package/dist/aun/group/identity.js +43 -0
- package/dist/aun/group/index.js +5 -0
- package/dist/aun/{msg/group.js → group/operations.js} +161 -38
- package/dist/aun/{menu-client.js → menu/client.js} +13 -7
- package/dist/aun/menu/index.js +2 -0
- package/dist/aun/menu/transport.js +49 -0
- package/dist/aun/msg/index.js +2 -1
- package/dist/aun/msg/managed-operation.js +84 -18
- package/dist/aun/msg/mention-schema.js +51 -0
- package/dist/aun/msg/p2p.js +13 -8
- package/dist/aun/msg/upload.js +43 -88
- package/dist/aun/outbox.js +29 -7
- package/dist/aun/rpc/client.js +1 -0
- package/dist/aun/storage/client.js +39 -50
- package/dist/channels/aun.js +544 -239
- package/dist/channels/daemon.js +10 -6
- package/dist/cli/agent-command.js +108 -6
- package/dist/cli/agent-create.js +515 -2
- package/dist/cli/agent.js +109 -8
- package/dist/cli/aun-commands.js +191 -42
- package/dist/cli/config.js +8 -5
- package/dist/cli/contact.js +2 -2
- package/dist/cli/ctl-command.js +2 -2
- package/dist/cli/daemon-commands.js +111 -162
- package/dist/cli/diag.js +3 -3
- package/dist/cli/fs-command.js +3 -3
- package/dist/cli/handoff-command.js +6 -6
- package/dist/cli/index.js +8 -2
- package/dist/cli/init.js +34 -1
- package/dist/cli/managed-command-guard.js +2 -1
- package/dist/cli/menu-client.js +13 -5
- package/dist/cli/model.js +3 -3
- package/dist/cli/queue-command.js +2 -2
- package/dist/cli/response.js +2 -2
- package/dist/cli/restart-monitor.js +81 -19
- package/dist/cli/task-command.js +59 -0
- package/dist/cli/task-context.js +97 -49
- package/dist/cli/trigger-command.js +20 -10
- package/dist/config/builtin-roles.js +10 -0
- package/dist/config/config-field-policy.js +11 -0
- package/dist/config/config-manager.js +32 -4
- package/dist/config/config-operation-service.js +20 -5
- package/dist/config/contact-book-store.js +1 -1
- package/dist/config/contact-book.js +1 -1
- package/dist/config/contact-operation-service.js +1 -1
- package/dist/config/peer-role-resolver.js +1 -1
- package/dist/config/resolved-config-op.js +3 -0
- package/dist/config-store.js +1 -1
- package/dist/core/agent-application-service.js +5 -0
- package/dist/core/audit/event-key.js +17 -2
- package/dist/core/audit/log-integrity.js +34 -8
- package/dist/core/auth/agent-delegation.js +48 -14
- package/dist/core/auth/auth-gateway.js +2 -0
- package/dist/core/auth/authorization-audit.js +34 -38
- package/dist/core/auth/operation-authorizer.js +67 -5
- package/dist/core/auth/operation-catalog.js +110 -0
- package/dist/core/auth/remote-access-store.js +115 -9
- package/dist/core/bootstrap-messages.js +66 -7
- package/dist/core/bootstrap-service.js +110 -19
- package/dist/core/command/agent-control.js +88 -7
- package/dist/core/command/agent-storage-menu.js +443 -0
- package/dist/core/command/cli-intent-parser.js +19 -0
- package/dist/core/command/command-handler.js +105 -40
- package/dist/core/command/data-root-resolver.js +273 -0
- package/dist/core/command/diag-service.js +292 -27
- package/dist/core/command/group-menu.js +7 -2
- package/dist/core/command/menu-catalog.js +34 -4
- package/dist/core/command/menu-handler.js +364 -96
- package/dist/core/command/menu-protocol.js +43 -6
- package/dist/core/command/role-menu.js +2 -2
- package/dist/core/command/slash-handler.js +61 -37
- package/dist/core/event-catalog.js +4 -0
- package/dist/core/evolagent-registry.js +28 -2
- package/dist/core/group/invite-service.js +924 -0
- package/dist/core/interaction-router.js +22 -8
- package/dist/core/message/im-renderer.js +94 -16
- package/dist/core/message/message-bridge.js +140 -13
- package/dist/core/message/message-log.js +5 -3
- package/dist/core/message/message-queue.js +73 -41
- package/dist/core/message/response-engine.js +729 -118
- package/dist/core/permission/approval-gateway.js +36 -3
- package/dist/core/permission/ec-command-parser.js +76 -36
- package/dist/core/permission/protected-paths.js +134 -16
- package/dist/core/permission/sandbox-runtime.js +72 -3
- package/dist/core/permission/tool-error-code.js +15 -0
- package/dist/core/permission/tool-policy.js +8 -8
- package/dist/core/relation/peer-identity.js +57 -6
- package/dist/core/relation/shared-data.js +106 -0
- package/dist/core/role/runtime-policy.js +64 -0
- package/dist/core/runtime-lock.js +10 -26
- package/dist/core/session/runner-task-history.js +170 -0
- package/dist/core/session/session-manager.js +38 -6
- package/dist/core/session/session-mapper.js +41 -0
- package/dist/core/session/session-turn-coordinator.js +37 -7
- package/dist/core/session/session-turns.js +48 -7
- package/dist/core/task/task-recovery-service.js +176 -0
- package/dist/core/task/task-resume-operation.js +32 -0
- package/dist/eck/group-rules-sync.js +5 -3
- package/dist/eck/kit-renderer.js +1 -0
- package/dist/index.js +322 -207
- package/dist/ipc.js +141 -15
- package/dist/paths.js +17 -4
- package/dist/product.js +3 -0
- package/dist/trigger/event-source.js +19 -0
- package/dist/trigger/feedback.js +233 -40
- package/dist/trigger/parser.js +55 -5
- package/dist/trigger/patch.js +9 -0
- package/dist/trigger/scheduler.js +30 -4
- package/dist/trigger/validation.js +20 -3
- package/dist/utils/atomic-write.js +98 -0
- package/dist/utils/cross-platform.js +87 -16
- package/dist/utils/ecweb-utils.js +1 -0
- package/dist/utils/error-utils.js +40 -2
- package/dist/utils/logger.js +23 -13
- package/dist/utils/npm-ops.js +119 -4
- package/dist/utils/package-version-info.js +244 -0
- package/dist/utils/tool-summary.js +59 -3
- package/dist/utils/welcome.js +174 -1
- package/dist/utils/windows-shell-trust.js +37 -0
- package/ecagent/dist/harness/agent-harness.js +3 -0
- package/ecagent/dist/harness/session/jsonl-storage.js +21 -2
- package/kits/docs/INDEX.md +0 -6
- package/kits/docs/channels/aun.md +23 -2
- package/kits/docs/channels/feishu.md +1 -1
- package/kits/docs/context-assembly.md +29 -17
- package/kits/docs/evolcore/INDEX.md +8 -3
- package/kits/docs/evolcore/agent-create.md +39 -7
- package/kits/docs/evolcore/agent.md +33 -1
- package/kits/docs/evolcore/aid.md +9 -1
- package/kits/docs/evolcore/config.md +40 -1
- package/kits/docs/evolcore/group-collaboration.md +1 -1
- package/kits/docs/evolcore/group.md +117 -2
- package/kits/docs/evolcore/menu-client.md +16 -0
- package/kits/docs/evolcore/msg.md +3 -0
- package/kits/docs/evolcore/storage.md +3 -0
- package/kits/docs/evolcore/task.md +14 -0
- package/kits/docs/evolcore/trigger.md +51 -3
- package/kits/docs/venues/group.md +5 -0
- package/kits/eck_manifest.json +27 -0
- package/kits/rules/01-overview.md +11 -7
- package/kits/rules/04-relation.md +2 -1
- package/kits/rules/05-venue.md +1 -1
- package/kits/rules/06-channel.md +6 -4
- package/kits/schemas/agent-config.schema.12.json +25 -1
- package/kits/schemas/daemon.schema.6.json +2 -2
- package/kits/schemas/defaults.schema.5.json +1 -1
- package/kits/schemas/relation-config.schema.1.json +1 -1
- package/kits/schemas/relation-config.schema.5.json +1 -1
- package/kits/schemas/role-config.schema.1.json +14 -0
- package/kits/templates/roles/member.json +5 -0
- package/kits/templates/roles/visitor.json +5 -0
- package/kits/templates/system-fragments/baseagent.md +1 -1
- package/kits/templates/system-fragments/bootstrap.md +26 -9
- package/kits/templates/system-fragments/channel.md +8 -44
- package/kits/templates/system-fragments/commands.md +10 -2
- package/kits/templates/system-fragments/group-unread-history.md +7 -0
- package/kits/templates/system-fragments/reply.md +56 -0
- package/package.json +7 -3
- package/dist/aun/group-identity.js +0 -9
- /package/dist/aun/{group-fs-download.js → group/fs-download.js} +0 -0
- /package/dist/aun/{msg/group-index.js → group/index-rpc.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { CodexSessionFileAdapter } from './core/session/adapters/codex-session-f
|
|
|
14
14
|
import { GeminiSessionFileAdapter } from './core/session/adapters/gemini-session-file-adapter.js';
|
|
15
15
|
import { EcagentSessionFileAdapter } from './core/session/adapters/ecagent-session-file-adapter.js';
|
|
16
16
|
import { autoMigrateIfNeeded, loadDefaults, loadAllAgents, migrateIdentitiesIfNeeded, loadDaemonConfig, initializeEckSnapshotsConfig, isFullAccessEnabled } from './config-store.js';
|
|
17
|
+
import { migrateRelationSharedDirectories } from './core/relation/shared-data.js';
|
|
17
18
|
import { DEFAULT_ECWEB_PORT, ecwebService } from './config/daemon-services.js';
|
|
18
19
|
import { ConfigTarget, initConfigManager, onConfigWrite, read as readConfig, shouldFailFastForMissingOwners } from './config/config-manager.js';
|
|
19
20
|
import { ensureRoleConfigV4OnStartup, ensureRoleConfigV5OnStartup } from './config/role-migration-startup.js';
|
|
@@ -53,6 +54,8 @@ import { BootstrapService, completeBootstrapWithWelcome } from './core/bootstrap
|
|
|
53
54
|
import { postBootstrapWelcomeOperationId } from './core/bootstrap-messages.js';
|
|
54
55
|
import { MessageCache } from './core/message/message-cache.js';
|
|
55
56
|
import { CommandHandler, isProcessLevelOwner } from './core/command/command-handler.js';
|
|
57
|
+
import { executeLocalInitializationCommand, AgentInitializationService, hasSuppliedInitialization, readInitialization, parseInitializationArgs, parseAgentWelcomeArgs, resolveInitializationPlan, } from './cli/agent-create.js';
|
|
58
|
+
import { loadAgent } from './config-store.js';
|
|
56
59
|
import { AgentApplicationService } from './core/agent-application-service.js';
|
|
57
60
|
import { EventBus } from './core/event-bus.js';
|
|
58
61
|
import { eventPatternIncludesInternal, getEventCatalog } from './core/event-catalog.js';
|
|
@@ -60,12 +63,13 @@ import { StatsCollector } from './utils/stats.js';
|
|
|
60
63
|
import { AidStatsCollector } from './utils/stats.js';
|
|
61
64
|
import { PermissionGateway } from './core/permission/approval-gateway.js';
|
|
62
65
|
import { InteractionRouter, registerAdapterInteractions } from './core/interaction-router.js';
|
|
66
|
+
import { GroupInviteReviewService } from './core/group/invite-service.js';
|
|
63
67
|
import { AgentDelegationRegistry, authorizeDelegatedAunMsgSend, hasTrustedFullAccessDelegation, trustedExecutionIdentityInput, } from './core/auth/agent-delegation.js';
|
|
64
68
|
import { authorizeOperation, buildAuthSubject, canApprovePersistentFullAccessTrigger, isCrossAgentTriggerOperationAllowed, } from './core/auth/auth-gateway.js';
|
|
65
69
|
import { authorizationDenialData, formatAuthorizationDenial } from './core/auth/authorization-denial.js';
|
|
66
70
|
import { auditFullAccessEvent } from './core/auth/authorization-audit.js';
|
|
67
71
|
import { parsePeerKey } from './core/relation/peer-identity.js';
|
|
68
|
-
import { isHClassPath } from './core/permission/protected-paths.js';
|
|
72
|
+
import { isHClassPath, isSameOrDescendant } from './core/permission/protected-paths.js';
|
|
69
73
|
import { ChannelLoader, tryParseChannelKey } from './core/channel-loader.js';
|
|
70
74
|
import { AgentLoader } from './core/baseagent-loader.js';
|
|
71
75
|
import { EvolAgentRegistry } from './core/evolagent-registry.js';
|
|
@@ -73,6 +77,8 @@ import { createRunnerReloadTransaction, disposeAgentInstances } from './core/run
|
|
|
73
77
|
import { AgentReloadBusyError, AgentReloadCoordinator } from './core/agent-reload-coordinator.js';
|
|
74
78
|
import { buildReloadHooks } from './core/channel-loader.js';
|
|
75
79
|
import { IpcServer } from './ipc.js';
|
|
80
|
+
import { executeTaskResume } from './core/task/task-resume-operation.js';
|
|
81
|
+
import { TASK_RECOVERY_PROMPT } from './core/task/task-recovery-service.js';
|
|
76
82
|
import { logger, setLogLevel } from './utils/logger.js';
|
|
77
83
|
import { remoteAccessService } from './core/auth/remote-access-store.js';
|
|
78
84
|
import { DiagService, executeDiagIpc } from './core/command/diag-service.js';
|
|
@@ -97,11 +103,10 @@ import { atomicWriteJson } from './core/session/session-fs-store.js';
|
|
|
97
103
|
import { DAEMON_RUNTIME_EPOCH_ENV, ensureProcessManagedTempDir } from './cli/task-context.js';
|
|
98
104
|
import { appendMessageLog, buildOutboundEntry, classifyAunPayloadForLog } from './core/message/message-log.js';
|
|
99
105
|
import { normalizeAunMentionEntries } from './aun/msg/mention-schema.js';
|
|
100
|
-
import {
|
|
106
|
+
import { sanitizeMenuLogValue } from './core/command/menu-protocol.js';
|
|
101
107
|
import fs from 'fs';
|
|
102
108
|
import crypto from 'crypto';
|
|
103
109
|
import { fileURLToPath } from 'url';
|
|
104
|
-
import * as platform from './utils/cross-platform.js';
|
|
105
110
|
const controlMenuDeduper = new MenuRequestDeduper();
|
|
106
111
|
/** 出站 payload 摘要(用于 channel-out.log) */
|
|
107
112
|
function summarizeOutboundPayload(payload) {
|
|
@@ -365,160 +370,23 @@ function seedUpgradeCheckTrigger(manager, owner) {
|
|
|
365
370
|
fs.mkdirSync(dir, { recursive: true });
|
|
366
371
|
const scriptPath = path.join(dir, scriptName);
|
|
367
372
|
const packageRoot = getPackageRoot();
|
|
368
|
-
|
|
369
|
-
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
370
|
-
const devMode = fs.existsSync(path.join(packageRoot, 'src', 'index.ts'));
|
|
371
|
-
// Resolve the launch argv at generation time: in a checkout this points the
|
|
372
|
-
// monitor at src/ through tsx, so a `npm run build` that wipes dist/ cannot
|
|
373
|
-
// take the watchdog down with it.
|
|
374
|
-
const monitorEntry = platform.resolveCliEntry(packageRoot);
|
|
375
|
-
const stageParent = path.join(resolvePaths().root, 'data', 'monitor-stage');
|
|
373
|
+
// Keep this generated script check-only. It never starts a monitor or runs npm install.
|
|
376
374
|
fs.writeFileSync(scriptPath, `#!/usr/bin/env node
|
|
377
|
-
const
|
|
378
|
-
const
|
|
379
|
-
const { existsSync, readFileSync } = fs;
|
|
380
|
-
const { spawn } = require('node:child_process');
|
|
381
|
-
|
|
382
|
-
const CLI_PATH = ${JSON.stringify(monitorEntry.entry)};
|
|
383
|
-
const CLI_ARGS = ${JSON.stringify(monitorEntry.args)};
|
|
384
|
-
const PACKAGE_ROOT = ${JSON.stringify(packageRoot)};
|
|
385
|
-
const STAGE_PARENT = ${JSON.stringify(stageParent)};
|
|
386
|
-
const PACKAGE_JSON = ${JSON.stringify(packageJsonPath)};
|
|
387
|
-
const PACKAGE_NAME = ${JSON.stringify(MAIN_PACKAGE_NAME)};
|
|
388
|
-
const DEV_MODE = ${devMode ? 'true' : 'false'};
|
|
389
|
-
|
|
390
|
-
function emit(outcome, text) {
|
|
391
|
-
process.stdout.write(JSON.stringify({ outcome, text, files: [] }));
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
function compareVersions(a, b) {
|
|
395
|
-
const pa = a.split('-')[0].split('.').map(Number);
|
|
396
|
-
const pb = b.split('-')[0].split('.').map(Number);
|
|
397
|
-
const count = Math.max(pa.length, pb.length);
|
|
398
|
-
for (let i = 0; i < count; i += 1) {
|
|
399
|
-
const av = Number.isFinite(pa[i]) ? pa[i] : 0;
|
|
400
|
-
const bv = Number.isFinite(pb[i]) ? pb[i] : 0;
|
|
401
|
-
if (av < bv) return -1;
|
|
402
|
-
if (av > bv) return 1;
|
|
403
|
-
}
|
|
404
|
-
return 0;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
async function latestVersion() {
|
|
408
|
-
const controller = new AbortController();
|
|
409
|
-
const timer = setTimeout(() => controller.abort(), 10_000);
|
|
410
|
-
try {
|
|
411
|
-
const response = await fetch('https://registry.npmjs.org/' + encodeURIComponent(PACKAGE_NAME) + '/latest', {
|
|
412
|
-
signal: controller.signal,
|
|
413
|
-
headers: { Accept: 'application/json' },
|
|
414
|
-
});
|
|
415
|
-
if (!response.ok) return null;
|
|
416
|
-
const data = await response.json();
|
|
417
|
-
return typeof data.version === 'string' ? data.version : null;
|
|
418
|
-
} finally {
|
|
419
|
-
clearTimeout(timer);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
375
|
+
const { pathToFileURL } = require('node:url');
|
|
376
|
+
const entry = ${JSON.stringify(path.join(packageRoot, 'dist', 'utils', 'package-version-info.js'))};
|
|
423
377
|
async function main() {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
} catch {
|
|
433
|
-
emit('error', 'failed to read local ec version');
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
if (typeof localVersion !== 'string' || !localVersion) {
|
|
437
|
-
emit('error', 'failed to read local ec version');
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
let remoteVersion;
|
|
442
|
-
try {
|
|
443
|
-
remoteVersion = await latestVersion();
|
|
444
|
-
} catch {
|
|
445
|
-
remoteVersion = null;
|
|
446
|
-
}
|
|
447
|
-
if (!remoteVersion) {
|
|
448
|
-
emit('error', 'failed to check evolcore latest version');
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
if (compareVersions(localVersion, remoteVersion) >= 0) {
|
|
452
|
-
emit('noop', 'evolcore is already up to date (' + localVersion + '; latest ' + remoteVersion + ')');
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
if (!existsSync(CLI_PATH)) {
|
|
456
|
-
emit('error', 'restart-monitor entry not found: ' + CLI_PATH);
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// Installed mode: copy the monitor out of the package before it upgrades that
|
|
461
|
-
// same package. Mirrors prepareMonitorStage(); kept inline because this file
|
|
462
|
-
// is generated standalone CJS. Any failure degrades to launching in place —
|
|
463
|
-
// losing upgrade isolation beats losing the upgrade.
|
|
464
|
-
let launchArgs = CLI_ARGS;
|
|
465
|
-
const launchEnv = { ...process.env };
|
|
466
|
-
if (!DEV_MODE && STAGE_PARENT) {
|
|
467
|
-
try {
|
|
468
|
-
const stageDir = path.join(STAGE_PARENT, 'upgrade-' + process.pid + '-' + Date.now());
|
|
469
|
-
fs.mkdirSync(stageDir, { recursive: true });
|
|
470
|
-
fs.cpSync(path.join(PACKAGE_ROOT, 'dist'), path.join(stageDir, 'dist'), { recursive: true });
|
|
471
|
-
if (existsSync(PACKAGE_JSON)) fs.copyFileSync(PACKAGE_JSON, path.join(stageDir, 'package.json'));
|
|
472
|
-
const modulesSource = path.join(PACKAGE_ROOT, 'node_modules');
|
|
473
|
-
if (existsSync(modulesSource)) {
|
|
474
|
-
const staged = path.join(stageDir, 'node_modules');
|
|
475
|
-
try {
|
|
476
|
-
// junction works unelevated on Windows; dir symlink elsewhere.
|
|
477
|
-
fs.symlinkSync(modulesSource, staged, process.platform === 'win32' ? 'junction' : 'dir');
|
|
478
|
-
fs.readdirSync(staged);
|
|
479
|
-
} catch (linkError) {
|
|
480
|
-
fs.rmSync(staged, { recursive: true, force: true });
|
|
481
|
-
fs.cpSync(modulesSource, staged, { recursive: true });
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
const stagedEntry = path.join(stageDir, 'dist', 'cli', 'index.js');
|
|
485
|
-
if (existsSync(stagedEntry)) {
|
|
486
|
-
launchArgs = [stagedEntry];
|
|
487
|
-
launchEnv.EVOLCORE_TARGET_PACKAGE_ROOT = PACKAGE_ROOT;
|
|
488
|
-
launchEnv.EVOLCORE_MONITOR_STAGE = stageDir;
|
|
489
|
-
}
|
|
490
|
-
} catch (stageError) {
|
|
491
|
-
// Fall through with the in-place entry.
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
try {
|
|
496
|
-
const child = spawn(process.execPath, [...launchArgs, 'restart-monitor'], {
|
|
497
|
-
detached: true,
|
|
498
|
-
stdio: 'ignore',
|
|
499
|
-
windowsHide: process.platform === 'win32',
|
|
500
|
-
env: launchEnv,
|
|
501
|
-
});
|
|
502
|
-
child.unref();
|
|
503
|
-
const pid = child.pid;
|
|
504
|
-
// The daemon is still running here — the monitor is what stops it. So a
|
|
505
|
-
// monitor that dies on load costs the upgrade, not the service; still,
|
|
506
|
-
// report it accurately instead of claiming success.
|
|
507
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
508
|
-
let alive = false;
|
|
509
|
-
try { process.kill(pid, 0); alive = true; } catch (e) { alive = false; }
|
|
510
|
-
if (!alive) {
|
|
511
|
-
emit('error', 'restart-monitor exited during startup; upgrade to ' + remoteVersion + ' not applied');
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
emit('success', 'evolcore upgrade available: ' + localVersion + ' -> ' + remoteVersion + '; restart-monitor started');
|
|
515
|
-
} catch (error) {
|
|
516
|
-
emit('error', 'failed to start restart-monitor: ' + (error && error.message ? error.message : String(error)));
|
|
517
|
-
}
|
|
378
|
+
const { refreshManagedPackageVersions } = await import(pathToFileURL(entry).href);
|
|
379
|
+
const results = await refreshManagedPackageVersions(undefined, { source: 'daily-check' });
|
|
380
|
+
const failed = results.some(result => result.status === 'unavailable');
|
|
381
|
+
process.stdout.write(JSON.stringify({
|
|
382
|
+
outcome: failed ? 'error' : 'success',
|
|
383
|
+
text: results.map(result => result.packageName + ': ' + result.status).join('; '),
|
|
384
|
+
files: [],
|
|
385
|
+
}));
|
|
518
386
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
387
|
+
main().catch(() => {
|
|
388
|
+
process.stdout.write(JSON.stringify({ outcome: 'error', text: 'Version information refresh failed', files: [] }));
|
|
389
|
+
process.exitCode = 1;
|
|
522
390
|
});
|
|
523
391
|
`);
|
|
524
392
|
// Remove the pre-Node script left by older installations so it cannot be
|
|
@@ -529,6 +397,51 @@ main().catch((error) => {
|
|
|
529
397
|
atomicWriteJson(manager.definitionPath(definition.id), definition);
|
|
530
398
|
fs.rmSync(manager.activePath(definition.id), { force: true });
|
|
531
399
|
}
|
|
400
|
+
/**
|
|
401
|
+
* Keep one daemon-owned recovery Trigger for all local Agent sessions. The
|
|
402
|
+
* event-session feedback path resolves the owning Agent from task:error rather
|
|
403
|
+
* than treating the daemon AID as the target Agent.
|
|
404
|
+
*/
|
|
405
|
+
function seedTaskRecoveryTrigger(manager, owner) {
|
|
406
|
+
const now = Date.now();
|
|
407
|
+
const definition = normalizeTriggerDefinition({
|
|
408
|
+
$schema_version: 3.1,
|
|
409
|
+
id: '__task-recovery',
|
|
410
|
+
agentAid: owner.aid,
|
|
411
|
+
enabled: true,
|
|
412
|
+
name: '__task-recovery',
|
|
413
|
+
description: 'System trigger: recover failed tasks for local Agents.',
|
|
414
|
+
createdAt: now,
|
|
415
|
+
updatedAt: now,
|
|
416
|
+
origin: {
|
|
417
|
+
channelKey: 'daemon',
|
|
418
|
+
channelType: 'daemon',
|
|
419
|
+
channelId: owner.originPeerId || owner.aid,
|
|
420
|
+
session: 'main',
|
|
421
|
+
peerId: owner.originPeerId || owner.aid,
|
|
422
|
+
sessionKey: `daemon#${owner.originPeerId || owner.aid}#__task-recovery__`,
|
|
423
|
+
},
|
|
424
|
+
source: {
|
|
425
|
+
type: 'event',
|
|
426
|
+
eventPattern: 'task:error',
|
|
427
|
+
},
|
|
428
|
+
execution: {
|
|
429
|
+
type: 'target_session',
|
|
430
|
+
prompt: TASK_RECOVERY_PROMPT,
|
|
431
|
+
onError: 'retry',
|
|
432
|
+
noopSentinel: '[[NOOP]]',
|
|
433
|
+
},
|
|
434
|
+
feedback: { strategy: 'event_session' },
|
|
435
|
+
reliability: {
|
|
436
|
+
concurrency: 'forbid',
|
|
437
|
+
missedPolicy: 'run_once',
|
|
438
|
+
retry: { maxAttempts: 2, backoffMs: 30_000 },
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
fs.mkdirSync(manager.triggerDir(definition.id), { recursive: true });
|
|
442
|
+
atomicWriteJson(manager.definitionPath(definition.id), definition);
|
|
443
|
+
fs.rmSync(manager.activePath(definition.id), { force: true });
|
|
444
|
+
}
|
|
532
445
|
function removeLegacyAgentUpgradeCheck(manager) {
|
|
533
446
|
let existing;
|
|
534
447
|
try {
|
|
@@ -957,6 +870,10 @@ async function main() {
|
|
|
957
870
|
}
|
|
958
871
|
// ── 自动迁移 ──
|
|
959
872
|
migrateIdentitiesIfNeeded();
|
|
873
|
+
const relationSharedMigration = migrateRelationSharedDirectories();
|
|
874
|
+
if (relationSharedMigration.copied > 0) {
|
|
875
|
+
logger.info(`[migrate] Synced ${relationSharedMigration.copied} relation shared file(s) across ${relationSharedMigration.relations} relation(s)`);
|
|
876
|
+
}
|
|
960
877
|
// daemon.json 的旧 ecweb/serviceProxy 结构已在启动前归一化为 services[]。
|
|
961
878
|
// ── 配置体系初始化(schema 字段不相交硬约束校验)──
|
|
962
879
|
try {
|
|
@@ -1239,6 +1156,11 @@ async function main() {
|
|
|
1239
1156
|
});
|
|
1240
1157
|
// 交互路由器
|
|
1241
1158
|
const interactionRouter = new InteractionRouter();
|
|
1159
|
+
const groupInviteReviewService = new GroupInviteReviewService(interactionRouter);
|
|
1160
|
+
const removeGroupInviteConfigListener = onConfigWrite(({ target, selector }) => {
|
|
1161
|
+
if (target === ConfigTarget.Agent && selector.self)
|
|
1162
|
+
groupInviteReviewService.configurationChanged(selector.self);
|
|
1163
|
+
});
|
|
1242
1164
|
// 为所有支持权限的 agent 设置 gateway
|
|
1243
1165
|
for (const inst of agentInstances) {
|
|
1244
1166
|
inst.agent.setPermissionGateway?.(permissionGateway);
|
|
@@ -1327,6 +1249,7 @@ async function main() {
|
|
|
1327
1249
|
// 创建命令处理器
|
|
1328
1250
|
const cmdHandler = new CommandHandler(sessionManager, agentMap, messageCache, eventBus, primaryRunnerKey);
|
|
1329
1251
|
let agentApplicationService;
|
|
1252
|
+
let agentInitializationService;
|
|
1330
1253
|
cmdHandler.setAgentDelegationRegistry(agentDelegationRegistry);
|
|
1331
1254
|
cmdHandler.setPermissionGateway(permissionGateway);
|
|
1332
1255
|
cmdHandler.setInteractionRouter(interactionRouter);
|
|
@@ -1372,10 +1295,13 @@ async function main() {
|
|
|
1372
1295
|
dedupPath: daemonMessageDedupPath(),
|
|
1373
1296
|
});
|
|
1374
1297
|
// 设置中断回调(精确中断正在处理的 agent)
|
|
1375
|
-
messageQueue.setInterruptCallback(async (sessionKey, baseagent, evolagentName, reason = 'new_message') => {
|
|
1298
|
+
messageQueue.setInterruptCallback(async (sessionKey, baseagent, evolagentName, reason = 'new_message', timeout) => {
|
|
1376
1299
|
void baseagent;
|
|
1377
1300
|
void evolagentName;
|
|
1378
|
-
|
|
1301
|
+
if (timeout)
|
|
1302
|
+
await responseEngine.timeoutSession(sessionKey, timeout);
|
|
1303
|
+
else
|
|
1304
|
+
await responseEngine.interruptSession(sessionKey, reason);
|
|
1379
1305
|
});
|
|
1380
1306
|
messageQueue.setEventBus(eventBus);
|
|
1381
1307
|
// Restore persisted input before Trigger schedulers start. Trigger-owned work
|
|
@@ -1531,7 +1457,7 @@ async function main() {
|
|
|
1531
1457
|
};
|
|
1532
1458
|
};
|
|
1533
1459
|
const validateTriggerFeedbackChannels = (definition) => {
|
|
1534
|
-
if (definition.feedback.strategy === 'silent')
|
|
1460
|
+
if (definition.feedback.strategy === 'silent' || definition.feedback.strategy === 'event_session')
|
|
1535
1461
|
return;
|
|
1536
1462
|
const target = definition.feedback.strategy === 'target'
|
|
1537
1463
|
? definition.feedback.target
|
|
@@ -1614,6 +1540,9 @@ async function main() {
|
|
|
1614
1540
|
if (!effortDecision.ok)
|
|
1615
1541
|
throw new Error(effortDecision.message || 'trigger effort is not allowed by current role');
|
|
1616
1542
|
}
|
|
1543
|
+
if (!actor.management && definition.feedback.strategy === 'event_session') {
|
|
1544
|
+
throw new Error('event-session feedback requires owner/admin');
|
|
1545
|
+
}
|
|
1617
1546
|
if (!actor.management && definition.feedback.strategy === 'target') {
|
|
1618
1547
|
const target = definition.feedback.target;
|
|
1619
1548
|
const origin = actor.origin;
|
|
@@ -1721,6 +1650,9 @@ async function main() {
|
|
|
1721
1650
|
if (privilegedReason && !persistedFullAccessApproval && !hasDaemonTriggerAuthority(subject)) {
|
|
1722
1651
|
return { allowed: false, reason: `${privilegedReason} requires current DaemonOwner` };
|
|
1723
1652
|
}
|
|
1653
|
+
if (definition.feedback.strategy === 'event_session' && !isManagementRole(role)) {
|
|
1654
|
+
return { allowed: false, reason: 'event-session feedback requires current owner/admin role' };
|
|
1655
|
+
}
|
|
1724
1656
|
if (definition.feedback.strategy === 'target' && !isManagementRole(role)) {
|
|
1725
1657
|
const target = definition.feedback.target;
|
|
1726
1658
|
if (!target
|
|
@@ -1830,6 +1762,7 @@ async function main() {
|
|
|
1830
1762
|
const manager = new TriggerDefinitionManager(owner.aid);
|
|
1831
1763
|
if (opts.seedUpgradeCheck) {
|
|
1832
1764
|
seedUpgradeCheckTrigger(manager, owner);
|
|
1765
|
+
seedTaskRecoveryTrigger(manager, owner);
|
|
1833
1766
|
}
|
|
1834
1767
|
else {
|
|
1835
1768
|
removeLegacyAgentUpgradeCheck(manager);
|
|
@@ -1840,6 +1773,8 @@ async function main() {
|
|
|
1840
1773
|
getChannel: getTriggerChannel,
|
|
1841
1774
|
sessionManager,
|
|
1842
1775
|
messageQueue,
|
|
1776
|
+
recoverTask: request => responseEngine.recoverTask(request),
|
|
1777
|
+
inspectTargetExecution: (sessionId, attemptId, selfAid) => responseEngine.inspectTargetExecution(sessionId, attemptId, selfAid),
|
|
1843
1778
|
eventBus,
|
|
1844
1779
|
tryHandoff: async (input, text, target, binding) => {
|
|
1845
1780
|
if (input.signal?.aborted) {
|
|
@@ -1956,9 +1891,21 @@ async function main() {
|
|
|
1956
1891
|
const inst = channelInstances.find(candidate => candidate.adapter.channelKey === channelKey);
|
|
1957
1892
|
return !!inst && inst.channel.getStatus?.().connected === true;
|
|
1958
1893
|
};
|
|
1894
|
+
cmdHandler.setAgentStorageClientResolver((channelKey, targetAid) => {
|
|
1895
|
+
const inst = channelInstances.find(candidate => candidate.channelType === 'aun'
|
|
1896
|
+
&& (candidate.adapter.channelKey === channelKey || candidate.adapter.channelName === channelKey)
|
|
1897
|
+
&& candidate.channel.getAid?.() === targetAid);
|
|
1898
|
+
if (!inst || inst.channel.getStatus?.().connected !== true)
|
|
1899
|
+
return undefined;
|
|
1900
|
+
// A reconnect replaces the Client; never capture it during startup.
|
|
1901
|
+
const client = inst.channel.getClient?.();
|
|
1902
|
+
return client?.aid === targetAid ? client : undefined;
|
|
1903
|
+
});
|
|
1959
1904
|
const msgBridge = new MessageBridge(defaultProjectPath, sessionManager, processor, messageQueue, cmdHandler, eventBus, primaryAgent?.config.debounce, () => processLevelOwners);
|
|
1960
1905
|
msgBridge.setAgentRegistry(agentRegistry);
|
|
1961
1906
|
msgBridge.setInteractionRouter(interactionRouter);
|
|
1907
|
+
msgBridge.setGroupInviteReviewService(groupInviteReviewService);
|
|
1908
|
+
cmdHandler.setGroupInviteDecisionResolver((selfAid, ownerAid, inviteId, action) => groupInviteReviewService.decideManaged(selfAid, ownerAid, inviteId, action));
|
|
1962
1909
|
msgBridge.setContactBindRuntimeChecker(isContactBindChannelReady);
|
|
1963
1910
|
msgBridge.setAidStatsCollector(aidStatsCollector);
|
|
1964
1911
|
cmdHandler.setContactRequestSubmitter((input) => msgBridge.submitAgentContactRequest(input));
|
|
@@ -1982,7 +1929,7 @@ async function main() {
|
|
|
1982
1929
|
sessionId: envelope.sessionId,
|
|
1983
1930
|
agentAid: owningAgent?.aid,
|
|
1984
1931
|
agentName: envelope.agentName,
|
|
1985
|
-
payload: summarizeOutboundPayload(payload),
|
|
1932
|
+
payload: sanitizeMenuLogValue(summarizeOutboundPayload(payload)),
|
|
1986
1933
|
});
|
|
1987
1934
|
const result = await originalSend(envelope, payload);
|
|
1988
1935
|
// AUN adapters return an explicit receipt. Only a receipt with a remote
|
|
@@ -2552,7 +2499,10 @@ async function main() {
|
|
|
2552
2499
|
catch {
|
|
2553
2500
|
parsed = null;
|
|
2554
2501
|
}
|
|
2555
|
-
const menuResponseContext = () =>
|
|
2502
|
+
const menuResponseContext = () => ({
|
|
2503
|
+
...controlReplyContext(opts, evolMenuResponseTransportMetadata(opts.protectedHeaders?.sdk_version)),
|
|
2504
|
+
...(opts.peerDeviceId ? { toDeviceId: opts.peerDeviceId } : {}),
|
|
2505
|
+
});
|
|
2556
2506
|
const sendControlMenuResponse = async (response) => {
|
|
2557
2507
|
const timedResponse = withMenuProcessingTime(enforceMenuResponseSize(response, 128 * 1024 - 1024), menuTiming);
|
|
2558
2508
|
const request = activeMenuRequest ?? {
|
|
@@ -2637,9 +2587,9 @@ async function main() {
|
|
|
2637
2587
|
return;
|
|
2638
2588
|
}
|
|
2639
2589
|
if (text.toLowerCase() === '/pair') {
|
|
2640
|
-
const pair = remoteAccessService.getPairingCode(opts.peerId);
|
|
2590
|
+
const pair = remoteAccessService.getPairingCode(opts.peerId, Date.now(), 'pair');
|
|
2641
2591
|
const mins = Math.max(0, Math.round((pair.expiresAt - Date.now()) / 60000));
|
|
2642
|
-
const reply = `远程控制配对码:${pair.code}(约 ${mins}
|
|
2592
|
+
const reply = `远程控制配对码:${pair.code}(约 ${mins} 分钟内有效,仅可配对一次)`;
|
|
2643
2593
|
await controlChannel.sendMessage(opts.channelId, reply, controlReplyContext(opts));
|
|
2644
2594
|
return;
|
|
2645
2595
|
}
|
|
@@ -2650,7 +2600,7 @@ async function main() {
|
|
|
2650
2600
|
await sendControlMenuResponse(menuFailure({ id: menuControl.id, ...(menuControl.name?.trim() ? { name: menuControl.name } : {}) }, validationError));
|
|
2651
2601
|
return;
|
|
2652
2602
|
}
|
|
2653
|
-
const deduped = await controlMenuDeduper.execute([opts.channelId, opts.peerId, menuControl.id].join('\u001f'), menuPayloadFingerprint(menuControl.raw), () => cmdHandler.execMenuForControl(parsed, opts.peerId, {
|
|
2603
|
+
const deduped = await controlMenuDeduper.execute([opts.channelId, opts.peerId, opts.peerDeviceId || '', menuControl.id].join('\u001f'), menuPayloadFingerprint(menuControl.raw), () => cmdHandler.execMenuForControl(parsed, opts.peerId, {
|
|
2654
2604
|
encrypted: opts.encrypted,
|
|
2655
2605
|
protectedHeaders: opts.protectedHeaders,
|
|
2656
2606
|
}));
|
|
@@ -2848,6 +2798,41 @@ async function main() {
|
|
|
2848
2798
|
});
|
|
2849
2799
|
}
|
|
2850
2800
|
}
|
|
2801
|
+
async function completeAgentBootstrap(aid) {
|
|
2802
|
+
const aunInstance = channelInstances.find(candidate => {
|
|
2803
|
+
if (candidate.channelType !== 'aun')
|
|
2804
|
+
return false;
|
|
2805
|
+
const owner = agentRegistry.resolveByChannel(candidate.adapter.channelKey)
|
|
2806
|
+
?? agentRegistry.resolveByChannel(candidate.adapter.channelName);
|
|
2807
|
+
return owner?.aid === aid;
|
|
2808
|
+
});
|
|
2809
|
+
const welcome = aunInstance?.channel;
|
|
2810
|
+
const owningAgent = agentRegistry.get(aid);
|
|
2811
|
+
const firstOwnerAid = getFirstStaticAgentOwner(aid);
|
|
2812
|
+
const sessions = aunInstance && firstOwnerAid && owningAgent
|
|
2813
|
+
? {
|
|
2814
|
+
ensurePostBootstrapMainSession: async (owner) => {
|
|
2815
|
+
const ownerAid = owner || firstOwnerAid;
|
|
2816
|
+
const channel = aunInstance.adapter.channelName;
|
|
2817
|
+
const active = await sessionManager.getActiveSession(channel, ownerAid);
|
|
2818
|
+
const ensured = await sessionManager.ensureNewMainSessionForOperation({
|
|
2819
|
+
channel,
|
|
2820
|
+
channelId: ownerAid,
|
|
2821
|
+
projectPath: active?.projectPath || owningAgent.projectPath || defaultProjectPath,
|
|
2822
|
+
baseagent: owningAgent.baseagent || active?.baseagent || primaryBaseagent,
|
|
2823
|
+
operationId: postBootstrapWelcomeOperationId(aid, ownerAid),
|
|
2824
|
+
identityMetadata: {
|
|
2825
|
+
...(active?.metadata ?? {}),
|
|
2826
|
+
channelKey: aunInstance.adapter.channelKey,
|
|
2827
|
+
peerId: ownerAid,
|
|
2828
|
+
},
|
|
2829
|
+
});
|
|
2830
|
+
return { sessionId: ensured.session.id, created: ensured.created };
|
|
2831
|
+
},
|
|
2832
|
+
}
|
|
2833
|
+
: undefined;
|
|
2834
|
+
return completeBootstrapWithWelcome(bootstrapService, aid, welcome, sessions);
|
|
2835
|
+
}
|
|
2851
2836
|
function configureIpc() {
|
|
2852
2837
|
ipcServer.setShutdownExecutor(async (reason) => {
|
|
2853
2838
|
if (!shutdown) {
|
|
@@ -2880,39 +2865,10 @@ async function main() {
|
|
|
2880
2865
|
return { ok: false, code: 'INVALID_CONTROL_TOKEN', error: 'valid local control token is required' };
|
|
2881
2866
|
}
|
|
2882
2867
|
}
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
?? agentRegistry.resolveByChannel(candidate.adapter.channelName);
|
|
2888
|
-
return owner?.aid === aid;
|
|
2889
|
-
});
|
|
2890
|
-
const welcome = aunInstance?.channel;
|
|
2891
|
-
const owningAgent = agentRegistry.get(aid);
|
|
2892
|
-
const firstOwnerAid = getFirstStaticAgentOwner(aid);
|
|
2893
|
-
const sessions = aunInstance && firstOwnerAid && owningAgent
|
|
2894
|
-
? {
|
|
2895
|
-
ensurePostBootstrapMainSession: async (owner) => {
|
|
2896
|
-
const ownerAid = owner || firstOwnerAid;
|
|
2897
|
-
const channel = aunInstance.adapter.channelName;
|
|
2898
|
-
const active = await sessionManager.getActiveSession(channel, ownerAid);
|
|
2899
|
-
const ensured = await sessionManager.ensureNewMainSessionForOperation({
|
|
2900
|
-
channel,
|
|
2901
|
-
channelId: ownerAid,
|
|
2902
|
-
projectPath: active?.projectPath || owningAgent.projectPath || defaultProjectPath,
|
|
2903
|
-
baseagent: owningAgent.baseagent || active?.baseagent || primaryBaseagent,
|
|
2904
|
-
operationId: postBootstrapWelcomeOperationId(aid, ownerAid),
|
|
2905
|
-
identityMetadata: {
|
|
2906
|
-
...(active?.metadata ?? {}),
|
|
2907
|
-
channelKey: aunInstance.adapter.channelKey,
|
|
2908
|
-
peerId: ownerAid,
|
|
2909
|
-
},
|
|
2910
|
-
});
|
|
2911
|
-
return { sessionId: ensured.session.id, created: ensured.created };
|
|
2912
|
-
},
|
|
2913
|
-
}
|
|
2914
|
-
: undefined;
|
|
2915
|
-
return completeBootstrapWithWelcome(bootstrapService, aid, welcome, sessions);
|
|
2868
|
+
if (hasSuppliedInitialization(aid) || loadAgent(aid)?.initialization) {
|
|
2869
|
+
return { ok: false, code: 'INITIALIZATION_MANAGED', error: 'Use the initialization service for this Agent' };
|
|
2870
|
+
}
|
|
2871
|
+
return completeAgentBootstrap(aid);
|
|
2916
2872
|
});
|
|
2917
2873
|
ipcServer.setDingtalkContactBindExecutor({
|
|
2918
2874
|
register: (cmd) => registerPendingDingtalkContactBind(cmd),
|
|
@@ -3020,6 +2976,14 @@ async function main() {
|
|
|
3020
2976
|
aidStatsCollector.recordOutbound(params.aid, params.toPeer, Buffer.byteLength(params.text || '', 'utf-8'), params.text, false, params.encrypt, params.chatmode, 'send');
|
|
3021
2977
|
});
|
|
3022
2978
|
ipcServer.setTaskRuntimeContextProvider(({ sessionId }) => responseEngine.getTaskRuntimeContext(sessionId));
|
|
2979
|
+
ipcServer.setTaskRuntimeContextAuthorizer(({ sessionId, delegationToken, delegationCommandHash }) => {
|
|
2980
|
+
// Codex persistent threads carry a command-scoped authorization. Looking
|
|
2981
|
+
// up fresh routing context must not consume the subsequent CLI operation.
|
|
2982
|
+
const authorization = agentDelegationRegistry.validateForContext(delegationToken, sessionId, delegationCommandHash);
|
|
2983
|
+
return authorization.ok
|
|
2984
|
+
? { ok: true }
|
|
2985
|
+
: { ok: false, code: authorization.code, error: authorization.reason };
|
|
2986
|
+
});
|
|
3023
2987
|
ipcServer.setCodexPreToolUseExecutor(async (params) => {
|
|
3024
2988
|
for (const runner of new Set(agentMap.values())) {
|
|
3025
2989
|
if (typeof runner?.evaluatePreToolUse !== 'function')
|
|
@@ -3694,6 +3658,57 @@ async function main() {
|
|
|
3694
3658
|
}),
|
|
3695
3659
|
aunAidStats: () => aidStatsCollector.getAllSnapshots(),
|
|
3696
3660
|
});
|
|
3661
|
+
agentInitializationService = new AgentInitializationService({
|
|
3662
|
+
register: async (aid) => {
|
|
3663
|
+
const { aidCreate } = await import('./aun/aid/identity.js');
|
|
3664
|
+
const created = await aidCreate(aid);
|
|
3665
|
+
await created.client.close();
|
|
3666
|
+
},
|
|
3667
|
+
publish: async (aid, content) => {
|
|
3668
|
+
const { agentmdPut } = await import('./aun/aid/agentmd.js');
|
|
3669
|
+
await agentmdPut(content, { aid });
|
|
3670
|
+
},
|
|
3671
|
+
fetch: async (aid) => {
|
|
3672
|
+
const { agentmdGet } = await import('./aun/aid/agentmd.js');
|
|
3673
|
+
const card = await agentmdGet(aid, { withVerification: true, remoteOnly: true });
|
|
3674
|
+
return { content: card.content, verified: card.verification.status === 'verified' };
|
|
3675
|
+
},
|
|
3676
|
+
hotLoad: async (aid) => {
|
|
3677
|
+
await coreHotLoadAgent(aid);
|
|
3678
|
+
const until = Date.now() + 20_000;
|
|
3679
|
+
while (Date.now() < until) {
|
|
3680
|
+
if (channelInstances.some(inst => inst.channelType === 'aun'
|
|
3681
|
+
&& inst.channel.getAidState?.()?.aid === aid
|
|
3682
|
+
&& inst.channel.getAidState?.()?.status === 'connected'))
|
|
3683
|
+
return;
|
|
3684
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
3685
|
+
}
|
|
3686
|
+
throw Object.assign(new Error('AUN connection unavailable'), { code: 'INITIALIZE_CHANNEL_UNAVAILABLE' });
|
|
3687
|
+
},
|
|
3688
|
+
activate: completeAgentBootstrap,
|
|
3689
|
+
authorize: actor => actor === 'local-control' || (loadDaemonConfig().owners ?? []).includes(actor),
|
|
3690
|
+
usable: aid => {
|
|
3691
|
+
const agent = agentRegistry.get(aid);
|
|
3692
|
+
return !!agent && agent.config.enabled !== false && agentMap.has(`${aid}::${agent.baseagent}`)
|
|
3693
|
+
&& channelInstances.some(inst => inst.channelType === 'aun'
|
|
3694
|
+
&& inst.channel.getAidState?.()?.aid === aid
|
|
3695
|
+
&& inst.channel.getAidState?.()?.status === 'connected');
|
|
3696
|
+
},
|
|
3697
|
+
});
|
|
3698
|
+
agentApplicationService.setInitializationService(agentInitializationService);
|
|
3699
|
+
ipcServer.setInitializationExecutor(async (cmd) => executeLocalInitializationCommand(agentInitializationService, cmd));
|
|
3700
|
+
for (const entry of fs.readdirSync(resolvePaths().agentsDir, { withFileTypes: true })) {
|
|
3701
|
+
if (!entry.isDirectory())
|
|
3702
|
+
continue;
|
|
3703
|
+
try {
|
|
3704
|
+
const record = readInitialization(entry.name);
|
|
3705
|
+
if (record?.status === 'in_progress')
|
|
3706
|
+
agentInitializationService.resume(entry.name, record.actor);
|
|
3707
|
+
}
|
|
3708
|
+
catch {
|
|
3709
|
+
logger.warn('[Initialization] Recovery requires review for an incomplete operation');
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3697
3712
|
cmdHandler.setAgentApplicationService(agentApplicationService);
|
|
3698
3713
|
ipcServer.setAgentApplicationService(agentApplicationService);
|
|
3699
3714
|
ipcServer.setStatsProvider(() => statsCollector.getSnapshot());
|
|
@@ -3796,6 +3811,8 @@ async function main() {
|
|
|
3796
3811
|
? {
|
|
3797
3812
|
ok: true,
|
|
3798
3813
|
aid: subject.dataScope === 'daemon' ? (params.targetAid ?? delegation.grant.selfAid) : delegation.grant.selfAid,
|
|
3814
|
+
dataScope: subject.dataScope,
|
|
3815
|
+
management: isManagementRole(subject.role),
|
|
3799
3816
|
}
|
|
3800
3817
|
: { ok: false, code: decision.code, error: decision.reason };
|
|
3801
3818
|
}
|
|
@@ -3823,26 +3840,41 @@ async function main() {
|
|
|
3823
3840
|
return fail('INVALID_DELEGATION', 'delegation does not match the current session');
|
|
3824
3841
|
}
|
|
3825
3842
|
const taskAid = delegation.grant.selfAid;
|
|
3843
|
+
let welcomeArgs;
|
|
3844
|
+
if (sub === 'welcome') {
|
|
3845
|
+
try {
|
|
3846
|
+
welcomeArgs = parseAgentWelcomeArgs(argv.slice(2));
|
|
3847
|
+
}
|
|
3848
|
+
catch (error) {
|
|
3849
|
+
return fail('INVALID_ARGS', error.message);
|
|
3850
|
+
}
|
|
3851
|
+
if (delegation.grant.chatType !== 'private')
|
|
3852
|
+
return fail('NOT_ALLOWED', 'welcome requires a private conversation');
|
|
3853
|
+
}
|
|
3826
3854
|
const targetAid = sub === 'list'
|
|
3827
3855
|
? undefined
|
|
3828
3856
|
: sub === 'persona'
|
|
3829
3857
|
? taskAid
|
|
3830
|
-
: sub === '
|
|
3831
|
-
?
|
|
3832
|
-
: sub === '
|
|
3833
|
-
? (argv[2] && !argv[2].startsWith('--') ? argv[2] :
|
|
3834
|
-
:
|
|
3858
|
+
: sub === 'welcome'
|
|
3859
|
+
? taskAid
|
|
3860
|
+
: sub === 'show'
|
|
3861
|
+
? (argv[2] && !argv[2].startsWith('--') ? argv[2] : taskAid)
|
|
3862
|
+
: sub === 'reload'
|
|
3863
|
+
? (argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined)
|
|
3864
|
+
: (argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined);
|
|
3835
3865
|
const operation = sub === 'list' ? 'agent.list'
|
|
3836
3866
|
: sub === 'show' ? 'agent.show'
|
|
3837
3867
|
: sub === 'persona' ? 'agent.persona'
|
|
3838
|
-
: sub === '
|
|
3839
|
-
: sub === '
|
|
3840
|
-
: sub === '
|
|
3841
|
-
: sub === '
|
|
3842
|
-
: sub === '
|
|
3868
|
+
: sub === 'welcome' ? 'agent.welcome'
|
|
3869
|
+
: sub === 'initialize' || (sub === 'new' && argv.includes('--initialize')) ? 'agent.initialize'
|
|
3870
|
+
: sub === 'new' ? 'agent.create'
|
|
3871
|
+
: sub === 'enable' ? 'agent.enable'
|
|
3872
|
+
: sub === 'disable' ? 'agent.disable'
|
|
3873
|
+
: sub === 'reload' ? 'agent.reload'
|
|
3874
|
+
: sub === 'delete' ? 'agent.delete' : undefined;
|
|
3843
3875
|
if (!operation)
|
|
3844
3876
|
return fail('INVALID_ARGS', `unsupported managed agent command: ${sub}`);
|
|
3845
|
-
if (sub === 'new' && !argv.includes('--non-interactive')) {
|
|
3877
|
+
if (sub === 'new' && !argv.includes('--non-interactive') && !argv.includes('--initialize')) {
|
|
3846
3878
|
return fail('MANAGED_NON_INTERACTIVE_REQUIRED', 'interactive Agent creation is unavailable in a managed task', 'MANAGED_NON_INTERACTIVE_REQUIRED');
|
|
3847
3879
|
}
|
|
3848
3880
|
if (sub === 'delete' && argv.includes('--purge') && !argv.includes('--confirm-purge')) {
|
|
@@ -3871,7 +3903,7 @@ async function main() {
|
|
|
3871
3903
|
subject,
|
|
3872
3904
|
intent: {
|
|
3873
3905
|
operation,
|
|
3874
|
-
scope: operation === 'agent.show' || operation === 'agent.persona'
|
|
3906
|
+
scope: operation === 'agent.show' || operation === 'agent.persona' || operation === 'agent.welcome'
|
|
3875
3907
|
? 'agent'
|
|
3876
3908
|
: operation === 'agent.reload' && targetAid
|
|
3877
3909
|
? 'agent'
|
|
@@ -3882,6 +3914,7 @@ async function main() {
|
|
|
3882
3914
|
aid: targetAid ?? taskAid,
|
|
3883
3915
|
taskAgentAid: taskAid,
|
|
3884
3916
|
targetAgentAid: targetAid ?? taskAid,
|
|
3917
|
+
...(welcomeArgs ? { action: welcomeArgs.action } : {}),
|
|
3885
3918
|
},
|
|
3886
3919
|
},
|
|
3887
3920
|
auditMetadata: { taskId: delegation.grant.taskId, messageId: delegation.grant.messageId },
|
|
@@ -3933,6 +3966,7 @@ async function main() {
|
|
|
3933
3966
|
: { config: null, agent_md: null, project: null, data: null },
|
|
3934
3967
|
...(subject.dataScope === 'daemon' ? {} : { redacted: true }),
|
|
3935
3968
|
...(agent.createProgress ? { createProgress: agent.createProgress } : {}),
|
|
3969
|
+
...(agent.initialization ? { initialization: agent.initialization } : {}),
|
|
3936
3970
|
} };
|
|
3937
3971
|
}
|
|
3938
3972
|
if (operation === 'agent.persona') {
|
|
@@ -3967,6 +4001,48 @@ async function main() {
|
|
|
3967
4001
|
...(result.saved ? { saved: true } : {}),
|
|
3968
4002
|
} };
|
|
3969
4003
|
}
|
|
4004
|
+
if (operation === 'agent.welcome') {
|
|
4005
|
+
if (subject.role !== 'owner' && !(welcomeArgs?.action === 'show' && subject.role === 'admin')) {
|
|
4006
|
+
return fail('NOT_ALLOWED', 'welcome requires the current Agent Owner (admin may read)');
|
|
4007
|
+
}
|
|
4008
|
+
const { agentWelcome } = await import('./cli/agent.js');
|
|
4009
|
+
const result = await agentWelcome(taskAid, { text: welcomeArgs?.text, trustedLocal: true });
|
|
4010
|
+
if (!result.ok)
|
|
4011
|
+
return fail(result.code ?? 'INTERNAL', result.error);
|
|
4012
|
+
return { ok: true, result: {
|
|
4013
|
+
ok: true,
|
|
4014
|
+
aid: taskAid,
|
|
4015
|
+
content: result.content,
|
|
4016
|
+
...(result.path ? { path: result.path } : {}),
|
|
4017
|
+
...(result.saved ? { saved: true } : {}),
|
|
4018
|
+
...(result.bytes !== undefined ? { bytes: result.bytes } : {}),
|
|
4019
|
+
...(result.sha256 ? { sha256: result.sha256 } : {}),
|
|
4020
|
+
} };
|
|
4021
|
+
}
|
|
4022
|
+
if (operation === 'agent.initialize') {
|
|
4023
|
+
try {
|
|
4024
|
+
const parsed = parseInitializationArgs(argv.slice(1));
|
|
4025
|
+
const actor = delegation.grant.actorId;
|
|
4026
|
+
if (parsed.resume)
|
|
4027
|
+
return { ok: true, result: agentInitializationService.resume(parsed.aid, actor) };
|
|
4028
|
+
const createPermission = authorizeOperation({
|
|
4029
|
+
source: 'agent-tool', subject,
|
|
4030
|
+
intent: { operation: 'agent.create', scope: 'control', source: 'agent-tool', args: { aid: parsed.aid } },
|
|
4031
|
+
auditMetadata: { taskId: delegation.grant.taskId, messageId: delegation.grant.messageId },
|
|
4032
|
+
});
|
|
4033
|
+
if (!createPermission.allow)
|
|
4034
|
+
return fail(createPermission.code, createPermission.reason);
|
|
4035
|
+
if (!argv.includes('--owner') && !argv.includes('--owners'))
|
|
4036
|
+
return fail('INITIALIZE_OWNER_MISMATCH', 'Explicit Owner required');
|
|
4037
|
+
const plan = resolveInitializationPlan(argv.slice(1));
|
|
4038
|
+
if (!plan.owners.includes(actor))
|
|
4039
|
+
return fail('INITIALIZE_OWNER_MISMATCH', 'The authenticated requesting Owner must be retained');
|
|
4040
|
+
return { ok: true, result: agentInitializationService.start(plan, actor, parsed.dryRun) };
|
|
4041
|
+
}
|
|
4042
|
+
catch (error) {
|
|
4043
|
+
return fail(error.code ?? 'INVALID_ARGS', error.message);
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
3970
4046
|
if (operation === 'agent.create') {
|
|
3971
4047
|
const aid = argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined;
|
|
3972
4048
|
if (!aid)
|
|
@@ -4094,6 +4170,11 @@ async function main() {
|
|
|
4094
4170
|
const result = await execAgentAction(sub, { aid: targetAid ?? taskAid, force: argv.includes('--force') }, delegation.grant.actorId, eventBus, agentApplicationService);
|
|
4095
4171
|
return 'error' in result ? fail(result.code, result.error) : { ok: true, result: { ok: true, ...(result.data ?? {}) } };
|
|
4096
4172
|
});
|
|
4173
|
+
ipcServer.setTaskResumeExecutor(params => executeTaskResume(params, {
|
|
4174
|
+
sessions: sessionManager,
|
|
4175
|
+
authorizeManaged: authorizeManagedAgentOperation,
|
|
4176
|
+
recover: request => responseEngine.recoverTask(request),
|
|
4177
|
+
}));
|
|
4097
4178
|
ipcServer.setQueueOperationExecutor(async (params) => {
|
|
4098
4179
|
const operation = `ec.queue.${params.action ?? 'read'}`;
|
|
4099
4180
|
const authorization = await authorizeManagedAgentOperation(params, operation);
|
|
@@ -4134,6 +4215,38 @@ async function main() {
|
|
|
4134
4215
|
const authorization = await authorizeManagedAgentOperation({ ...params, targetAid: params.aid }, params.operation);
|
|
4135
4216
|
return authorization.ok ? { ok: true } : authorization;
|
|
4136
4217
|
});
|
|
4218
|
+
ipcServer.setStorageUploadExecutor(async (params) => {
|
|
4219
|
+
const authorization = await authorizeManagedAgentOperation({ ...params, targetAid: params.aid }, 'storage.upload');
|
|
4220
|
+
if (!authorization.ok)
|
|
4221
|
+
return authorization;
|
|
4222
|
+
const session = await sessionManager.getSessionById(params.sessionId);
|
|
4223
|
+
if (!session)
|
|
4224
|
+
return { ok: false, code: 'SESSION_NOT_FOUND', error: 'current session not found' };
|
|
4225
|
+
try {
|
|
4226
|
+
const projectPath = fs.realpathSync(path.resolve(session.projectPath));
|
|
4227
|
+
const requestedFile = path.resolve(session.projectPath, params.localFile);
|
|
4228
|
+
const requestedStat = fs.lstatSync(requestedFile);
|
|
4229
|
+
if (requestedStat.isSymbolicLink()) {
|
|
4230
|
+
return { ok: false, code: 'INVALID_LOCAL_FILE', error: 'Upload source must not be a symbolic link' };
|
|
4231
|
+
}
|
|
4232
|
+
const localFile = fs.realpathSync(requestedFile);
|
|
4233
|
+
const stat = fs.lstatSync(localFile);
|
|
4234
|
+
if (!isSameOrDescendant(localFile, projectPath) || isHClassPath(localFile)) {
|
|
4235
|
+
return { ok: false, code: 'INVALID_LOCAL_PATH', error: 'Upload source must be an unprotected file inside the current session project' };
|
|
4236
|
+
}
|
|
4237
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
4238
|
+
return { ok: false, code: 'INVALID_LOCAL_FILE', error: 'Upload source must be a regular non-symlink file' };
|
|
4239
|
+
}
|
|
4240
|
+
const { storageUpload } = await import('./aun/storage/index.js');
|
|
4241
|
+
const result = await storageUpload(authorization.aid, localFile, params.remotePath, { isPublic: params.isPublic });
|
|
4242
|
+
return result.ok
|
|
4243
|
+
? { ok: true, objectKey: result.objectKey, publicUrl: result.publicUrl }
|
|
4244
|
+
: { ok: false, code: 'STORAGE_UPLOAD_FAILED', error: result.error };
|
|
4245
|
+
}
|
|
4246
|
+
catch (error) {
|
|
4247
|
+
return { ok: false, code: 'INVALID_LOCAL_FILE', error: error instanceof Error ? error.message : String(error) };
|
|
4248
|
+
}
|
|
4249
|
+
});
|
|
4137
4250
|
ipcServer.setTriggerExecutor(async (cmd) => {
|
|
4138
4251
|
const schedulerFor = (agentAid) => {
|
|
4139
4252
|
const scheduler = triggerSchedulers.get(agentAid);
|
|
@@ -4537,6 +4650,8 @@ async function main() {
|
|
|
4537
4650
|
timestamp: Date.now()
|
|
4538
4651
|
});
|
|
4539
4652
|
// 断开插件系统的渠道
|
|
4653
|
+
removeGroupInviteConfigListener();
|
|
4654
|
+
await shutdownStep('stop group invitation review', () => groupInviteReviewService.dispose());
|
|
4540
4655
|
await shutdownStep('disconnect channels', () => channelLoader.disconnectAll(channelInstances));
|
|
4541
4656
|
for (const inst of channelInstances) {
|
|
4542
4657
|
const type = inst.channelType || inst.adapter.channelName;
|