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.
- package/CHANGELOG.md +42 -0
- package/README.md +6 -0
- package/bin/install-codex-managed-hooks.mjs +20 -3
- package/dist/agents/baseagent-availability.js +1 -1
- package/dist/agents/baseagent.js +88 -0
- package/dist/agents/claude-runner.js +59 -12
- package/dist/agents/codex/app-server-client.js +18 -1
- package/dist/agents/codex-runner.js +262 -21
- package/dist/agents/ecagent-runner.js +47 -11
- package/dist/agents/gemini-runner.js +36 -12
- package/dist/aun/aid/client.js +4 -3
- package/dist/aun/aid/control-aid.js +270 -8
- package/dist/aun/aid/identity.js +6 -3
- package/dist/aun/aid/ownership-operation.js +58 -0
- package/dist/aun/aid/store.js +1 -0
- package/dist/aun/group/fs-download.js +67 -2
- package/dist/aun/group/history.js +20 -5
- package/dist/aun/group/operations.js +8 -2
- package/dist/aun/menu/client.js +39 -2
- package/dist/aun/menu/transport.js +1 -1
- package/dist/aun/msg/history.js +43 -4
- package/dist/aun/msg/managed-operation.js +30 -53
- package/dist/aun/msg/p2p.js +51 -15
- package/dist/aun/outbox.js +4 -0
- package/dist/channels/aun.js +260 -73
- package/dist/channels/daemon.js +6 -4
- package/dist/channels/feishu.js +3 -0
- package/dist/cli/agent-command.js +161 -223
- package/dist/cli/agent-create.js +190 -223
- package/dist/cli/agent.js +3 -1
- package/dist/cli/aid-bind-command.js +53 -0
- package/dist/cli/aun-commands.js +384 -91
- package/dist/cli/bench.js +1 -1
- package/dist/cli/cli-argv.js +74 -0
- package/dist/cli/daemon-commands.js +105 -74
- package/dist/cli/diag.js +1 -1
- package/dist/cli/fs-command.js +18 -19
- package/dist/cli/getmeta-command.js +159 -6
- package/dist/cli/index.js +6 -12
- package/dist/cli/init-channel.js +8 -55
- package/dist/cli/init.js +125 -218
- package/dist/cli/queue-command.js +11 -8
- package/dist/cli/restart-monitor.js +177 -85
- package/dist/cli/session-command.js +1 -1
- package/dist/cli/stats.js +7 -5
- package/dist/cli/thread-command.js +103 -30
- package/dist/cli/trigger-command.js +1 -1
- package/dist/cli/watch-msg-diag.js +1 -0
- package/dist/config/access-policy.js +2 -2
- package/dist/config/boot-log.js +14 -11
- package/dist/config/config-field-policy.js +9 -1
- package/dist/config/config-manager.js +176 -90
- package/dist/config/config-operation-service.js +7 -14
- package/dist/config/contact-book-store.js +142 -26
- package/dist/config/contact-book.js +4 -2
- package/dist/config/lifecycle.js +1 -1
- package/dist/config/owner-config.js +96 -0
- package/dist/config/peer-role-resolver.js +12 -18
- package/dist/config/providers-config.js +382 -0
- package/dist/config/providers-import.js +74 -0
- package/dist/config/providers-management.js +328 -0
- package/dist/config/providers.js +22 -0
- package/dist/config/resolved-config-op.js +17 -14
- package/dist/config/snapshot.js +28 -16
- package/dist/config-store.js +18 -14
- package/dist/core/agent-ipc-registration.js +21 -63
- package/dist/core/agent-runtime.js +16 -5
- package/dist/core/auth/agent-delegation.js +199 -25
- package/dist/core/auth/auth-gateway.js +44 -2
- package/dist/core/auth/authorization-denial.js +1 -1
- package/dist/core/auth/debug-context.js +2 -1
- package/dist/core/auth/delegation-authorization.js +2 -2
- package/dist/core/auth/delegation-diagnostics.js +4 -1
- package/dist/core/auth/operation-authorizer.js +10 -1
- package/dist/core/auth/operation-catalog.js +19 -1
- package/dist/core/bootstrap-service.js +43 -20
- package/dist/core/channel-loader.js +0 -1
- package/dist/core/channel-runtime.js +30 -4
- package/dist/core/command/agent-control.js +196 -37
- package/dist/core/command/cli-intent-parser.js +60 -4
- package/dist/core/command/command-handler.js +212 -60
- package/dist/core/command/connect-menu.js +1 -0
- package/dist/core/command/diag-service.js +5 -4
- package/dist/core/command/file-search.js +368 -0
- package/dist/core/command/menu-catalog.js +2 -1
- package/dist/core/command/menu-handler.js +292 -107
- package/dist/core/command/menu-protocol.js +23 -0
- package/dist/core/command/role-menu.js +7 -19
- package/dist/core/command/skill-slash.js +130 -25
- package/dist/core/command/slash-handler.js +101 -53
- package/dist/core/command/topic-slash.js +16 -5
- package/dist/core/daemon-bootstrap.js +7 -1
- package/dist/core/daemon-control.js +19 -1
- package/dist/core/daemon-lifecycle.js +2 -1
- package/dist/core/event-catalog.js +2 -0
- package/dist/core/evolagent-registry.js +13 -2
- package/dist/core/evolagent.js +3 -6
- package/dist/core/handoff/ipc-registration.js +2 -2
- package/dist/core/handoff/runtime.js +40 -6
- package/dist/core/handoff/store.js +1 -0
- package/dist/core/inference/text-inference.js +95 -6
- package/dist/core/ipc-registration.js +43 -24
- package/dist/core/memory/consolidation-context.js +4 -1
- package/dist/core/memory/consolidation.js +25 -14
- package/dist/core/message/aun-ipc-sender.js +296 -88
- package/dist/core/message/aun-request-registry.js +226 -0
- package/dist/core/message/create-status.js +33 -4
- package/dist/core/message/message-bridge.js +62 -13
- package/dist/core/message/message-log.js +0 -1
- package/dist/core/message/message-queue.js +4 -1
- package/dist/core/message/message-utils.js +8 -1
- package/dist/core/message/peer-mode.js +17 -9
- package/dist/core/message/response-engine.js +266 -124
- package/dist/core/message/retry-scheduler.js +11 -8
- package/dist/core/model/catalog-service.js +60 -18
- package/dist/core/model/model-catalog.js +112 -9
- package/dist/core/model/model-fallback.js +94 -26
- package/dist/core/ownership/owner-resolver.js +687 -0
- package/dist/core/permission/approval-gateway.js +196 -62
- package/dist/core/permission/ec-command-parser.js +138 -25
- package/dist/core/permission/filesystem-approval-scope.js +141 -0
- package/dist/core/permission/protected-paths.js +14 -1
- package/dist/core/permission/sandbox-runtime.js +171 -18
- package/dist/core/permission/tool-policy.js +13 -2
- package/dist/core/role/runtime-policy.js +3 -4
- package/dist/core/session/session-idle-monitor.js +10 -8
- package/dist/core/session/session-manager.js +72 -45
- package/dist/core/session/session-mapper.js +18 -7
- package/dist/core/session/session-renew.js +5 -4
- package/dist/core/session/session-title.js +2 -1
- package/dist/core/session/session-turn-coordinator.js +4 -2
- package/dist/core/skill/index-generator.js +2 -16
- package/dist/core/task/task-recovery-service.js +15 -2
- package/dist/core/thread/command-parser.js +28 -13
- package/dist/core/thread/index.js +1 -0
- package/dist/core/thread/ipc-operation.js +11 -8
- package/dist/core/thread/thread-operation.js +79 -44
- package/dist/core/thread/thread-route.js +54 -6
- package/dist/core/thread/thread-service.js +236 -45
- package/dist/core/thread/topic-id.js +248 -0
- package/dist/eck/kit-renderer.js +1 -1
- package/dist/eck/message-renderer.js +12 -2
- package/dist/index.js +50 -27
- package/dist/ipc.js +59 -6
- package/dist/paths.js +1 -0
- package/dist/product.js +1 -0
- package/dist/response-system/engines/v1/proactive-flow.js +10 -3
- package/dist/stats/db.js +8 -0
- package/dist/stats/writer.js +26 -4
- package/dist/trigger/authorization.js +48 -3
- package/dist/trigger/feedback.js +28 -10
- package/dist/trigger/ipc-service.js +86 -10
- package/dist/trigger/local-files.js +55 -23
- package/dist/trigger/scheduler.js +57 -11
- package/dist/trigger/system-definitions.js +1 -0
- package/dist/trigger/validation.js +44 -15
- package/dist/utils/aid-bind.js +17 -297
- package/dist/utils/avatar-upload.js +16 -4
- package/dist/utils/cross-platform.js +115 -36
- package/dist/utils/ecweb-supervisor.js +1 -1
- package/dist/utils/ecweb-utils.js +8 -1
- package/dist/utils/error-utils.js +44 -6
- package/dist/utils/instance-registry.js +12 -2
- package/dist/utils/npm-ops.js +102 -27
- package/dist/utils/package-version-info.js +72 -27
- package/dist/utils/restart-safety.js +50 -0
- package/dist/utils/upgrade-jobs.js +304 -0
- package/dist/utils/windows-autostart.js +17 -10
- package/kits/docs/INDEX.md +5 -0
- package/kits/docs/aun/ABILITY_CALLING.md +239 -0
- package/kits/docs/evolcore/INDEX.md +14 -3
- package/kits/docs/evolcore/agent-create.md +55 -141
- package/kits/docs/evolcore/agent.md +38 -16
- package/kits/docs/evolcore/aid.md +34 -0
- package/kits/docs/evolcore/config.md +20 -1
- package/kits/docs/evolcore/event.md +2 -2
- package/kits/docs/evolcore/fs.md +18 -2
- package/kits/docs/evolcore/group-collaboration.md +13 -246
- package/kits/docs/evolcore/group.md +2 -1
- package/kits/docs/evolcore/memory-consolidation-batches.md +1 -1
- package/kits/docs/evolcore/menu-protocol.md +65 -1
- package/kits/docs/evolcore/msg.md +64 -2
- package/kits/docs/evolcore/skill.md +86 -0
- package/kits/docs/evolcore/stats.md +6 -0
- package/kits/docs/evolcore/task.md +2 -0
- package/kits/docs/evolcore/thread-chain.md +145 -51
- package/kits/docs/evolcore/trigger.md +48 -3
- package/kits/eck_manifest.json +21 -0
- package/kits/eck_message_manifest.json +4 -4
- package/kits/migrations/migrate-role-config-v5.mjs +20 -7
- package/kits/rules/01-overview.md +2 -1
- package/kits/rules/03-identity.md +3 -1
- package/kits/rules/04-relation.md +1 -1
- package/kits/rules/07-memory-and-thread.md +1 -1
- package/kits/schemas/_meta.json +16 -1
- package/kits/schemas/agent-config.schema.13.json +44 -2
- package/kits/schemas/contact-book.schema.3.json +5 -0
- package/kits/schemas/daemon.schema.6.json +3 -1
- package/kits/schemas/daemon.schema.8.json +329 -0
- package/kits/schemas/defaults.schema.5.json +39 -3
- package/kits/schemas/providers.schema.1.json +76 -0
- package/kits/schemas/relation-config.schema.9.json +5 -1
- package/kits/skills/.switches.json +28 -0
- package/kits/skills/aid-ability/SKILL.md +214 -0
- package/kits/skills/ec-agent-create/SKILL.md +162 -0
- package/kits/skills/ec-group/SKILL.md +2 -1
- package/kits/skills/ec-group-collaboration/SKILL.md +228 -0
- package/kits/skills/ec-identity/SKILL.md +143 -0
- package/kits/skills/ec-skill/scripts/cli.mjs +36 -3
- package/kits/skills/ec-skill/scripts/skill.mjs +202 -15
- package/kits/skills/ec-trigger/SKILL.md +167 -0
- package/kits/skills/ec-trigger/references/examples.md +153 -0
- package/kits/skills/thread-ops/SKILL.md +108 -420
- package/kits/templates/message-fragments/thread-context.md +1 -2
- package/kits/templates/message-fragments/trigger-thread-check.md +1 -1
- package/kits/templates/roles/member.json +1 -1
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +1 -0
- package/kits/templates/system-fragments/channel.md +2 -1
- package/kits/templates/system-fragments/commands.md +5 -4
- package/kits/templates/system-fragments/identity.md +2 -0
- package/kits/templates/system-fragments/session.md +1 -1
- package/kits/templates/system-fragments/venue.md +1 -1
- 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
|
|
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
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
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]
|
|
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
|
-
//
|
|
140
|
-
|
|
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
|
-
|
|
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
|
-
|
|
279
|
-
|
|
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') {
|