evolcore 0.0.35 → 0.0.37

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 (224) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +6 -0
  3. package/bin/install-codex-managed-hooks.mjs +20 -3
  4. package/dist/agents/baseagent-availability.js +1 -1
  5. package/dist/agents/baseagent.js +88 -0
  6. package/dist/agents/claude-runner.js +59 -12
  7. package/dist/agents/codex/app-server-client.js +18 -1
  8. package/dist/agents/codex-runner.js +262 -21
  9. package/dist/agents/ecagent-runner.js +47 -11
  10. package/dist/agents/gemini-runner.js +36 -12
  11. package/dist/aun/aid/client.js +4 -3
  12. package/dist/aun/aid/control-aid.js +270 -8
  13. package/dist/aun/aid/identity.js +6 -3
  14. package/dist/aun/aid/ownership-operation.js +58 -0
  15. package/dist/aun/aid/store.js +1 -0
  16. package/dist/aun/group/fs-download.js +67 -2
  17. package/dist/aun/group/history.js +20 -5
  18. package/dist/aun/group/operations.js +8 -2
  19. package/dist/aun/menu/client.js +39 -2
  20. package/dist/aun/menu/transport.js +1 -1
  21. package/dist/aun/msg/history.js +43 -4
  22. package/dist/aun/msg/managed-operation.js +30 -53
  23. package/dist/aun/msg/p2p.js +51 -15
  24. package/dist/aun/outbox.js +4 -0
  25. package/dist/channels/aun.js +260 -73
  26. package/dist/channels/daemon.js +6 -4
  27. package/dist/channels/feishu.js +3 -0
  28. package/dist/cli/agent-command.js +161 -223
  29. package/dist/cli/agent-create.js +190 -223
  30. package/dist/cli/agent.js +3 -1
  31. package/dist/cli/aid-bind-command.js +53 -0
  32. package/dist/cli/aun-commands.js +384 -91
  33. package/dist/cli/bench.js +1 -1
  34. package/dist/cli/cli-argv.js +74 -0
  35. package/dist/cli/daemon-commands.js +105 -74
  36. package/dist/cli/diag.js +1 -1
  37. package/dist/cli/fs-command.js +18 -19
  38. package/dist/cli/getmeta-command.js +159 -6
  39. package/dist/cli/index.js +6 -12
  40. package/dist/cli/init-channel.js +8 -55
  41. package/dist/cli/init.js +125 -218
  42. package/dist/cli/queue-command.js +11 -8
  43. package/dist/cli/restart-monitor.js +177 -85
  44. package/dist/cli/session-command.js +1 -1
  45. package/dist/cli/stats.js +7 -5
  46. package/dist/cli/thread-command.js +103 -30
  47. package/dist/cli/trigger-command.js +1 -1
  48. package/dist/cli/watch-msg-diag.js +1 -0
  49. package/dist/config/access-policy.js +2 -2
  50. package/dist/config/boot-log.js +14 -11
  51. package/dist/config/config-field-policy.js +9 -1
  52. package/dist/config/config-manager.js +176 -90
  53. package/dist/config/config-operation-service.js +7 -14
  54. package/dist/config/contact-book-store.js +142 -26
  55. package/dist/config/contact-book.js +4 -2
  56. package/dist/config/lifecycle.js +1 -1
  57. package/dist/config/owner-config.js +96 -0
  58. package/dist/config/peer-role-resolver.js +12 -18
  59. package/dist/config/providers-config.js +382 -0
  60. package/dist/config/providers-import.js +74 -0
  61. package/dist/config/providers-management.js +328 -0
  62. package/dist/config/providers.js +22 -0
  63. package/dist/config/resolved-config-op.js +17 -14
  64. package/dist/config/snapshot.js +28 -16
  65. package/dist/config-store.js +18 -14
  66. package/dist/core/agent-ipc-registration.js +21 -63
  67. package/dist/core/agent-runtime.js +16 -5
  68. package/dist/core/auth/agent-delegation.js +199 -25
  69. package/dist/core/auth/auth-gateway.js +44 -2
  70. package/dist/core/auth/authorization-denial.js +1 -1
  71. package/dist/core/auth/debug-context.js +2 -1
  72. package/dist/core/auth/delegation-authorization.js +2 -2
  73. package/dist/core/auth/delegation-diagnostics.js +4 -1
  74. package/dist/core/auth/operation-authorizer.js +10 -1
  75. package/dist/core/auth/operation-catalog.js +19 -1
  76. package/dist/core/bootstrap-service.js +43 -20
  77. package/dist/core/channel-loader.js +0 -1
  78. package/dist/core/channel-runtime.js +30 -4
  79. package/dist/core/command/agent-control.js +196 -37
  80. package/dist/core/command/cli-intent-parser.js +60 -4
  81. package/dist/core/command/command-handler.js +212 -60
  82. package/dist/core/command/connect-menu.js +1 -0
  83. package/dist/core/command/diag-service.js +5 -4
  84. package/dist/core/command/file-search.js +368 -0
  85. package/dist/core/command/menu-catalog.js +2 -1
  86. package/dist/core/command/menu-handler.js +292 -107
  87. package/dist/core/command/menu-protocol.js +23 -0
  88. package/dist/core/command/role-menu.js +7 -19
  89. package/dist/core/command/skill-slash.js +130 -25
  90. package/dist/core/command/slash-handler.js +101 -53
  91. package/dist/core/command/topic-slash.js +16 -5
  92. package/dist/core/daemon-bootstrap.js +7 -1
  93. package/dist/core/daemon-control.js +19 -1
  94. package/dist/core/daemon-lifecycle.js +2 -1
  95. package/dist/core/event-catalog.js +2 -0
  96. package/dist/core/evolagent-registry.js +13 -2
  97. package/dist/core/evolagent.js +3 -6
  98. package/dist/core/handoff/ipc-registration.js +2 -2
  99. package/dist/core/handoff/runtime.js +40 -6
  100. package/dist/core/handoff/store.js +1 -0
  101. package/dist/core/inference/text-inference.js +95 -6
  102. package/dist/core/ipc-registration.js +43 -24
  103. package/dist/core/memory/consolidation-context.js +4 -1
  104. package/dist/core/memory/consolidation.js +25 -14
  105. package/dist/core/message/aun-ipc-sender.js +296 -88
  106. package/dist/core/message/aun-request-registry.js +226 -0
  107. package/dist/core/message/create-status.js +33 -4
  108. package/dist/core/message/message-bridge.js +62 -13
  109. package/dist/core/message/message-log.js +0 -1
  110. package/dist/core/message/message-queue.js +4 -1
  111. package/dist/core/message/message-utils.js +8 -1
  112. package/dist/core/message/peer-mode.js +17 -9
  113. package/dist/core/message/response-engine.js +266 -124
  114. package/dist/core/message/retry-scheduler.js +11 -8
  115. package/dist/core/model/catalog-service.js +60 -18
  116. package/dist/core/model/model-catalog.js +112 -9
  117. package/dist/core/model/model-fallback.js +94 -26
  118. package/dist/core/ownership/owner-resolver.js +687 -0
  119. package/dist/core/permission/approval-gateway.js +196 -62
  120. package/dist/core/permission/ec-command-parser.js +138 -25
  121. package/dist/core/permission/filesystem-approval-scope.js +141 -0
  122. package/dist/core/permission/protected-paths.js +14 -1
  123. package/dist/core/permission/sandbox-runtime.js +171 -18
  124. package/dist/core/permission/tool-policy.js +13 -2
  125. package/dist/core/role/runtime-policy.js +3 -4
  126. package/dist/core/session/session-idle-monitor.js +10 -8
  127. package/dist/core/session/session-manager.js +72 -45
  128. package/dist/core/session/session-mapper.js +18 -7
  129. package/dist/core/session/session-renew.js +5 -4
  130. package/dist/core/session/session-title.js +2 -1
  131. package/dist/core/session/session-turn-coordinator.js +4 -2
  132. package/dist/core/skill/index-generator.js +2 -16
  133. package/dist/core/task/task-recovery-service.js +15 -2
  134. package/dist/core/thread/command-parser.js +28 -13
  135. package/dist/core/thread/index.js +1 -0
  136. package/dist/core/thread/ipc-operation.js +11 -8
  137. package/dist/core/thread/thread-operation.js +79 -44
  138. package/dist/core/thread/thread-route.js +54 -6
  139. package/dist/core/thread/thread-service.js +236 -45
  140. package/dist/core/thread/topic-id.js +248 -0
  141. package/dist/eck/kit-renderer.js +1 -1
  142. package/dist/eck/message-renderer.js +12 -2
  143. package/dist/index.js +50 -27
  144. package/dist/ipc.js +59 -6
  145. package/dist/paths.js +1 -0
  146. package/dist/product.js +1 -0
  147. package/dist/response-system/engines/v1/proactive-flow.js +10 -3
  148. package/dist/stats/db.js +8 -0
  149. package/dist/stats/writer.js +26 -4
  150. package/dist/trigger/authorization.js +48 -3
  151. package/dist/trigger/feedback.js +28 -10
  152. package/dist/trigger/ipc-service.js +86 -10
  153. package/dist/trigger/local-files.js +55 -23
  154. package/dist/trigger/scheduler.js +57 -11
  155. package/dist/trigger/system-definitions.js +1 -0
  156. package/dist/trigger/validation.js +44 -15
  157. package/dist/utils/aid-bind.js +17 -297
  158. package/dist/utils/avatar-upload.js +16 -4
  159. package/dist/utils/cross-platform.js +115 -36
  160. package/dist/utils/ecweb-supervisor.js +1 -1
  161. package/dist/utils/ecweb-utils.js +8 -1
  162. package/dist/utils/error-utils.js +44 -6
  163. package/dist/utils/instance-registry.js +12 -2
  164. package/dist/utils/npm-ops.js +102 -27
  165. package/dist/utils/package-version-info.js +72 -27
  166. package/dist/utils/restart-safety.js +50 -0
  167. package/dist/utils/upgrade-jobs.js +304 -0
  168. package/dist/utils/windows-autostart.js +17 -10
  169. package/kits/docs/INDEX.md +5 -0
  170. package/kits/docs/aun/ABILITY_CALLING.md +239 -0
  171. package/kits/docs/evolcore/INDEX.md +14 -3
  172. package/kits/docs/evolcore/agent-create.md +55 -141
  173. package/kits/docs/evolcore/agent.md +38 -16
  174. package/kits/docs/evolcore/aid.md +34 -0
  175. package/kits/docs/evolcore/config.md +20 -1
  176. package/kits/docs/evolcore/event.md +2 -2
  177. package/kits/docs/evolcore/fs.md +18 -2
  178. package/kits/docs/evolcore/group-collaboration.md +13 -246
  179. package/kits/docs/evolcore/group.md +2 -1
  180. package/kits/docs/evolcore/memory-consolidation-batches.md +1 -1
  181. package/kits/docs/evolcore/menu-protocol.md +65 -1
  182. package/kits/docs/evolcore/msg.md +64 -2
  183. package/kits/docs/evolcore/skill.md +86 -0
  184. package/kits/docs/evolcore/stats.md +6 -0
  185. package/kits/docs/evolcore/task.md +2 -0
  186. package/kits/docs/evolcore/thread-chain.md +145 -51
  187. package/kits/docs/evolcore/trigger.md +48 -3
  188. package/kits/eck_manifest.json +21 -0
  189. package/kits/eck_message_manifest.json +4 -4
  190. package/kits/migrations/migrate-role-config-v5.mjs +20 -7
  191. package/kits/rules/01-overview.md +2 -1
  192. package/kits/rules/03-identity.md +3 -1
  193. package/kits/rules/04-relation.md +1 -1
  194. package/kits/rules/07-memory-and-thread.md +1 -1
  195. package/kits/schemas/_meta.json +16 -1
  196. package/kits/schemas/agent-config.schema.13.json +44 -2
  197. package/kits/schemas/contact-book.schema.3.json +5 -0
  198. package/kits/schemas/daemon.schema.6.json +3 -1
  199. package/kits/schemas/daemon.schema.8.json +329 -0
  200. package/kits/schemas/defaults.schema.5.json +39 -3
  201. package/kits/schemas/providers.schema.1.json +76 -0
  202. package/kits/schemas/relation-config.schema.9.json +5 -1
  203. package/kits/skills/.switches.json +28 -0
  204. package/kits/skills/aid-ability/SKILL.md +214 -0
  205. package/kits/skills/ec-agent-create/SKILL.md +162 -0
  206. package/kits/skills/ec-group/SKILL.md +2 -1
  207. package/kits/skills/ec-group-collaboration/SKILL.md +228 -0
  208. package/kits/skills/ec-identity/SKILL.md +143 -0
  209. package/kits/skills/ec-skill/scripts/cli.mjs +36 -3
  210. package/kits/skills/ec-skill/scripts/skill.mjs +202 -15
  211. package/kits/skills/ec-trigger/SKILL.md +167 -0
  212. package/kits/skills/ec-trigger/references/examples.md +153 -0
  213. package/kits/skills/thread-ops/SKILL.md +108 -420
  214. package/kits/templates/message-fragments/thread-context.md +1 -2
  215. package/kits/templates/message-fragments/trigger-thread-check.md +1 -1
  216. package/kits/templates/roles/member.json +1 -1
  217. package/kits/templates/roles/visitor.json +1 -0
  218. package/kits/templates/system-fragments/bootstrap.md +1 -0
  219. package/kits/templates/system-fragments/channel.md +2 -1
  220. package/kits/templates/system-fragments/commands.md +5 -4
  221. package/kits/templates/system-fragments/identity.md +2 -0
  222. package/kits/templates/system-fragments/session.md +1 -1
  223. package/kits/templates/system-fragments/venue.md +1 -1
  224. package/package.json +4 -3
