evolcore 0.0.10 → 0.0.12

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.
Files changed (131) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +3 -3
  3. package/bin/codex-managed-hook.mjs +80 -0
  4. package/dist/agents/baseagent.js +4 -0
  5. package/dist/agents/claude-runner.js +158 -44
  6. package/dist/agents/codex-app-server-client.js +153 -23
  7. package/dist/agents/codex-runner.js +331 -43
  8. package/dist/agents/ecagent-runner.js +53 -6
  9. package/dist/agents/gemini-runner.js +1 -0
  10. package/dist/agents/request-identity.js +55 -0
  11. package/dist/aun/aid/client.js +11 -21
  12. package/dist/aun/aid/managed-operation.js +107 -0
  13. package/dist/aun/msg/group.js +81 -12
  14. package/dist/aun/msg/managed-operation.js +804 -0
  15. package/dist/aun/msg/mention-schema.js +20 -0
  16. package/dist/aun/msg/p2p.js +7 -0
  17. package/dist/aun/outbox.js +28 -31
  18. package/dist/channels/aun.js +418 -235
  19. package/dist/channels/daemon.js +13 -0
  20. package/dist/cli/agent-command.js +72 -17
  21. package/dist/cli/agent.js +249 -22
  22. package/dist/cli/aun-commands.js +270 -69
  23. package/dist/cli/bench.js +12 -3
  24. package/dist/cli/daemon-commands.js +52 -33
  25. package/dist/cli/fs-command.js +60 -0
  26. package/dist/cli/handoff-command.js +3 -0
  27. package/dist/cli/index.js +106 -63
  28. package/dist/cli/init-cancel.js +208 -0
  29. package/dist/cli/init-channel.js +343 -195
  30. package/dist/cli/init.js +21 -9
  31. package/dist/cli/managed-command-guard.js +41 -0
  32. package/dist/cli/model.js +11 -4
  33. package/dist/cli/queue-command.js +11 -1
  34. package/dist/cli/response.js +71 -0
  35. package/dist/cli/restart-monitor.js +4 -18
  36. package/dist/cli/trigger-command.js +4 -0
  37. package/dist/config/builtin-roles.js +5 -0
  38. package/dist/config/contact-book-store.js +11 -3
  39. package/dist/config/contact-request-service.js +161 -15
  40. package/dist/config/gateway-config.js +26 -10
  41. package/dist/config/mention-mode.js +8 -24
  42. package/dist/core/agent-reload-coordinator.js +53 -0
  43. package/dist/core/auth/agent-delegation.js +0 -1
  44. package/dist/core/auth/operation-authorizer.js +62 -154
  45. package/dist/core/auth/operation-catalog.js +264 -22
  46. package/dist/core/bootstrap-messages.js +68 -0
  47. package/dist/core/bootstrap-service.js +144 -10
  48. package/dist/core/capability/providers/claude-capability-provider.js +9 -31
  49. package/dist/core/capability/providers/codex-capability-provider.js +4 -15
  50. package/dist/core/capability/skill-discovery.js +55 -0
  51. package/dist/core/channel-loader.js +24 -7
  52. package/dist/core/command/agent-control.js +14 -11
  53. package/dist/core/command/cli-intent-parser.js +9 -0
  54. package/dist/core/command/command-handler.js +467 -6
  55. package/dist/core/command/connect-menu.js +15 -0
  56. package/dist/core/command/group-menu.js +4 -4
  57. package/dist/core/command/menu-catalog.js +366 -0
  58. package/dist/core/command/menu-handler.js +213 -110
  59. package/dist/core/command/menu-protocol.js +71 -0
  60. package/dist/core/command/slash-gate.js +5 -2
  61. package/dist/core/command/slash-handler.js +45 -25
  62. package/dist/core/daemon-file-cache.js +2 -1
  63. package/dist/core/data-migration.js +9 -2
  64. package/dist/core/evolagent-registry.js +125 -35
  65. package/dist/core/evolagent.js +12 -5
  66. package/dist/core/handoff/dispatcher.js +5 -2
  67. package/dist/core/handoff/runtime.js +145 -21
  68. package/dist/core/handoff/store.js +24 -0
  69. package/dist/core/handoff/types.js +1 -0
  70. package/dist/core/inference/text-inference.js +38 -4
  71. package/dist/core/message/logical-queue-bridge.js +1 -0
  72. package/dist/core/message/mention-schema.js +126 -0
  73. package/dist/core/message/message-bridge.js +237 -79
  74. package/dist/core/message/message-log.js +23 -0
  75. package/dist/core/message/message-queue.js +20 -4
  76. package/dist/core/message/response-engine.js +54 -36
  77. package/dist/core/model/model-catalog.js +143 -24
  78. package/dist/core/model/model-diagnostics.js +28 -10
  79. package/dist/core/permission/ec-command-parser.js +156 -10
  80. package/dist/core/permission/index.js +1 -0
  81. package/dist/core/permission/readonly-shell-query.js +532 -0
  82. package/dist/core/permission/sandbox-runtime.js +22 -1
  83. package/dist/core/permission/shell-environment.js +46 -0
  84. package/dist/core/permission/tool-policy.js +292 -111
  85. package/dist/core/protected-paths.js +17 -9
  86. package/dist/core/runner-reload-transaction.js +57 -0
  87. package/dist/core/session/session-manager.js +21 -2
  88. package/dist/eck/manifest-engine.js +39 -13
  89. package/dist/index.js +644 -180
  90. package/dist/ipc.js +246 -19
  91. package/dist/response-system/coordinator.js +6 -4
  92. package/dist/response-system/engines/v1/proactive-flow.js +26 -8
  93. package/dist/response-system/modes/single-session/index.js +14 -1
  94. package/dist/response-system/selector.js +6 -5
  95. package/dist/trigger/anomaly-store.js +4 -0
  96. package/dist/trigger/script-executor.js +1 -0
  97. package/dist/utils/aid-bind.js +3 -8
  98. package/dist/utils/codex-app-server-registry.js +90 -0
  99. package/dist/utils/codex-cli.js +5 -1
  100. package/dist/utils/cross-platform.js +15 -0
  101. package/dist/utils/log-writer.js +6 -10
  102. package/dist/utils/logger.js +5 -5
  103. package/dist/utils/npm-ops.js +5 -12
  104. package/dist/utils/tool-summary.js +11 -0
  105. package/kits/docs/channels/aun.md +1 -1
  106. package/kits/docs/context-assembly.md +2 -2
  107. package/kits/docs/evolcore/agent.md +11 -6
  108. package/kits/docs/evolcore/aid.md +14 -0
  109. package/kits/docs/evolcore/msg.md +13 -0
  110. package/kits/docs/prompt-loading-architecture.md +1 -2
  111. package/kits/docs/venues/group.md +1 -1
  112. package/kits/eck_manifest.json +0 -12
  113. package/kits/rules/01-overview.md +9 -0
  114. package/kits/rules/04-relation.md +1 -1
  115. package/kits/rules/05-venue.md +2 -2
  116. package/kits/schemas/agent-config.schema.3.json +1 -1
  117. package/kits/schemas/agent-config.schema.4.json +1 -1
  118. package/kits/schemas/relation-config.schema.2.json +1 -1
  119. package/kits/schemas/role-config.schema.1.json +1 -1
  120. package/kits/schemas/single-session.schema.1.json +3 -3
  121. package/kits/schemas/single-session.schema.2.json +3 -3
  122. package/kits/templates/roles/admin.json +27 -0
  123. package/kits/templates/roles/member.json +44 -0
  124. package/kits/templates/roles/visitor.json +40 -2
  125. package/kits/templates/system-fragments/bootstrap.md +12 -6
  126. package/kits/templates/system-fragments/channel.md +6 -0
  127. package/kits/templates/system-fragments/session.md +2 -0
  128. package/package.json +3 -2
  129. package/skills/eclink/SKILL.md +15 -3
  130. package/skills/eclink/agents/openai.yaml +3 -3
  131. package/dist/core/command/evol-menu-version-gate.js +0 -39
