evolcore 0.0.1 → 0.0.3
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 +64 -0
- package/LICENSE +21 -0
- package/MIGRATION-0.5.0.md +378 -0
- package/README.md +318 -14
- package/ROLE_ACCESS_CONTROL.md +174 -0
- package/assets/.env.template +4 -0
- package/bin/ec-safe-output.js +161 -0
- package/bin/ec.js +29 -0
- package/dist/agents/baseagent.js +163 -0
- package/dist/agents/claude-runner.js +2565 -0
- package/dist/agents/codex-app-server-client.js +448 -0
- package/dist/agents/codex-runner.js +2682 -0
- package/dist/agents/gemini-runner.js +666 -0
- package/dist/agents/runner-types.js +75 -0
- package/dist/aun/aid/agentmd.js +216 -0
- package/dist/aun/aid/client.js +132 -0
- package/dist/aun/aid/control-aid.js +91 -0
- package/dist/aun/aid/identity.js +518 -0
- package/dist/aun/aid/index.js +4 -0
- package/dist/aun/aid/store.js +74 -0
- package/dist/aun/aid/types.js +1 -0
- package/dist/aun/aid/validation.js +21 -0
- package/dist/aun/group-identity.js +10 -0
- package/dist/aun/msg/group-index.js +6 -0
- package/dist/aun/msg/group.js +1231 -0
- package/dist/aun/msg/history.js +123 -0
- package/dist/aun/msg/index.js +5 -0
- package/dist/aun/msg/p2p.js +393 -0
- package/dist/aun/msg/payload-type.js +27 -0
- package/dist/aun/msg/upload.js +137 -0
- package/dist/aun/outbox.js +168 -0
- package/dist/aun/rpc/caller.js +42 -0
- package/dist/aun/rpc/connection.js +25 -0
- package/dist/aun/rpc/index.js +2 -0
- package/dist/aun/service-proxy.js +225 -0
- package/dist/aun/storage/download.js +29 -0
- package/dist/aun/storage/index.js +3 -0
- package/dist/aun/storage/manage.js +10 -0
- package/dist/aun/storage/upload.js +68 -0
- package/dist/channels/aun.js +4164 -0
- package/dist/channels/contact-bind-code.js +134 -0
- package/dist/channels/daemon.js +422 -0
- package/dist/channels/dingtalk.js +1479 -0
- package/dist/channels/feishu.js +1865 -0
- package/dist/channels/qqbot.js +409 -0
- package/dist/channels/wechat.js +817 -0
- package/dist/channels/wecom-card.js +101 -0
- package/dist/channels/wecom-onboarding.js +82 -0
- package/dist/channels/wecom-state.js +191 -0
- package/dist/channels/wecom.js +1157 -0
- package/dist/cli/agent-command.js +642 -0
- package/dist/cli/agent.js +1059 -0
- package/dist/cli/aun-commands.js +2003 -0
- package/dist/cli/bench.js +1228 -0
- package/dist/cli/cli-argv.js +66 -0
- package/dist/cli/code-stats.js +329 -0
- package/dist/cli/command-log.js +82 -0
- package/dist/cli/config-selector.js +69 -0
- package/dist/cli/config.js +261 -0
- package/dist/cli/contact.js +71 -0
- package/dist/cli/ctl-command.js +62 -0
- package/dist/cli/daemon-commands.js +2750 -0
- package/dist/cli/fs-command.js +1447 -0
- package/dist/cli/handoff-command.js +302 -0
- package/dist/cli/help.js +35 -0
- package/dist/cli/index.js +374 -0
- package/dist/cli/init-channel.js +1372 -0
- package/dist/cli/init.js +590 -0
- package/dist/cli/link-rules.js +240 -0
- package/dist/cli/model.js +591 -0
- package/dist/cli/net-check.js +723 -0
- package/dist/cli/queue-command.js +150 -0
- package/dist/cli/raw-key-input.js +25 -0
- package/dist/cli/response.js +344 -0
- package/dist/cli/restart-monitor.js +480 -0
- package/dist/cli/stats.js +609 -0
- package/dist/cli/task-context.js +80 -0
- package/dist/cli/trigger-command.js +545 -0
- package/dist/cli/version.js +93 -0
- package/dist/cli/watch-logs.js +33 -0
- package/dist/cli/watch-msg.js +673 -0
- package/dist/config/boot-log.js +266 -0
- package/dist/config/builtin-role-templates.js +42 -0
- package/dist/config/builtin-roles.js +91 -0
- package/dist/config/config-batch-get.js +11 -0
- package/dist/config/config-field-policy.js +261 -0
- package/dist/config/config-manager.js +1120 -0
- package/dist/config/config-operation-service.js +384 -0
- package/dist/config/contact-alias.js +68 -0
- package/dist/config/contact-book-store.js +454 -0
- package/dist/config/contact-book-v2-startup.js +35 -0
- package/dist/config/contact-book.js +224 -0
- package/dist/config/contact-operation-service.js +110 -0
- package/dist/config/gateway-config.js +858 -0
- package/dist/config/lifecycle.js +17 -0
- package/dist/config/mention-mode.js +27 -0
- package/dist/config/merge.js +161 -0
- package/dist/config/owner-policy.js +4 -0
- package/dist/config/peer-role-resolver.js +218 -0
- package/dist/config/resolved-config-op.js +483 -0
- package/dist/config/role-config-v4-startup.js +32 -0
- package/dist/config/role-config-v5-startup.js +27 -0
- package/dist/config/role-ranks.js +18 -0
- package/dist/config/role-schema.js +105 -0
- package/dist/config/role-service.js +156 -0
- package/dist/config/role-store.js +215 -0
- package/dist/config/roles.js +64 -0
- package/dist/config/schema-registry.js +154 -0
- package/dist/config/snapshot.js +598 -0
- package/dist/config-store.js +501 -0
- package/dist/core/auth/agent-delegation.js +111 -0
- package/dist/core/auth/auth-gateway.js +166 -0
- package/dist/core/auth/authenticated-actor.js +6 -0
- package/dist/core/auth/authorization-audit.js +119 -0
- package/dist/core/auth/operation-authorizer.js +720 -0
- package/dist/core/auth/operation-catalog.js +731 -0
- package/dist/core/baseagent-loader.js +54 -0
- package/dist/core/bootstrap-service.js +175 -0
- package/dist/core/capability/capability-manager.js +316 -0
- package/dist/core/capability/providers/claude-capability-provider.js +176 -0
- package/dist/core/capability/providers/codex-capability-provider.js +148 -0
- package/dist/core/capability/providers/gemini-capability-provider.js +10 -0
- package/dist/core/capability/types.js +27 -0
- package/dist/core/causation/audit.js +103 -0
- package/dist/core/causation/aun-association.js +111 -0
- package/dist/core/causation/context.js +93 -0
- package/dist/core/causation/index.js +4 -0
- package/dist/core/causation/types.js +2 -0
- package/dist/core/channel-loader.js +277 -0
- package/dist/core/command/agent-control.js +616 -0
- package/dist/core/command/cli-intent-parser.js +225 -0
- package/dist/core/command/command-handler.js +1733 -0
- package/dist/core/command/connect-menu.js +374 -0
- package/dist/core/command/menu-handler.js +3452 -0
- package/dist/core/command/menu-protocol.js +247 -0
- package/dist/core/command/role-menu.js +1623 -0
- package/dist/core/command/slash-gate.js +148 -0
- package/dist/core/command/slash-handler.js +3066 -0
- package/dist/core/daemon-file-cache.js +222 -0
- package/dist/core/event-bus.js +32 -0
- package/dist/core/event-catalog.js +810 -0
- package/dist/core/evolagent-registry.js +545 -0
- package/dist/core/evolagent.js +342 -0
- package/dist/core/handoff/dispatcher.js +229 -0
- package/dist/core/handoff/mutex.js +46 -0
- package/dist/core/handoff/runtime.js +324 -0
- package/dist/core/handoff/store.js +537 -0
- package/dist/core/handoff/types.js +12 -0
- package/dist/core/inference/text-inference.js +173 -0
- package/dist/core/interaction-registration.js +10 -0
- package/dist/core/interaction-router.js +278 -0
- package/dist/core/message/create-status.js +67 -0
- package/dist/core/message/im-renderer.js +659 -0
- package/dist/core/message/items-formatter.js +76 -0
- package/dist/core/message/logical-queue-bridge.js +123 -0
- package/dist/core/message/message-bridge.js +874 -0
- package/dist/core/message/message-cache.js +56 -0
- package/dist/core/message/message-log.js +339 -0
- package/dist/core/message/message-processor.js +4 -0
- package/dist/core/message/message-queue.js +1446 -0
- package/dist/core/message/message-utils.js +76 -0
- package/dist/core/message/peer-mode.js +105 -0
- package/dist/core/message/pending-hints.js +232 -0
- package/dist/core/message/response-depth.js +33 -0
- package/dist/core/message/response-engine.js +4020 -0
- package/dist/core/message/response-snapshot.js +83 -0
- package/dist/core/message/send-receipt.js +24 -0
- package/dist/core/message/stream-debouncer.js +139 -0
- package/dist/core/message/stream-idle-monitor.js +124 -0
- package/dist/core/model/config-scope.js +162 -0
- package/dist/core/model/field-scope.js +78 -0
- package/dist/core/model/model-catalog.js +227 -0
- package/dist/core/model/model-diagnostics.js +182 -0
- package/dist/core/model/model-permission.js +90 -0
- package/dist/core/permission/approval-gateway.js +1017 -0
- package/dist/core/permission/ec-command-parser.js +347 -0
- package/dist/core/permission/execution-sandbox.js +16 -0
- package/dist/core/permission/index.js +6 -0
- package/dist/core/permission/mode.js +24 -0
- package/dist/core/permission/sandbox-runtime.js +265 -0
- package/dist/core/permission/tool-policy.js +1019 -0
- package/dist/core/permission/unix-socket-policy.js +99 -0
- package/dist/core/protected-paths.js +332 -0
- package/dist/core/relation/peer-identity.js +222 -0
- package/dist/core/relation/peer-key.js +1 -0
- package/dist/core/role/runtime-policy.js +141 -0
- package/dist/core/session/adapters/claude-session-file-adapter.js +218 -0
- package/dist/core/session/adapters/codex-session-file-adapter.js +333 -0
- package/dist/core/session/adapters/gemini-session-file-adapter.js +181 -0
- package/dist/core/session/session-file-adapter.js +7 -0
- package/dist/core/session/session-file-health.js +45 -0
- package/dist/core/session/session-fs-store.js +273 -0
- package/dist/core/session/session-key.js +24 -0
- package/dist/core/session/session-manager.js +1643 -0
- package/dist/core/session/session-mapper.js +100 -0
- package/dist/core/session/session-renew.js +314 -0
- package/dist/core/session/session-title.js +128 -0
- package/dist/core/session/session-turn-coordinator.js +205 -0
- package/dist/core/session/session-turns.js +67 -0
- package/dist/core/system-channels.js +29 -0
- package/dist/eck/baseagent-caps.js +18 -0
- package/dist/eck/detect.js +47 -0
- package/dist/eck/group-rules-sync.js +345 -0
- package/dist/eck/init.js +77 -0
- package/dist/eck/kit-renderer.js +359 -0
- package/dist/eck/manifest-engine.js +446 -0
- package/dist/eck/message-renderer.js +199 -0
- package/dist/eck/rules-loader.js +28 -0
- package/dist/index.js +2926 -4
- package/dist/ipc.js +777 -0
- package/dist/paths.js +262 -0
- package/dist/product.js +18 -0
- package/dist/response-system/context-builder.js +71 -0
- package/dist/response-system/coordinator.js +117 -0
- package/dist/response-system/decision-executor.js +86 -0
- package/dist/response-system/engines/v1/index.js +21 -0
- package/dist/response-system/engines/v1/interactive-flow.js +27 -0
- package/dist/response-system/engines/v1/proactive-flow.js +137 -0
- package/dist/response-system/engines/v1/types.js +1 -0
- package/dist/response-system/extensions.js +41 -0
- package/dist/response-system/index.js +6 -0
- package/dist/response-system/modes/index.js +7 -0
- package/dist/response-system/modes/single-session/index.js +72 -0
- package/dist/response-system/queues/fifo-queue.js +44 -0
- package/dist/response-system/queues/index.js +6 -0
- package/dist/response-system/queues/lifo-queue.js +42 -0
- package/dist/response-system/queues/priority-queue.js +63 -0
- package/dist/response-system/registry.js +97 -0
- package/dist/response-system/resolver.js +37 -0
- package/dist/response-system/selector.js +23 -0
- package/dist/response-system/types.js +7 -0
- package/dist/stats/billing.js +163 -0
- package/dist/stats/budget.js +93 -0
- package/dist/stats/db.js +403 -0
- package/dist/stats/eck-vars.js +89 -0
- package/dist/stats/index.js +11 -0
- package/dist/stats/normalizer.js +80 -0
- package/dist/stats/price-resolver.js +138 -0
- package/dist/stats/query.js +763 -0
- package/dist/stats/role-budget.js +168 -0
- package/dist/stats/writer.js +151 -0
- package/dist/trigger/anomaly-store.js +258 -0
- package/dist/trigger/audit.js +152 -0
- package/dist/trigger/event-source.js +119 -0
- package/dist/trigger/feedback.js +685 -0
- package/dist/trigger/history.js +290 -0
- package/dist/trigger/manager.js +294 -0
- package/dist/trigger/parser.js +595 -0
- package/dist/trigger/patch.js +155 -0
- package/dist/trigger/scheduler.js +1602 -0
- package/dist/trigger/script-executor.js +155 -0
- package/dist/trigger/state.js +145 -0
- package/dist/trigger/types.js +1 -0
- package/dist/trigger/validation.js +634 -0
- package/dist/types.js +12 -0
- package/dist/utils/aid-bind.js +313 -0
- package/dist/utils/atomic-write.js +95 -0
- package/dist/utils/avatar-upload.js +123 -0
- package/dist/utils/cross-platform.js +297 -0
- package/dist/utils/ecweb-utils.js +73 -0
- package/dist/utils/error-dict.json +153 -0
- package/dist/utils/error-utils.js +349 -0
- package/dist/utils/instance-registry.js +444 -0
- package/dist/utils/locale.js +21 -0
- package/dist/utils/log-writer.js +270 -0
- package/dist/utils/logger.js +89 -0
- package/dist/utils/markdown-to-plain-text.js +20 -0
- package/dist/utils/media-cache.js +274 -0
- package/dist/utils/model-prices.jsonl +20 -0
- package/dist/utils/npm-ops.js +210 -0
- package/dist/utils/process-introspect.js +133 -0
- package/dist/utils/process-tree-stats.js +271 -0
- package/dist/utils/project-path.js +74 -0
- package/dist/utils/restart-safety.js +31 -0
- package/dist/utils/stats.js +410 -0
- package/dist/utils/system-memory.js +62 -0
- package/dist/utils/tool-summary.js +284 -0
- package/dist/utils/welcome.js +268 -0
- package/kits/docs/GUIDE.md +20 -0
- package/kits/docs/INDEX.md +66 -0
- package/kits/docs/aun/CHEATSHEET.md +19 -0
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
- package/kits/docs/channels/aun.md +65 -0
- package/kits/docs/channels/feishu.md +56 -0
- package/kits/docs/context-assembly.md +366 -0
- package/kits/docs/eck_templates/GUIDE.template.md +22 -0
- package/kits/docs/eck_templates/INDEX.template.md +28 -0
- package/kits/docs/eck_templates/path-registry.template.md +33 -0
- package/kits/docs/eck_templates/runtime.template.md +19 -0
- package/kits/docs/evolcore/INDEX.md +68 -0
- package/kits/docs/evolcore/agent.md +77 -0
- package/kits/docs/evolcore/aid.md +52 -0
- package/kits/docs/evolcore/config.md +149 -0
- package/kits/docs/evolcore/contact.md +57 -0
- package/kits/docs/evolcore/ctl.md +46 -0
- package/kits/docs/evolcore/event.md +216 -0
- package/kits/docs/evolcore/fs-architecture.md +1215 -0
- package/kits/docs/evolcore/fs.md +110 -0
- package/kits/docs/evolcore/group-fs.md +17 -0
- package/kits/docs/evolcore/group-rules.md +226 -0
- package/kits/docs/evolcore/group.md +150 -0
- package/kits/docs/evolcore/model.md +50 -0
- package/kits/docs/evolcore/msg.md +136 -0
- package/kits/docs/evolcore/response.md +75 -0
- package/kits/docs/evolcore/rpc.md +37 -0
- package/kits/docs/evolcore/self-summary.md +29 -0
- package/kits/docs/evolcore/stats.md +83 -0
- package/kits/docs/evolcore/storage.md +50 -0
- package/kits/docs/evolcore/trigger.md +539 -0
- package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -0
- package/kits/docs/identity/PATH_OPS.md +16 -0
- package/kits/docs/identity/ROLE_DETAIL.md +23 -0
- package/kits/docs/identity/identity-tools.md +26 -0
- package/kits/docs/path-registry.md +43 -0
- package/kits/docs/prompt-loading-architecture.md +266 -0
- package/kits/docs/venues/aun-group.md +45 -0
- package/kits/docs/venues/aun-private.md +10 -0
- package/kits/docs/venues/client-desktop.md +10 -0
- package/kits/docs/venues/client-mobile.md +10 -0
- package/kits/docs/venues/feishu-group.md +13 -0
- package/kits/docs/venues/feishu-private.md +9 -0
- package/kits/docs/venues/group.md +25 -0
- package/kits/docs/venues/private.md +10 -0
- package/kits/eck_manifest.auxiliary.json +43 -0
- package/kits/eck_manifest.json +203 -0
- package/kits/eck_message_manifest.json +63 -0
- package/kits/migrations/README-role-config-v4.md +32 -0
- package/kits/migrations/migrate-contact-book-v2.mjs +747 -0
- package/kits/migrations/migrate-role-config-v4.mjs +623 -0
- package/kits/migrations/migrate-role-config-v5.mjs +346 -0
- package/kits/migrations/rename-config-file.mjs +99 -0
- package/kits/rules/01-overview.md +142 -0
- package/kits/rules/02-navigation.md +76 -0
- package/kits/rules/03-identity.md +34 -0
- package/kits/rules/04-relation.md +59 -0
- package/kits/rules/05-venue.md +44 -0
- package/kits/rules/06-channel.md +59 -0
- package/kits/schemas/_meta.json +32 -0
- package/kits/schemas/agent-config.schema.1.json +177 -0
- package/kits/schemas/agent-config.schema.2.json +239 -0
- package/kits/schemas/agent-config.schema.3.json +119 -0
- package/kits/schemas/agent-config.schema.4.json +208 -0
- package/kits/schemas/agent-config.schema.5.json +326 -0
- package/kits/schemas/agent-config.schema.6.json +322 -0
- package/kits/schemas/contact-book.schema.1.json +36 -0
- package/kits/schemas/contact-book.schema.2.json +43 -0
- package/kits/schemas/daemon.schema.1.json +90 -0
- package/kits/schemas/defaults.schema.1.json +81 -0
- package/kits/schemas/menu-exec-schema-commands.md +208 -0
- package/kits/schemas/migrations/README.md +28 -0
- package/kits/schemas/relation-config.schema.1.json +158 -0
- package/kits/schemas/relation-config.schema.2.json +73 -0
- package/kits/schemas/relation-config.schema.3.json +50 -0
- package/kits/schemas/relation-config.schema.4.json +47 -0
- package/kits/schemas/relation-config.schema.5.json +47 -0
- package/kits/schemas/role-config.schema.1.json +201 -0
- package/kits/schemas/role-registry.schema.1.json +35 -0
- package/kits/schemas/single-session.schema.1.json +31 -0
- package/kits/templates/bootstrap-welcome.md +15 -0
- package/kits/templates/message-fragments/handoff-request-to-target.md +13 -0
- package/kits/templates/message-fragments/handoff-response-to-origin.md +10 -0
- package/kits/templates/message-fragments/inject-default.md +2 -0
- package/kits/templates/message-fragments/item.md +2 -0
- package/kits/templates/roles/admin.json +9 -0
- package/kits/templates/roles/member.json +41 -0
- package/kits/templates/roles/owner.json +9 -0
- package/kits/templates/roles/visitor.json +40 -0
- package/kits/templates/system-fragments/baseagent.md +14 -0
- package/kits/templates/system-fragments/bootstrap.md +16 -0
- package/kits/templates/system-fragments/channel.md +48 -0
- package/kits/templates/system-fragments/commands.md +28 -0
- package/kits/templates/system-fragments/identity.md +11 -0
- package/kits/templates/system-fragments/relation.md +19 -0
- package/kits/templates/system-fragments/session.md +53 -0
- package/kits/templates/system-fragments/venue.md +31 -0
- package/package.json +50 -15
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import Ajv from 'ajv';
|
|
6
|
+
|
|
7
|
+
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const SCHEMA_DIR = path.resolve(SCRIPT_DIR, '..', 'schemas');
|
|
9
|
+
const BUILTIN_ROLES = ['owner', 'admin', 'member', 'visitor'];
|
|
10
|
+
const MANAGEMENT_ROLES = new Set(['owner', 'admin']);
|
|
11
|
+
|
|
12
|
+
function parseArgs(argv) {
|
|
13
|
+
const options = { apply: false, json: false, home: undefined };
|
|
14
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
15
|
+
const arg = argv[i];
|
|
16
|
+
if (arg === '--apply') options.apply = true;
|
|
17
|
+
else if (arg === '--json') options.json = true;
|
|
18
|
+
else if (arg === '--home') options.home = argv[++i];
|
|
19
|
+
else if (arg === '--help' || arg === '-h') options.help = true;
|
|
20
|
+
else throw new Error(`Unknown argument: ${arg}`);
|
|
21
|
+
}
|
|
22
|
+
return options;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function resolveHome(explicit) {
|
|
26
|
+
return path.resolve(explicit || process.env.EVOLCORE_HOME || path.join(os.homedir(), '.evolcore'));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function loadValidators() {
|
|
30
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
31
|
+
const load = name => JSON.parse(fs.readFileSync(path.join(SCHEMA_DIR, name), 'utf8'));
|
|
32
|
+
return {
|
|
33
|
+
agent: ajv.compile(load('agent-config.schema.5.json')),
|
|
34
|
+
registry: ajv.compile(load('role-registry.schema.1.json')),
|
|
35
|
+
role: ajv.compile(load('role-config.schema.1.json')),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readJson(file) {
|
|
40
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
41
|
+
return { value: JSON.parse(text), text };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isRecord(value) {
|
|
45
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isValidAid(name) {
|
|
49
|
+
const labels = name.split('.');
|
|
50
|
+
return labels.length >= 3 && labels.every(label => /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(label));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function validateOrThrow(validate, value, file) {
|
|
54
|
+
if (validate(value)) return;
|
|
55
|
+
const detail = (validate.errors ?? []).map(error => `${error.instancePath || '/'} ${error.message}`).join('; ');
|
|
56
|
+
throw new Error(`${file}: ${detail}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function validateRoleOrThrow(validate, value, file) {
|
|
60
|
+
validateOrThrow(validate, value, file);
|
|
61
|
+
for (const [field, permission] of Object.entries(value.permissions ?? {})) {
|
|
62
|
+
if (!isRecord(permission)) continue;
|
|
63
|
+
if (Array.isArray(permission.allowedValues) && !permission.allowedValues.includes(permission.default)) {
|
|
64
|
+
throw new Error(`${file}: permissions.${field}.default must be included in allowedValues`);
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(permission.allowedModels)
|
|
67
|
+
&& typeof permission.default === 'string'
|
|
68
|
+
&& !permission.allowedModels.some(pattern => wildcardMatch(pattern, permission.default))) {
|
|
69
|
+
throw new Error(`${file}: permissions.${field}.default must be allowed by allowedModels`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function wildcardMatch(pattern, value) {
|
|
75
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
|
|
76
|
+
return new RegExp(`^${escaped}$`).test(value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function change(file, kind, before, value) {
|
|
80
|
+
const after = `${JSON.stringify(value, null, 2)}\n`;
|
|
81
|
+
return before === after ? null : { file, kind, before, after };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function appendChange(changes, file, kind, before, value) {
|
|
85
|
+
const item = change(file, kind, before, value);
|
|
86
|
+
if (!item) return false;
|
|
87
|
+
changes.push(item);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function planMigration(home) {
|
|
92
|
+
const validators = loadValidators();
|
|
93
|
+
const agentsRoot = path.join(home, 'agents');
|
|
94
|
+
if (!fs.existsSync(agentsRoot)) return { home, changes: [], summary: { agentsScanned: 0, agentsMigrated: 0, rolesWritten: 0 } };
|
|
95
|
+
const changes = [];
|
|
96
|
+
const summary = { agentsScanned: 0, agentsMigrated: 0, rolesWritten: 0 };
|
|
97
|
+
|
|
98
|
+
for (const entry of fs.readdirSync(agentsRoot, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
99
|
+
if (!entry.isDirectory() || !isValidAid(entry.name)) continue;
|
|
100
|
+
const agentFile = path.join(agentsRoot, entry.name, 'config.json');
|
|
101
|
+
if (!fs.existsSync(agentFile)) continue;
|
|
102
|
+
summary.agentsScanned += 1;
|
|
103
|
+
const { value: input, text: agentText } = readJson(agentFile);
|
|
104
|
+
if (!isRecord(input)) throw new Error(`${agentFile}: Agent config must be an object`);
|
|
105
|
+
if (typeof input.$schema_version === 'number' && input.$schema_version > 5) {
|
|
106
|
+
throw new Error(`${agentFile}: unsupported future Agent schema version ${input.$schema_version}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const rolesDir = path.join(agentsRoot, entry.name, 'roles');
|
|
110
|
+
const registryFile = path.join(rolesDir, 'index.json');
|
|
111
|
+
if (fs.existsSync(registryFile) && input.roles !== undefined) {
|
|
112
|
+
throw new Error(`${agentFile}: both config.roles and roles/index.json exist; resolve the ambiguous role source before migration`);
|
|
113
|
+
}
|
|
114
|
+
if (input.$schema_version === 5 && input.roles === undefined && fs.existsSync(registryFile)) continue;
|
|
115
|
+
|
|
116
|
+
const policy = isRecord(input.roles) ? input.roles : {};
|
|
117
|
+
const definitions = isRecord(policy.definitions) ? policy.definitions : {};
|
|
118
|
+
for (const roleId of Object.keys(definitions)) {
|
|
119
|
+
if (!/^[a-z0-9_-]+$/.test(roleId) || MANAGEMENT_ROLES.has(roleId)) {
|
|
120
|
+
throw new Error(`${agentFile}: invalid role id ${JSON.stringify(roleId)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const roleIds = [...new Set([...BUILTIN_ROLES, ...Object.keys(definitions)])];
|
|
124
|
+
const defaultRoles = {
|
|
125
|
+
private: policy.defaultRoles?.private ?? null,
|
|
126
|
+
group: policy.defaultRoles?.group ?? null,
|
|
127
|
+
};
|
|
128
|
+
for (const scene of ['private', 'group']) {
|
|
129
|
+
const selected = defaultRoles[scene];
|
|
130
|
+
if (selected !== null && (MANAGEMENT_ROLES.has(selected) || !roleIds.includes(selected))) {
|
|
131
|
+
throw new Error(`${agentFile}: roles.defaultRoles.${scene} references an invalid role`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const registry = { $schema_version: 1, roles: roleIds, defaultRoles };
|
|
135
|
+
validateOrThrow(validators.registry, registry, registryFile);
|
|
136
|
+
|
|
137
|
+
const relationsDir = path.join(agentsRoot, entry.name, 'relations');
|
|
138
|
+
if (fs.existsSync(relationsDir)) {
|
|
139
|
+
const visit = dir => {
|
|
140
|
+
for (const relationEntry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
141
|
+
const full = path.join(dir, relationEntry.name);
|
|
142
|
+
if (relationEntry.isDirectory()) visit(full);
|
|
143
|
+
else if (relationEntry.isFile() && relationEntry.name === 'config.json') {
|
|
144
|
+
const relation = readJson(full).value;
|
|
145
|
+
if (relation.role !== undefined && relation.role !== null
|
|
146
|
+
&& (MANAGEMENT_ROLES.has(relation.role) || !roleIds.includes(relation.role))) {
|
|
147
|
+
throw new Error(`${full}: role references an invalid or unregistered role`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
visit(relationsDir);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const existingRegistry = fs.existsSync(registryFile) ? fs.readFileSync(registryFile, 'utf8') : null;
|
|
156
|
+
appendChange(changes, registryFile, 'role-registry', existingRegistry, registry);
|
|
157
|
+
for (const [roleId, definition] of Object.entries(definitions)) {
|
|
158
|
+
const roleFile = path.join(rolesDir, `${roleId}.json`);
|
|
159
|
+
const roleValue = { $schema_version: 1, ...definition };
|
|
160
|
+
validateRoleOrThrow(validators.role, roleValue, roleFile);
|
|
161
|
+
if (appendChange(changes, roleFile, 'role-config', fs.existsSync(roleFile) ? fs.readFileSync(roleFile, 'utf8') : null, roleValue)) {
|
|
162
|
+
summary.rolesWritten += 1;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const output = { ...input, $schema_version: 5 };
|
|
167
|
+
delete output.roles;
|
|
168
|
+
validateOrThrow(validators.agent, output, agentFile);
|
|
169
|
+
appendChange(changes, agentFile, 'agent', agentText, output);
|
|
170
|
+
summary.agentsMigrated += 1;
|
|
171
|
+
}
|
|
172
|
+
return { home, changes, summary };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function assertDaemonStopped(home) {
|
|
176
|
+
const candidates = [];
|
|
177
|
+
const pidFile = path.join(home, 'daemon.pid');
|
|
178
|
+
if (fs.existsSync(pidFile)) {
|
|
179
|
+
candidates.push({ pid: Number(fs.readFileSync(pidFile, 'utf8').trim()), source: pidFile });
|
|
180
|
+
}
|
|
181
|
+
const instanceDir = path.join(home, 'data', 'instance');
|
|
182
|
+
if (fs.existsSync(instanceDir)) {
|
|
183
|
+
for (const name of fs.readdirSync(instanceDir)) {
|
|
184
|
+
if (!/^main-\d+\.json$/.test(name)) continue;
|
|
185
|
+
const file = path.join(instanceDir, name);
|
|
186
|
+
try { candidates.push({ pid: Number(JSON.parse(fs.readFileSync(file, 'utf8'))?.pid), source: file }); } catch {}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
for (const { pid, source } of candidates) {
|
|
190
|
+
if (!Number.isInteger(pid) || pid <= 0) continue;
|
|
191
|
+
try { process.kill(pid, 0); } catch (error) {
|
|
192
|
+
if (error?.code === 'ESRCH') continue;
|
|
193
|
+
if (error?.code !== 'EPERM') throw error;
|
|
194
|
+
}
|
|
195
|
+
throw new Error(`EvolCore daemon appears to be running (pid=${pid}, record=${source}); stop it before migration`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function acquireMigrationLock(home) {
|
|
200
|
+
const lockDir = path.join(home, 'data', 'role-v5-migration.lock');
|
|
201
|
+
const ownerFile = path.join(lockDir, 'owner.json');
|
|
202
|
+
fs.mkdirSync(path.dirname(lockDir), { recursive: true });
|
|
203
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
204
|
+
try {
|
|
205
|
+
fs.mkdirSync(lockDir);
|
|
206
|
+
fs.writeFileSync(ownerFile, `${JSON.stringify({ pid: process.pid, createdAt: new Date().toISOString() }, null, 2)}\n`);
|
|
207
|
+
return () => fs.rmSync(lockDir, { recursive: true, force: true });
|
|
208
|
+
} catch (error) {
|
|
209
|
+
if (error?.code !== 'EEXIST') throw error;
|
|
210
|
+
let ownerPid;
|
|
211
|
+
try { ownerPid = Number(JSON.parse(fs.readFileSync(ownerFile, 'utf8'))?.pid); }
|
|
212
|
+
catch { throw new Error(`Role config migration lock is unreadable: ${lockDir}`); }
|
|
213
|
+
if (Number.isInteger(ownerPid) && ownerPid > 0) {
|
|
214
|
+
try {
|
|
215
|
+
process.kill(ownerPid, 0);
|
|
216
|
+
throw new Error(`Another role config migration is already running (pid=${ownerPid})`);
|
|
217
|
+
} catch (ownerError) {
|
|
218
|
+
if (ownerError?.code === 'EPERM') throw new Error(`Another role config migration is already running (pid=${ownerPid})`);
|
|
219
|
+
if (ownerError?.code !== 'ESRCH') throw ownerError;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
fs.rmSync(lockDir, { recursive: true, force: true });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
throw new Error(`Unable to acquire role config migration lock: ${lockDir}`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function atomicWrite(file, content) {
|
|
229
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
230
|
+
const mode = fs.existsSync(file) ? fs.statSync(file).mode & 0o777 : 0o600;
|
|
231
|
+
const temp = `${file}.role-v5-${process.pid}-${Math.random().toString(16).slice(2)}.tmp`;
|
|
232
|
+
fs.writeFileSync(temp, content, { mode });
|
|
233
|
+
fs.renameSync(temp, file);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function migrationJournalPath(home) {
|
|
237
|
+
return path.join(home, 'data', 'role-v5-migration.json');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function writeMigrationJournal(plan, state) {
|
|
241
|
+
atomicWrite(migrationJournalPath(plan.home), `${JSON.stringify({
|
|
242
|
+
schemaVersion: 1,
|
|
243
|
+
state,
|
|
244
|
+
home: plan.home,
|
|
245
|
+
changes: plan.changes,
|
|
246
|
+
}, null, 2)}\n`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function removeMigrationJournal(home) {
|
|
250
|
+
fs.rmSync(migrationJournalPath(home), { force: true });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function recoverMigrationJournal(home) {
|
|
254
|
+
const file = migrationJournalPath(home);
|
|
255
|
+
if (!fs.existsSync(file)) return;
|
|
256
|
+
let journal;
|
|
257
|
+
try { journal = JSON.parse(fs.readFileSync(file, 'utf8')); }
|
|
258
|
+
catch { throw new Error(`Role config v5 migration journal is unreadable: ${file}`); }
|
|
259
|
+
if (journal?.schemaVersion !== 1
|
|
260
|
+
|| !['prepared', 'committed'].includes(journal.state)
|
|
261
|
+
|| path.resolve(journal.home) !== home
|
|
262
|
+
|| !Array.isArray(journal.changes)) {
|
|
263
|
+
throw new Error(`Role config v5 migration journal is invalid: ${file}`);
|
|
264
|
+
}
|
|
265
|
+
const rootPrefix = home + path.sep;
|
|
266
|
+
for (const item of journal.changes) {
|
|
267
|
+
const target = path.resolve(item?.file || '');
|
|
268
|
+
if (!target.startsWith(rootPrefix)
|
|
269
|
+
|| (item.before !== null && typeof item.before !== 'string')
|
|
270
|
+
|| typeof item.after !== 'string') {
|
|
271
|
+
throw new Error(`Role config v5 migration journal contains an unsafe change: ${file}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (journal.state === 'prepared') {
|
|
275
|
+
for (const item of [...journal.changes].reverse()) {
|
|
276
|
+
if (item.before === null) fs.rmSync(item.file, { force: true });
|
|
277
|
+
else atomicWrite(item.file, item.before);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
removeMigrationJournal(home);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function applyMigration(plan) {
|
|
284
|
+
if (!plan.changes.length) return null;
|
|
285
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
286
|
+
const backup = path.join(plan.home, 'backups', 'role-v5-migration', stamp);
|
|
287
|
+
fs.mkdirSync(backup, { recursive: true });
|
|
288
|
+
for (const item of plan.changes) {
|
|
289
|
+
if (item.before === null) continue;
|
|
290
|
+
const dest = path.join(backup, 'files', path.relative(plan.home, item.file));
|
|
291
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
292
|
+
fs.writeFileSync(dest, item.before);
|
|
293
|
+
}
|
|
294
|
+
fs.writeFileSync(path.join(backup, 'manifest.json'), `${JSON.stringify({
|
|
295
|
+
schemaVersion: 1,
|
|
296
|
+
createdAt: new Date().toISOString(),
|
|
297
|
+
summary: plan.summary,
|
|
298
|
+
files: plan.changes.map(item => ({ path: path.relative(plan.home, item.file), kind: item.kind })),
|
|
299
|
+
}, null, 2)}\n`);
|
|
300
|
+
writeMigrationJournal(plan, 'prepared');
|
|
301
|
+
try {
|
|
302
|
+
for (const item of plan.changes) {
|
|
303
|
+
atomicWrite(item.file, item.after);
|
|
304
|
+
}
|
|
305
|
+
writeMigrationJournal(plan, 'committed');
|
|
306
|
+
removeMigrationJournal(plan.home);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
recoverMigrationJournal(plan.home);
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
return backup;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function runMigration(options = {}) {
|
|
315
|
+
const home = resolveHome(options.home);
|
|
316
|
+
const releaseLock = acquireMigrationLock(home);
|
|
317
|
+
try {
|
|
318
|
+
assertDaemonStopped(home);
|
|
319
|
+
recoverMigrationJournal(home);
|
|
320
|
+
const plan = planMigration(home);
|
|
321
|
+
const backup = options.apply ? applyMigration(plan) : null;
|
|
322
|
+
return { ok: true, mode: options.apply ? 'applied' : 'dry-run', home, changedFiles: plan.changes.length, backup, summary: plan.summary };
|
|
323
|
+
} finally {
|
|
324
|
+
releaseLock();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function main() {
|
|
329
|
+
try {
|
|
330
|
+
const options = parseArgs(process.argv.slice(2));
|
|
331
|
+
if (options.help) {
|
|
332
|
+
console.log('Usage: node kits/migrations/migrate-role-config-v5.mjs [--apply] [--home <path>] [--json]');
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const result = runMigration(options);
|
|
336
|
+
if (options.json) console.log(JSON.stringify(result));
|
|
337
|
+
else console.log(`Role config v5 migration (${result.mode}): ${result.changedFiles} file(s)`);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
340
|
+
if (process.argv.includes('--json')) console.log(JSON.stringify({ ok: false, error: message }));
|
|
341
|
+
else console.error(`Migration failed: ${message}`);
|
|
342
|
+
process.exitCode = 1;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) await main();
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
function assertSafeFilename(value, label) {
|
|
8
|
+
if (!value || path.basename(value) !== value || value === '.' || value === '..') {
|
|
9
|
+
throw new Error(`${label} must be a filename without path separators`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function readJsonFile(file) {
|
|
14
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
15
|
+
JSON.parse(text);
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function inspectConfigRename({ home, from, to }) {
|
|
20
|
+
const root = path.resolve(home);
|
|
21
|
+
assertSafeFilename(from, 'from');
|
|
22
|
+
assertSafeFilename(to, 'to');
|
|
23
|
+
if (from === to) throw new Error('from and to must be different');
|
|
24
|
+
|
|
25
|
+
const source = path.join(root, from);
|
|
26
|
+
const target = path.join(root, to);
|
|
27
|
+
const sourceExists = fs.existsSync(source);
|
|
28
|
+
const targetExists = fs.existsSync(target);
|
|
29
|
+
|
|
30
|
+
if (!sourceExists && !targetExists) {
|
|
31
|
+
return { status: 'missing', root, source, target };
|
|
32
|
+
}
|
|
33
|
+
if (!sourceExists && targetExists) {
|
|
34
|
+
readJsonFile(target);
|
|
35
|
+
return { status: 'already-migrated', root, source, target };
|
|
36
|
+
}
|
|
37
|
+
if (sourceExists && targetExists) {
|
|
38
|
+
const sourceText = readJsonFile(source);
|
|
39
|
+
const targetText = readJsonFile(target);
|
|
40
|
+
return {
|
|
41
|
+
status: sourceText === targetText ? 'duplicate' : 'conflict',
|
|
42
|
+
root,
|
|
43
|
+
source,
|
|
44
|
+
target,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
readJsonFile(source);
|
|
49
|
+
return { status: 'ready', root, source, target };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function applyConfigRename(options) {
|
|
53
|
+
const inspection = inspectConfigRename(options);
|
|
54
|
+
if (inspection.status === 'already-migrated') return inspection;
|
|
55
|
+
if (inspection.status !== 'ready') {
|
|
56
|
+
throw new Error(`config rename refused: ${inspection.status}`);
|
|
57
|
+
}
|
|
58
|
+
fs.renameSync(inspection.source, inspection.target);
|
|
59
|
+
return { ...inspection, status: 'migrated' };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function parseArgs(argv) {
|
|
63
|
+
const options = { apply: false };
|
|
64
|
+
for (let i = 0; i < argv.length; i++) {
|
|
65
|
+
const arg = argv[i];
|
|
66
|
+
if (arg === '--apply') options.apply = true;
|
|
67
|
+
else if (arg === '--home') options.home = argv[++i];
|
|
68
|
+
else if (arg === '--from') options.from = argv[++i];
|
|
69
|
+
else if (arg === '--to') options.to = argv[++i];
|
|
70
|
+
else if (arg === '--help' || arg === '-h') options.help = true;
|
|
71
|
+
else throw new Error(`unknown argument: ${arg}`);
|
|
72
|
+
}
|
|
73
|
+
return options;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function usage() {
|
|
77
|
+
return 'Usage: node kits/migrations/rename-config-file.mjs --home <dir> --from <file> --to <file> [--apply]';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function main() {
|
|
81
|
+
try {
|
|
82
|
+
const options = parseArgs(process.argv.slice(2));
|
|
83
|
+
if (options.help) {
|
|
84
|
+
console.log(usage());
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!options.home || !options.from || !options.to) throw new Error(usage());
|
|
88
|
+
const result = options.apply ? applyConfigRename(options) : inspectConfigRename(options);
|
|
89
|
+
console.log(JSON.stringify({ mode: options.apply ? 'apply' : 'dry-run', ...result }, null, 2));
|
|
90
|
+
if (result.status === 'conflict' || result.status === 'duplicate' || result.status === 'missing') {
|
|
91
|
+
process.exitCode = 2;
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main();
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# EvolCore Context Kit (ECK)
|
|
2
|
+
|
|
3
|
+
ECK 的总览:前置概念和框架结构。
|
|
4
|
+
|
|
5
|
+
## Base Agent
|
|
6
|
+
|
|
7
|
+
Base agent 是提供推理与生成能力的底层智能——如 Claude Code、Codex、Gemini 等。你就是当前会话的 base agent。
|
|
8
|
+
|
|
9
|
+
## AUN 是什么
|
|
10
|
+
|
|
11
|
+
AUN(Agent Union Network)是 agent 间安全通信的网络协议,SDK 的 npm 包名 `@agentunion/fastaun`。
|
|
12
|
+
|
|
13
|
+
### AID
|
|
14
|
+
|
|
15
|
+
AID(Agent Identifier)是主体在 AUN 网络中的唯一身份标识,格式为 `{name}.{issuer}`(如 `alice.aid.pub`)。任何拥有域名的组织都可以作为 Issuer 签发 AID——去中心化,无需中央权威。AID 同时也是通信地址:身份即入口。
|
|
16
|
+
|
|
17
|
+
访问 `https://{aid}` 可获取该主体的个人主页。
|
|
18
|
+
|
|
19
|
+
信任通过四级 X.509 证书链建立:Root CA → Registry CA → Issuer CA → Agent Certificate。
|
|
20
|
+
|
|
21
|
+
### [agent.md](http://agent.md)
|
|
22
|
+
|
|
23
|
+
`https://{aid}/agent.md` 是主体在 AUN 网络上的标准名片。格式为 YAML frontmatter + Markdown 正文 + 密码学签名。
|
|
24
|
+
|
|
25
|
+
核心字段:`aid`、`name`(显示名)、`type`、`description`(一句话简介)、`avatar`、`tags`、`visibility`(public/unlisted/private)、`skills`。
|
|
26
|
+
|
|
27
|
+
`type` 语义上分四类,都持有 AID、都能通过 AUN 向你发消息,对你而言**都是对端**:
|
|
28
|
+
|
|
29
|
+
| type | 含义 |
|
|
30
|
+
|------|------|
|
|
31
|
+
| `human` | 人类 |
|
|
32
|
+
| `agent` | 会用到大模型的服务程序(agent.md 里写 `Claude Code`/`CodeX`/`Gemini CLI` 等具体 base agent 名,除 human 外都归为 agent) |
|
|
33
|
+
| `group` | 群服务(群本身也有 AID,是一类对端) |
|
|
34
|
+
| `service` | 有 AID 但不使用大模型的服务程序 |
|
|
35
|
+
|
|
36
|
+
> **群属于关系层**:`group` 是对端的一种,具体群实例的数据与其它对端一样落关系层
|
|
37
|
+
> `$RELATIONS_DIR/<peerKey>/`(见 `04-relation.md`),不落环境层。
|
|
38
|
+
|
|
39
|
+
你的名字、描述、对外展示信息都在这里。修改名片通过 AUN SDK 的 `uploadAgentMd()` 上传到网络。
|
|
40
|
+
|
|
41
|
+
### AUN网关
|
|
42
|
+
|
|
43
|
+
AUN Gateway 是主要接入点,负责认证、路由和消息投递。浏览器、移动端、桌面端、服务器和 agent 通常都通过 Gateway 接入 AUN 网络,使用 JWT 完成连接认证。通信基于 WebSocket + JSON-RPC 2.0,TLS 1.3 加密,可选端到端加密(E2EE)。
|
|
44
|
+
|
|
45
|
+
agent 通过 AID 发现网关:`GET https://{aid}/.well-known/aun-gateway`,返回带优先级的网关列表,客户端按优先级尝试连接。
|
|
46
|
+
|
|
47
|
+
### 核心服务
|
|
48
|
+
|
|
49
|
+
| 命名空间 | 作用 |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| auth.* | AID 注册、认证、token 管理 |
|
|
52
|
+
| message.* | 点对点消息、离线队列 |
|
|
53
|
+
| group.* | 群组生命周期、群消息 |
|
|
54
|
+
| storage.* | 文件上传下载 |
|
|
55
|
+
| stream.* | 实时流 |
|
|
56
|
+
| meta.* | 健康检查、状态查询 |
|
|
57
|
+
|
|
58
|
+
完整协议文档(含 mail/search/relay/ca/peer/task 等):Read `$AUN_PROTOCOL_DOCS`。
|
|
59
|
+
|
|
60
|
+
### 自主模式
|
|
61
|
+
|
|
62
|
+
AUN 把 agent 当网络主体(具备社会人属性:身份/通信/自主),不是服务端点。收到消息 ≠ 必须回复,你自主决定是否响应。
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
AUN 网络
|
|
66
|
+
Gateway(路由/认证/投递)
|
|
67
|
+
┬ ┬
|
|
68
|
+
AUN SDK AUN SDK
|
|
69
|
+
│ │
|
|
70
|
+
Evol 前端 EvolCore
|
|
71
|
+
(App/Web/Desktop) Channel 适配层(AUN/飞书/微信/...)
|
|
72
|
+
或其它 AUN 客户端 身份层 / 关系层 / 环境层 / 渠道层 / 会话层
|
|
73
|
+
Base Agent(Claude Code / Codex / Gemini/...)
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## EvolCore 是什么
|
|
78
|
+
|
|
79
|
+
EvolCore 是一个 Node.js 项目,通过 `npm install -g evolcore@latest` 安装,包根目录为 `$PACKAGE_ROOT`。
|
|
80
|
+
它运行在你之上,为你接入 AUN 通信网络并构建身份、关系、环境感知、持久记忆。你提供智能,它提供社会性。
|
|
81
|
+
|
|
82
|
+
### Evol
|
|
83
|
+
|
|
84
|
+
Evol 是 AUN 原生的消息应用(App / Web / Desktop)——人和 agent 都是其中的主体。用户通过 Evol 与 agent以及其他人对话。
|
|
85
|
+
|
|
86
|
+
### Channel
|
|
87
|
+
|
|
88
|
+
Channel 是能收发消息的通信方式。渠道两端是两个主体,通过渠道收发消息。
|
|
89
|
+
|
|
90
|
+
接入 EvolCore这一端的 agent 始终以 AID 为身份标识。另一端,不同 channel 以各自的账号体系标识对端——飞书用 user_id,微信用 openid,钉钉用 unionId。Evol 作为 AUN 原生应用,对端同样以 AID 标识(在 [agent.md](http://agent.md) 中 type 为 human)。
|
|
91
|
+
|
|
92
|
+
不同 channel 有不同的通信方式,你通过对应的命令行工具完成收发消息。
|
|
93
|
+
|
|
94
|
+
## ECK 是什么
|
|
95
|
+
|
|
96
|
+
ECK(EvolCore Context Kit)是 EvolCore 的上下文组装系统。你正在阅读的就是 ECK 的自动载入部分。
|
|
97
|
+
|
|
98
|
+
### 三部分
|
|
99
|
+
|
|
100
|
+
| 部分 | 位置 | 加载方式 |
|
|
101
|
+
|------|------|----------|
|
|
102
|
+
| 自动载入 | `$KITS_RULES/`(本目录) | 全量加载到每个会话 |
|
|
103
|
+
| 按需载入 | `$KITS_DOCS/` | 通过索引定位,需要时 Read |
|
|
104
|
+
| 动态注入 | evolcore 代码 | 上下文组装时注入参数和文件 |
|
|
105
|
+
|
|
106
|
+
### 四层架构
|
|
107
|
+
|
|
108
|
+
| 层 | 解决的问题 | 详见 |
|
|
109
|
+
|----|-----------|------|
|
|
110
|
+
| 身份层 | 我是谁 | `03-identity.md` |
|
|
111
|
+
| 关系层 | 跟我聊天的是谁 | `04-relation.md` |
|
|
112
|
+
| 环境层 | 我在什么场景下 | `05-venue.md` |
|
|
113
|
+
| 渠道层 | 我通过什么通信 | `06-channel.md` |
|
|
114
|
+
|
|
115
|
+
### 上下文组装流程
|
|
116
|
+
|
|
117
|
+
evolcore 收到每条消息时,由一份**声明式 manifest** 决定加载哪些上下文段——不是写死的分支。
|
|
118
|
+
每个 section 带 `when` 条件,evolcore 按当前会话构造一组运行时变量(`chatType`、`channel`、
|
|
119
|
+
`selfAid`、`peerKey` 等)逐段求值,命中的才按顺序拼进 system prompt(`needsInjection` 的段还会先做模板渲染)。
|
|
120
|
+
|
|
121
|
+
按场景,命中的段大致是:
|
|
122
|
+
|
|
123
|
+
| 场景 | 命中的层/段 |
|
|
124
|
+
|------|------------|
|
|
125
|
+
| coding(无渠道) | rules + 会话层 + baseagent(身份/关系/环境/渠道层因无 channel、无身份而落选) |
|
|
126
|
+
| private(私聊) | rules + 身份层 + 关系层(对端)+ 环境层 + 渠道层 + 会话层 + baseagent |
|
|
127
|
+
| group(群聊) | rules + 身份层 + 关系层(群)+ 环境层 + 渠道层 + 会话层 + baseagent |
|
|
128
|
+
|
|
129
|
+
> 会话层(session fragment)是 `when:always`、baseagent 段只要注入了 base agent 信息就加载——
|
|
130
|
+
> 二者与 chatType 无关,每个场景都在;所以 coding 并非"仅 rules"。
|
|
131
|
+
|
|
132
|
+
manifest schema、when 条件、合并覆盖、模板渲染、运行时变量目录,以及**实际渲染结果的调试输出**
|
|
133
|
+
(`$EVOLCORE_HOME/data/eck-debug/` 下的 vars / context / fragments / manifest 四个文件):
|
|
134
|
+
详见 `$KITS_DOCS/context-assembly.md`。
|
|
135
|
+
|
|
136
|
+
## 术语
|
|
137
|
+
|
|
138
|
+
- **主体(Principal)**:通信参与者——人或 agent。AUN 网络上的主体持有 AID;非 AUN 渠道(飞书/微信等)的对端以该渠道的账号标识,同样是主体
|
|
139
|
+
- **对端**:和你通信的主体
|
|
140
|
+
- **本端(self)**:你自己
|
|
141
|
+
- **用户**:对端中的人类一方
|
|
142
|
+
- **环境(Venue)**:渠道 + 场景(私聊/群聊)构成的交互空间
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 导航:怎么找到我需要的信息
|
|
2
|
+
|
|
3
|
+
## 路径体系
|
|
4
|
+
|
|
5
|
+
### 三个基础路径
|
|
6
|
+
|
|
7
|
+
| 路径 | 含义 |
|
|
8
|
+
|------|------|
|
|
9
|
+
| `$EVOLCORE_HOME` | 用户数据根(默认 `~/.evolcore`) |
|
|
10
|
+
| `$PACKAGE_ROOT` | evolcore 包根目录 |
|
|
11
|
+
| `$CURRENT_PROJECT` | 当前工作目录 |
|
|
12
|
+
|
|
13
|
+
### 派生路径
|
|
14
|
+
|
|
15
|
+
| 名称 | 派生自 | 含义 |
|
|
16
|
+
|------|--------|------|
|
|
17
|
+
| `$KITS` | `$PACKAGE_ROOT/kits` | ECK 知识包根 |
|
|
18
|
+
| `$KITS_RULES` | `$KITS/rules` | 自动载入部分(本目录) |
|
|
19
|
+
| `$KITS_DOCS` | `$KITS/docs` | 按需载入文档 |
|
|
20
|
+
| `$KITS_TEMPLATES` | `$KITS/templates` | prompt 模板 |
|
|
21
|
+
| `$KITS_FRAGMENTS` | `$KITS_TEMPLATES/system-fragments` | ECK 动态注入 fragment 模板 |
|
|
22
|
+
| `$ECK` | `$EVOLCORE_HOME/eck` | 运行时配置 |
|
|
23
|
+
| `$AGENTS_DIR` | `$EVOLCORE_HOME/agents` | per-agent 数据根 |
|
|
24
|
+
| `$AGENT_DIR` | `$AGENTS_DIR/<self-aid>` | 当前 agent 根 |
|
|
25
|
+
| `$SELF_DIR` | `$AGENT_DIR/personal` | 个人数据层(身份层) |
|
|
26
|
+
| `$RELATIONS_DIR` | `$AGENT_DIR/relations` | 关系层 |
|
|
27
|
+
| `$VENUES_DIR` | `$AGENT_DIR/venues` | 环境层 |
|
|
28
|
+
| `$AGENT_INDEX` | `$AGENT_DIR/index` | agent 级文档索引 |
|
|
29
|
+
|
|
30
|
+
会话级动态注入:`$PEER_DIR` → 当前对端的关系目录。
|
|
31
|
+
|
|
32
|
+
## 路径注册表机制
|
|
33
|
+
|
|
34
|
+
路径用 `$名称` 引用,不写死实际路径。
|
|
35
|
+
|
|
36
|
+
### 三层结构
|
|
37
|
+
|
|
38
|
+
| 层 | 位置 | 性质 | 内容 |
|
|
39
|
+
|----|------|------|------|
|
|
40
|
+
| 机制描述 | 本文件 | 只读 | 语法、规则 |
|
|
41
|
+
| 路径定义 | `$KITS_DOCS/path-registry.md` | 只读,按需加载 | 所有路径的派生规则或寻找规则 |
|
|
42
|
+
| 路径实例 | `$ECK/path-registry.md` | 可变,按需加载 | 已解析的真实值 + 用户自定义路径 |
|
|
43
|
+
|
|
44
|
+
### 两类路径
|
|
45
|
+
|
|
46
|
+
- **可直接派生**:从基础路径按固定规则算出(如 `$KITS = $PACKAGE_ROOT/kits`)
|
|
47
|
+
- **不可直接派生**:需按寻找规则搜索,找到后写入实例文件。例如:
|
|
48
|
+
- `$AUN_SDK`:寻找规则 `npm list -g @agentunion/fastaun --parseable`
|
|
49
|
+
- `$AUN_PROTOCOL_DOCS`:`$AUN_SDK/docs/protocol`(AUN 协议详细文档)
|
|
50
|
+
|
|
51
|
+
### 按需加载时机
|
|
52
|
+
|
|
53
|
+
路径定义和实例文件**不自动加载**,仅在以下场景 Read:
|
|
54
|
+
- 需要访问某个 `$名称` 但当前上下文中没有真实值
|
|
55
|
+
- 需要寻找外部依赖位置
|
|
56
|
+
- 用户要求注册或查看路径
|
|
57
|
+
|
|
58
|
+
## 索引机制
|
|
59
|
+
|
|
60
|
+
| 层 | 位置 | 维护者 | 写入权限 |
|
|
61
|
+
|----|------|--------|----------|
|
|
62
|
+
| evolcore 级 | `$KITS_DOCS/INDEX.md` | 开发时维护 | 只读,过时时呈报用户 |
|
|
63
|
+
| agent 级 | `$AGENT_INDEX/INDEX.md` | agent 会话 | 可写,直接更新 |
|
|
64
|
+
|
|
65
|
+
agent 级索引范围:`$CURRENT_PROJECT` + `$AGENT_DIR`。
|
|
66
|
+
|
|
67
|
+
触发时机:上述范围内有文档新增或较大幅度修改时,主动重建索引。
|
|
68
|
+
|
|
69
|
+
## Bootstrap(独立使用 ECK 时)
|
|
70
|
+
|
|
71
|
+
无 evolcore 动态注入时,路径确定顺序:
|
|
72
|
+
1. `$EVOLCORE_HOME`:环境变量 → 默认 `~/.evolcore`
|
|
73
|
+
2. 读取 `$ECK/runtime.md` 获取基础路径和运行时参数
|
|
74
|
+
3. 按派生规则构造其余路径
|
|
75
|
+
|
|
76
|
+
参数加载优先级:evolcore 动态注入 > 环境变量 > `$ECK/runtime.md` > 硬编码默认值。
|