@@ -5,6 +5,7 @@ import { readInstalledEvolcoreVersion } from '../../utils/evolcore-version.js';
5
5
  import { compareStableSemver, parseStableSemver } from '../../utils/stable-semver.js';
6
6
  import { logger } from '../../utils/logger.js';
7
7
  import { validateIdleSeconds } from '../session/session-idle-monitor.js';
8
+ import { parseFileSearchArgs } from './file-search.js';
8
9
  export const MENU_REQUEST_TYPES = new Set([
9
10
  'menu.token.request',
10
11
  'menu.list',
@@ -13,6 +14,20 @@ export const MENU_REQUEST_TYPES = new Set([
13
14
  'menu.update',
14
15
  'menu.action',
15
16
  ]);
17
+ export function parseMenuEvent(value) {
18
+ if (!value || typeof value !== 'object' || Array.isArray(value))
19
+ throw Object.assign(new Error('Menu event must be an object'), { code: 'INVALID_EVENT' });
20
+ const event = value;
21
+ if (event.type !== 'menu.event' || !['upgrade.progress', 'upgrade.result'].includes(String(event.event))
22
+ || typeof event.requestId !== 'string' || !event.requestId.trim()
23
+ || typeof event.jobId !== 'string' || !/^job_[a-f0-9-]{36}$/.test(event.jobId)
24
+ || !Number.isSafeInteger(event.seq) || event.seq < 1
25
+ || !['upgrade-check', 'downloading', 'tarball-check', 'preflight', 'restart'].includes(String(event.phase))
26
+ || typeof event.status !== String.name.toLowerCase() || typeof event.message !== String.name.toLowerCase()) {
27
+ throw Object.assign(new Error('Invalid Menu event'), { code: 'INVALID_EVENT' });
28
+ }
29
+ return value;
30
+ }
16
31
  export function buildMenuClientProtectedHeaders(input) {
17
32
  const clientName = input.clientName ?? 'evol';
18
33
  if (clientName === 'ec-menu-client') {
@@ -377,6 +392,14 @@ export function validateMenuRequest(request) {
377
392
  return { code: 'INVALID_ARGUMENT', message: 'File fetch requires args.path' };
378
393
  }
379
394
  }
395
+ if (type === 'menu.action' && (request.name === 'file' || request.cmd === '/file') && request.action === 'search') {
396
+ try {
397
+ parseFileSearchArgs(request.args);
398
+ }
399
+ catch (error) {
400
+ return { code: 'INVALID_ARGUMENT', message: error.message };
401
+ }
402
+ }
380
403
  if ((request.name === 'file' || request.cmd === '/file') && request.args !== undefined) {
381
404
  const args = request.args;
382
405
  if (args.rootId !== undefined && (typeof args.rootId !== 'string' || args.rootId.trim().length === 0)) {
@@ -11,7 +11,7 @@ import { listOperations } from '../auth/operation-catalog.js';
11
11
  import { auditRoleMutation } from '../auth/authorization-audit.js';
12
12
  import { formatPeerKey, parsePeerKey } from '../relation/peer-identity.js';
13
13
  import { agentDir, agentRoleConfig, agentRolesIndex, agentRelationConfig, agentRelationsDir, resolvePaths } from '../../paths.js';
14
- import { atomicReadJson, atomicWrite, atomicWriteJson } from '../../utils/atomic-write.js';
14
+ import { atomicReadJson, atomicWrite } from '../../utils/atomic-write.js';
15
15
  import { fileCache } from '../daemon-file-cache.js';
16
16
  import { currentVersion } from '../../config/schema-registry.js';
17
17
  import { loadSchema } from '../../config/schema-registry.js';
@@ -22,6 +22,7 @@ import { isExplicitGroupId } from '../../aun/group/index.js';
22
22
  import { readJsonFile, readLastJsonlLine, scanChatDirs, scanMetaFiles } from '../session/session-fs-store.js';
23
23
  import { constrainResolvedModelForRole } from '../model/model-permission.js';
24
24
  import { resolveRuntimePermissionMode, resolveRuntimeStringField } from '../role/runtime-policy.js';
25
+ import { mutateContactBookTransactionSync } from '../../config/contact-book-store.js';
25
26
  import { readRoleDefinition, readRoleRegistry, registerRole, writeRoleDefinition, writeRoleRegistry, } from '../../config/role-service.js';
26
27
  import { clearRoleStoreCache, readRoleStore, roleRegistryExists } from '../../config/role-store.js';
27
28
  const ROLE_MENU_SCHEMA_VERSION = 1;
@@ -1428,24 +1429,11 @@ function normalizeRelationForScene(value, scene) {
1428
1429
  return normalized;
1429
1430
  }
1430
1431
  function commitJournal(self, changes) {
1431
- const journalFile = roleJournalPath(self);
1432
- const journal = { $schema_version: 1, self, state: 'prepared', changes };
1433
- atomicWriteJson(journalFile, journal);
1434
- try {
1435
- for (const change of changes)
1436
- applyFileContent(change.file, change.after);
1437
- journal.state = 'committed';
1438
- atomicWriteJson(journalFile, journal);
1439
- removeJournalFiles(journalFile);
1440
- invalidateChanges(changes);
1441
- }
1442
- catch (error) {
1443
- try {
1444
- recoverRoleMutationSync(self);
1445
- }
1446
- catch { }
1447
- throw error;
1448
- }
1432
+ mutateContactBookTransactionSync({
1433
+ selfAid: self,
1434
+ actor: 'role-delete-transaction',
1435
+ mutation: { type: 'sync-management-roles' },
1436
+ }, changes);
1449
1437
  }
1450
1438
  function removeJournalFiles(journalFile) {
1451
1439
  // Remove backups first. If the process exits mid-cleanup, a committed main
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import fs from 'fs';
14
14
  import path from 'path';
15
+ import { spawnSync } from 'child_process';
15
16
  import { agentDir, getPackageRoot, resolveRoot } from '../../paths.js';
16
17
  import { resolveAllSkillStates } from '../skill/switch-resolver.js';
17
18
  import { readSkillDescription } from '../skill/index-generator.js';
@@ -21,7 +22,10 @@ import { resolveAgentLifecycle } from '../../config/lifecycle.js';
21
22
  const USAGE = [
22
23
  '用法:',
23
24
  ' /skill 技能概览(启用数 / 总数)',
24
- ' /skill list [all] 技能列表(默认仅启用;all 显示未启用的)',
25
+ ' /skill list [all|--all] [--filter <kw>]... [--page <n>] [--limit <n>]',
26
+ ' 技能列表(默认仅启用;all/--all 显示全部;超出 limit 条自动分页并提示翻页和 filter 方法)',
27
+ ' /skill load <name> 加载技能正文(输出 SKILL.md 内容 + skillDir)',
28
+ ' /skill path <name> 查看技能 SKILL.md 完整路径(含状态和时间戳)',
25
29
  ' /skill index 查看技能索引加载情况(哪些索引文件被加载、时间、技能数)',
26
30
  ' /skill index builtin 查看内置技能索引正文',
27
31
  ' /skill index local 查看本机技能索引正文',
@@ -52,7 +56,10 @@ export function skillHelpEntries(ctx) {
52
56
  const roles = [ctx.role];
53
57
  const out = [
54
58
  { command: '/skill list', description: '已启用的技能列表', category, roles },
55
- { command: '/skill list all', description: '全部技能列表(含未启用)', category, roles },
59
+ { command: '/skill list --all', description: '全部技能列表(含未启用)', category, roles },
60
+ { command: '/skill list', description: '按关键词筛选技能(匹配名称+描述;组内逗号为或,多个 --filter 为且)', args: "--filter '<kw1,kw2>'", category, roles },
61
+ { command: '/skill load', description: '加载技能正文(输出 SKILL.md 内容 + skillDir)', args: '<name>', category, roles },
62
+ { command: '/skill path', description: '查看技能 SKILL.md 路径(含状态和时间戳)', args: '<name>', category, roles },
56
63
  { command: '/skill index', description: '技能索引加载情况(文件、时间、技能数)', category, roles },
57
64
  { command: '/skill index builtin', description: '查看内置技能索引正文', category, roles },
58
65
  { command: '/skill index local', description: '查看本机技能索引正文', category, roles },
@@ -76,29 +83,16 @@ function skillRoots(selfAid) {
76
83
  function agentRootFor(selfAid) {
77
84
  return selfAid ? agentDir(selfAid) : undefined;
78
85
  }
86
+ function overviewLine(states) {
87
+ const enabled = states.filter(s => s.enabled).length;
88
+ return `${states.length} 个技能,${enabled} 个启用`;
89
+ }
79
90
  function sourceLabel(source) {
80
91
  return source === 'builtin' ? '内置' : '本机';
81
92
  }
82
93
  function stateLabel(s) {
83
94
  return s.enabled ? '开' : '关';
84
95
  }
85
- function overviewLine(states) {
86
- const enabled = states.filter(s => s.enabled).length;
87
- return `${states.length} 个技能,${enabled} 个启用`;
88
- }
89
- function formatList(states, showAll) {
90
- const shown = showAll ? states : states.filter(s => s.enabled);
91
- if (shown.length === 0) {
92
- return showAll ? '(没有任何技能)' : '(没有启用的技能;用 /skill list all 查看全部)';
93
- }
94
- const nameW = Math.max(20, ...shown.map(s => s.name.length + 2));
95
- const lines = [`${overviewLine(states)}${showAll ? '' : '(仅列启用;/skill list all 查看全部)'}`, ''];
96
- for (const s of shown) {
97
- const lock = s.locked ? ' [locked]' : '';
98
- lines.push(` ${s.name.padEnd(nameW)}${sourceLabel(s.source).padEnd(6)}${stateLabel(s)}${lock}`);
99
- }
100
- return lines.join('\n');
101
- }
102
96
  function formatInfo(s) {
103
97
  const desc = readSkillDescription(s.skillDir);
104
98
  const lines = [
@@ -136,13 +130,15 @@ function inspectSkillIndexes(agentRoot, selfAid, lifecycle) {
136
130
  // 只关心指向 <agentRoot>/skills/.index-*.md 的段;override 可能加段或改路径,
137
131
  // 所以按解析后的路径判断,而不是按段 id 匹配。
138
132
  const skillsDir = path.join(agentRoot, 'skills');
139
- // lifecycle 与渲染器同源解析:显式非法值按 null(fail-closed),缺省按 active 兼容。
140
- const resolvedLifecycle = resolveAgentLifecycle({ lifecycle });
133
+ // /skill index 是诊断工具,运行在已活跃的会话里;lifecycle 缺失或无法解析时
134
+ // 按 'active' 处理,否则 when: lifecycle = active 的段永远判成"未加载",
135
+ // 产生误导性的诊断结果。
136
+ const resolvedLifecycle = resolveAgentLifecycle({ lifecycle }) ?? 'active';
141
137
  const vars = {
142
138
  selfAid,
143
139
  EVOLCORE_HOME: resolveRoot(),
144
140
  AGENT_DIR: agentRoot,
145
- ...(resolvedLifecycle === null ? {} : { lifecycle: resolvedLifecycle }),
141
+ lifecycle: resolvedLifecycle,
146
142
  };
147
143
  const out = [];
148
144
  for (const section of sections) {
@@ -275,8 +271,47 @@ export async function handleSkillSlash(ctx) {
275
271
  return error('无法确定当前 agent 目录');
276
272
  try {
277
273
  if (sub === 'list') {
278
- const showAll = args[1] === 'all';
279
- return result(formatList(resolveAllSkillStates(root), showAll));
274
+ // 参数解析:/skill list [all] [--all] [--filter <kw>] [--page <n>] [--limit <n>]
275
+ const showAll = args.includes('all') || args.includes('--all');
276
+ const filterArgs = [];
277
+ let page = 1;
278
+ let limit = 20;
279
+ for (let i = 1; i < args.length; i++) {
280
+ if (args[i] === '--filter' && args[i + 1] && !args[i + 1].startsWith('--')) {
281
+ // slash 内容不经 shell,页脚示例里的单/双引号会原样传进来,这里剥掉
282
+ filterArgs.push(args[++i].replace(/^(['"])(.*)\1$/, '$2'));
283
+ }
284
+ else if (args[i] === '--page' && args[i + 1]) {
285
+ page = parseInt(args[++i], 10) || 1;
286
+ }
287
+ else if (args[i] === '--limit' && args[i + 1]) {
288
+ limit = parseInt(args[++i], 10) || 20;
289
+ }
290
+ }
291
+ // 调 skill.mjs CLI,以 skill-slash 的 commandStyle=slash 传入,页脚用 /skill list 格式
292
+ const cliScript = path.join(getPackageRoot(), 'kits', 'skills', 'ec-skill', 'scripts', 'cli.mjs');
293
+ const cliArgs = ['list'];
294
+ if (showAll)
295
+ cliArgs.push('--all');
296
+ for (const f of filterArgs)
297
+ cliArgs.push('--filter', f);
298
+ cliArgs.push('--page', String(page), '--limit', String(limit));
299
+ // commandStyle 通过环境变量传入,skill.mjs 读取后生成 /skill list 格式的翻页提示
300
+ const r = spawnSync(process.execPath, [cliScript, ...cliArgs], {
301
+ encoding: 'utf-8',
302
+ // daemon 托管多个 agent,自身 env 里没有当前 agent 身份;必须显式传入,
303
+ // 否则子进程定位不到 Agent 级 .switches.json,启用状态会算错
304
+ env: {
305
+ ...process.env,
306
+ SKILL_COMMAND_STYLE: 'slash',
307
+ EVOLCORE_SELF_AID: ctx.selfAid,
308
+ EVOLCORE_AGENT_DIR: root,
309
+ },
310
+ });
311
+ if (r.error)
312
+ return error(`调用 skill CLI 失败: ${r.error.message}`);
313
+ const out = (r.stdout || '').trim();
314
+ return result(out || (r.stderr || '').trim() || '(无输出)');
280
315
  }
281
316
  if (sub === 'show' || sub === 'info') {
282
317
  const name = args[1];
@@ -284,7 +319,7 @@ export async function handleSkillSlash(ctx) {
284
319
  return error('用法: /skill show <name>');
285
320
  const found = resolveAllSkillStates(root).find(s => s.name === name);
286
321
  if (!found)
287
- return error(`技能不存在: ${name}\n用 /skill list all 查看全部技能`);
322
+ return error(`技能不存在: ${name}\n用 /skill list --all 查看全部技能`);
288
323
  return result(formatInfo(found));
289
324
  }
290
325
  if (sub === 'index') {
@@ -297,6 +332,76 @@ export async function handleSkillSlash(ctx) {
297
332
  }
298
333
  return result(formatIndexOverview(inspectSkillIndexes(root, ctx.selfAid, ctx.lifecycle), ctx.selfAid));
299
334
  }
335
+ if (sub === 'path') {
336
+ const name = args[1];
337
+ if (!name)
338
+ return error('用法: /skill path <name>');
339
+ const states = resolveAllSkillStates(root);
340
+ const found = states.filter(s => s.name === name);
341
+ if (found.length === 0)
342
+ return error(`技能不存在: ${name}\n用 /skill list --all 查看全部技能`);
343
+ const lines = [];
344
+ let newestMtime = 0;
345
+ let newestPath = '';
346
+ for (const s of found) {
347
+ const skillMd = path.join(s.skillDir, 'SKILL.md');
348
+ const exists = fs.existsSync(skillMd);
349
+ const mtime = exists ? fs.statSync(skillMd).mtimeMs : 0;
350
+ const mtimeStr = exists ? new Date(mtime).toLocaleString('zh-CN') : '(文件不存在)';
351
+ const stateStr = s.enabled ? '开' : '关';
352
+ lines.push(`${s.source.padEnd(8)}${stateStr} ${skillMd} (${mtimeStr})`);
353
+ if (mtime > newestMtime) {
354
+ newestMtime = mtime;
355
+ newestPath = skillMd;
356
+ }
357
+ }
358
+ if (found.length > 1)
359
+ lines.push(`\n建议: ${newestPath}`);
360
+ return result(lines.join('\n'));
361
+ }
362
+ if (sub === 'load') {
363
+ const name = args[1];
364
+ if (!name)
365
+ return error('用法: /skill load <name> [--source builtin|local] [--with-frontmatter]');
366
+ const withFrontmatter = args.includes('--with-frontmatter');
367
+ const sourceArg = (() => {
368
+ const i = args.indexOf('--source');
369
+ return i >= 0 ? args[i + 1] : undefined;
370
+ })();
371
+ if (sourceArg && sourceArg !== 'builtin' && sourceArg !== 'local') {
372
+ return error('--source 只能是 builtin 或 local');
373
+ }
374
+ const states = resolveAllSkillStates(root);
375
+ let candidates = states.filter(s => s.name === name);
376
+ if (sourceArg)
377
+ candidates = candidates.filter(s => s.source === sourceArg);
378
+ if (candidates.length === 0) {
379
+ const other = states.find(s => s.name === name);
380
+ if (!other)
381
+ return error(`技能不存在: ${name}\n用 /skill list --all 查看全部技能`);
382
+ // 只可能是 --source 过滤掉了:技能在另一个来源
383
+ const label = sourceArg === 'builtin' ? '内置级' : '本机级';
384
+ return error(`${label}没有技能 ${name}(该技能来自 ${other.source},去掉 --source 或改用 --source ${other.source})`);
385
+ }
386
+ if (candidates.length > 1) {
387
+ const paths = candidates.map(s => ` --source ${s.source} ${path.join(s.skillDir, 'SKILL.md')}`).join('\n');
388
+ return error(`技能 ${name} 在多个来源中存在,请用 --source 指定:\n${paths}`);
389
+ }
390
+ const skill = candidates[0];
391
+ if (!skill.enabled) {
392
+ return error(`技能 ${name} 未启用,请先执行: ec skill enable ${name}`);
393
+ }
394
+ const skillMd = path.join(skill.skillDir, 'SKILL.md');
395
+ if (!fs.existsSync(skillMd))
396
+ return error(`SKILL.md 不存在: ${skillMd}`);
397
+ let content = fs.readFileSync(skillMd, 'utf-8');
398
+ if (!withFrontmatter) {
399
+ // 去掉 frontmatter(--- ... --- 块)
400
+ content = content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '');
401
+ }
402
+ const footer = `\n---\nskillDir: ${skill.skillDir}\n`;
403
+ return result(content.trimStart() + footer);
404
+ }
300
405
  if (sub === 'where')
301
406
  return result(formatWhere(ctx.selfAid));
302
407
  if (sub === 'refresh') {