@@ -2,6 +2,7 @@ import fs from 'fs';
2
2
  import os from 'os';
3
3
  import path from 'path';
4
4
  import { execFileSync } from 'child_process';
5
+ import { discoverSkillDirectories } from '../skill-discovery.js';
5
6
  function readJson(file) {
6
7
  try {
7
8
  if (!fs.existsSync(file))
@@ -12,31 +13,6 @@ function readJson(file) {
12
13
  return null;
13
14
  }
14
15
  }
15
- function listDirectories(dir) {
16
- try {
17
- if (!fs.existsSync(dir))
18
- return [];
19
- return fs.readdirSync(dir, { withFileTypes: true })
20
- .filter(entry => entry.isDirectory())
21
- .map(entry => entry.name);
22
- }
23
- catch {
24
- return [];
25
- }
26
- }
27
- function readSkillDescription(skillDir) {
28
- const file = path.join(skillDir, 'SKILL.md');
29
- try {
30
- const text = fs.readFileSync(file, 'utf-8');
31
- const firstBodyLine = text.split(/\r?\n/)
32
- .map(line => line.trim())
33
- .find(line => line && !line.startsWith('#') && !line.startsWith('---') && !line.includes(':'));
34
- return firstBodyLine ? firstBodyLine.slice(0, 180) : undefined;
35
- }
36
- catch {
37
- return undefined;
38
- }
39
- }
40
16
  function describeMcpSpec(spec) {
41
17
  const command = typeof spec?.command === 'string' ? spec.command : undefined;
42
18
  if (command)
@@ -60,14 +36,15 @@ function discoverSkills(projectPath) {
60
36
  const seen = new Set();
61
37
  const items = [];
62
38
  for (const root of roots) {
63
- for (const name of listDirectories(root.dir)) {
64
- if (seen.has(name))
39
+ for (const skill of discoverSkillDirectories(root.dir)) {
40
+ const { id } = skill;
41
+ if (seen.has(id))
65
42
  continue;
66
- seen.add(name);
43
+ seen.add(id);
67
44
  items.push({
68
- id: name,
69
- label: name,
70
- desc: readSkillDescription(path.join(root.dir, name)),
45
+ id,
46
+ label: id,
47
+ desc: skill.description,
71
48
  source: root.source,
72
49
  });
73
50
  }
@@ -138,6 +115,7 @@ async function discoverPluginsFromCli() {
138
115
  encoding: 'utf-8',
139
116
  timeout: 3000,
140
117
  stdio: ['ignore', 'pipe', 'pipe'],
118
+ windowsHide: process.platform === 'win32',
141
119
  });
142
120
  const parsed = JSON.parse(output);
143
121
  const list = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.installed) ? parsed.installed : [];
@@ -1,19 +1,7 @@
1
- import fs from 'fs';
2
1
  import os from 'os';
3
2
  import path from 'path';
4
3
  import { execCodexCliSync } from '../../../utils/codex-cli.js';
5
- function listDirectories(dir) {
6
- try {
7
- if (!fs.existsSync(dir))
8
- return [];
9
- return fs.readdirSync(dir, { withFileTypes: true })
10
- .filter(entry => entry.isDirectory())
11
- .map(entry => entry.name);
12
- }
13
- catch {
14
- return [];
15
- }
16
- }
4
+ import { discoverSkillDirectories } from '../skill-discovery.js';
17
5
  function discoverSkills(ctx) {
18
6
  const roots = [
19
7
  { dir: path.join(ctx.projectPath, '.codex', 'skills'), source: 'project' },
@@ -23,11 +11,12 @@ function discoverSkills(ctx) {
23
11
  const seen = new Set();
24
12
  const out = [];
25
13
  for (const root of roots) {
26
- for (const id of listDirectories(root.dir)) {
14
+ for (const skill of discoverSkillDirectories(root.dir)) {
15
+ const { id } = skill;
27
16
  if (seen.has(id))
28
17
  continue;
29
18
  seen.add(id);
30
- out.push({ id, label: id, source: root.source });
19
+ out.push({ id, label: id, desc: skill.description, source: root.source });
31
20
  }
32
21
  }
33
22
  return out;
@@ -0,0 +1,55 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { parseDocument } from 'yaml';
4
+ function readSkillMetadata(skillDir) {
5
+ const skillFile = path.join(skillDir, 'SKILL.md');
6
+ try {
7
+ if (!fs.statSync(skillFile).isFile())
8
+ return undefined;
9
+ const text = fs.readFileSync(skillFile, 'utf-8');
10
+ const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
11
+ if (!match)
12
+ return undefined;
13
+ const document = parseDocument(match[1]);
14
+ if (document.errors.length > 0)
15
+ return undefined;
16
+ const metadata = document.toJS();
17
+ if (typeof metadata?.name !== 'string' || !metadata.name.trim())
18
+ return undefined;
19
+ if (typeof metadata.description !== 'string' || !metadata.description.trim())
20
+ return undefined;
21
+ return {
22
+ id: metadata.name.trim(),
23
+ description: metadata.description.trim(),
24
+ };
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
30
+ /** Return only directories that satisfy the Codex/Claude skill file contract. */
31
+ export function discoverSkillDirectories(root) {
32
+ try {
33
+ if (!fs.existsSync(root))
34
+ return [];
35
+ return fs.readdirSync(root, { withFileTypes: true })
36
+ .filter(entry => !entry.name.startsWith('.'))
37
+ .filter(entry => entry.isDirectory() || entry.isSymbolicLink())
38
+ .map(entry => {
39
+ const dir = path.join(root, entry.name);
40
+ try {
41
+ if (!fs.statSync(dir).isDirectory())
42
+ return undefined;
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ const metadata = readSkillMetadata(dir);
48
+ return metadata;
49
+ })
50
+ .filter((entry) => Boolean(entry));
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ }
@@ -177,10 +177,14 @@ export function isValidChannelName(name) {
177
177
  return typeof name === 'string' && name.length > 0 && !name.includes(SEP);
178
178
  }
179
179
  export function buildReloadHooks(deps) {
180
- const { channelLoader, channelInstances, registerChannelInstance, unregisterChannelInstance, messageQueue, handoffRuntime, onChannelStarted, onChannelConnected } = deps;
180
+ const { channelLoader, channelInstances, registerChannelInstance, unregisterChannelInstance, messageQueue, handoffRuntime, onChannelStarted, onChannelConnected, onAgentReloaded, stageAgentRunners, } = deps;
181
181
  const drainDelayMs = deps.drainDelayMs ?? 500;
182
182
  const drainTimeoutMs = deps.drainTimeoutMs ?? 30000;
183
183
  return {
184
+ stageAgentRunners,
185
+ async afterReload(agent) {
186
+ await onAgentReloaded?.(agent);
187
+ },
184
188
  async prepareHandoffReload(aid) {
185
189
  if (!handoffRuntime)
186
190
  return;
@@ -192,7 +196,7 @@ export function buildReloadHooks(deps) {
192
196
  if (!handoffRuntime)
193
197
  return;
194
198
  try {
195
- await handoffRuntime.recover([aid]);
199
+ await handoffRuntime.recover([aid], { discardExpired: false });
196
200
  }
197
201
  finally {
198
202
  handoffRuntime.resumeAgent(aid);
@@ -284,11 +288,24 @@ export function buildReloadHooks(deps) {
284
288
  return;
285
289
  }
286
290
  registerChannelInstance(newInst);
287
- onChannelStarted?.(newInst);
288
- await newInst.connect();
289
- channelInstances.push(newInst);
290
- await onChannelConnected?.(newInst);
291
- logger.info(`[Reload] Started channel: ${channelName}`);
291
+ try {
292
+ onChannelStarted?.(newInst);
293
+ await newInst.connect();
294
+ channelInstances.push(newInst);
295
+ await onChannelConnected?.(newInst);
296
+ logger.info(`[Reload] Started channel: ${channelName}`);
297
+ }
298
+ catch (error) {
299
+ try {
300
+ await newInst.disconnect();
301
+ }
302
+ catch { }
303
+ unregisterChannelInstance?.(channelName);
304
+ const index = channelInstances.indexOf(newInst);
305
+ if (index >= 0)
306
+ channelInstances.splice(index, 1);
307
+ throw error;
308
+ }
292
309
  },
293
310
  };
294
311
  }
@@ -4,7 +4,7 @@ import { resolvePaths, resolveRoot } from '../../paths.js';
4
4
  import path from 'path';
5
5
  import { ConfigTarget, ensureFile as cfgEnsure, read as cfgRead, write as cfgWrite, } from '../../config/config-manager.js';
6
6
  import { CreateStatusWriter, readCreateStatus } from '../message/create-status.js';
7
- import { deriveAgentProjectPath } from '../../utils/project-path.js';
7
+ import { agentProjectRootFromDefaults, deriveAgentProjectPath } from '../../utils/project-path.js';
8
8
  import { uploadAvatar } from '../../utils/avatar-upload.js';
9
9
  import { agentmdGet, agentmdPut, updateAgentMdFrontmatterName } from '../../aun/aid/agentmd.js';
10
10
  import { isValidAid } from '../../aun/aid/validation.js';
@@ -367,7 +367,7 @@ export async function execAgentAction(action, args, peerId, eventBus) {
367
367
  if (!isValidAid(owner))
368
368
  return { error: `无效 owner AID: ${owner}`, code: 'INVALID_ARGS' };
369
369
  if (!a.project || typeof a.project !== 'string') {
370
- return { error: 'project 缺失且无法兜底(需 defaults.projects.rootPath/defaultPath)', code: 'INVALID_ARGS' };
370
+ return { error: 'project 缺失(调用方应先解析默认项目路径)', code: 'INVALID_ARGS' };
371
371
  }
372
372
  const model = typeof a.model === 'string' && a.model.trim() ? a.model.trim() : undefined;
373
373
  const rawEffort = typeof a.effort === 'string' && a.effort.trim() ? a.effort.trim() : undefined;
@@ -401,9 +401,10 @@ export async function execAgentAction(action, args, peerId, eventBus) {
401
401
  if (action === 'enable' || action === 'disable') {
402
402
  if (!a.aid)
403
403
  return { error: '缺少 aid', code: 'INVALID_ARGS' };
404
- const res = action === 'enable' ? await agentEnable(a.aid) : await agentDisable(a.aid);
404
+ const options = { force: a.force === true };
405
+ const res = action === 'enable' ? await agentEnable(a.aid, options) : await agentDisable(a.aid, options);
405
406
  if (!('ok' in res) || res.ok !== true)
406
- return { error: res.error, code: classifyError(res.error) };
407
+ return { error: res.error, code: res.code || classifyError(res.error) };
407
408
  eventBus?.publish({
408
409
  type: action === 'enable' ? 'agent:enabled' : 'agent:disabled',
409
410
  aid: res.aid,
@@ -415,9 +416,9 @@ export async function execAgentAction(action, args, peerId, eventBus) {
415
416
  if (action === 'reload') {
416
417
  if (!a.aid)
417
418
  return { error: '缺少 aid', code: 'INVALID_ARGS' };
418
- const res = await agentReload(a.aid);
419
+ const res = await agentReload(a.aid, { force: a.force === true });
419
420
  if (!('ok' in res) || res.ok !== true)
420
- return { error: res.error, code: classifyError(res.error) };
421
+ return { error: res.error, code: res.code || classifyError(res.error) };
421
422
  eventBus?.publish({ type: 'agent:reloaded', aid: a.aid, timestamp: Date.now() });
422
423
  return { data: { aid: a.aid, reloaded: true } };
423
424
  }
@@ -564,14 +565,16 @@ export async function execAgentUpdate(args) {
564
565
  }
565
566
  return { data: { ...data, saved: true, ...(hasConfigPatch ? { requiresReload: true } : {}) } };
566
567
  }
567
- /** project 兜底:显式值 > rootPath 合成 > defaultPath > undefined */
568
+ /**
569
+ * project 解析与 ec agent create 保持一致:
570
+ * 显式值 > 默认项目根目录 + AID 前缀。
571
+ * 默认项目根目录由 defaults.projects.rootPath/defaultPath 或运行时根目录推导。
572
+ */
568
573
  export function resolveProjectPath(explicit, aid, defaults) {
569
574
  if (explicit && explicit.trim())
570
575
  return explicit;
571
- const root = defaults?.projects?.rootPath;
572
- if (root)
573
- return deriveAgentProjectPath(root, aid);
574
- return defaults?.projects?.defaultPath;
576
+ const root = agentProjectRootFromDefaults(defaults, resolveRoot());
577
+ return deriveAgentProjectPath(root, aid);
575
578
  }
576
579
  /** name=agent 的 menu.query:查单个 agent 详情,附构建进度(D3)。 */
577
580
  export async function execAgentQuery(args) {
@@ -33,6 +33,15 @@ export function parseCliIntent(inputArgv, source = 'menu.cli', options = {}) {
33
33
  return parseAidCommand(argv, source);
34
34
  if (cmd === 'storage')
35
35
  return parseStorageCommand(argv, source);
36
+ if (cmd === 'version') {
37
+ const parsed = parseArgs(argv.slice(1));
38
+ if (parsed.positionals.length > 0)
39
+ return raw(source, argv, 'Unexpected version positional args');
40
+ const unsupported = Object.keys(parsed.args).filter(key => key !== 'format' && key !== 'json');
41
+ if (unsupported.length > 0)
42
+ return raw(source, argv, `Unsupported version option: --${unsupported[0]}`);
43
+ return recognized('ec.version', 'relation', source, parsed.args, argv);
44
+ }
36
45
  if (cmd === 'status') {
37
46
  return recognized('system.status', 'process', source, parseArgs(argv.slice(1)), argv);
38
47
  }