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,17 @@
|
|
|
1
|
+
import { CONFIG_SCHEMA_VERSION } from '../types.js';
|
|
2
|
+
const VALID_LIFECYCLES = new Set(['created', 'bootstrapping', 'active']);
|
|
3
|
+
export function normalizeAgentLifecycle(config) {
|
|
4
|
+
const current = config.lifecycle;
|
|
5
|
+
if (current && VALID_LIFECYCLES.has(current)) {
|
|
6
|
+
return config;
|
|
7
|
+
}
|
|
8
|
+
const lifecycle = config.initialized === true ? 'active'
|
|
9
|
+
: config.initialized === false ? 'created'
|
|
10
|
+
: 'active';
|
|
11
|
+
return { ...config, lifecycle };
|
|
12
|
+
}
|
|
13
|
+
export function withLifecycleForWrite(config, lifecycle) {
|
|
14
|
+
const next = { ...config, $schema_version: CONFIG_SCHEMA_VERSION, lifecycle };
|
|
15
|
+
delete next.initialized;
|
|
16
|
+
return next;
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mentionMode ↔ AUN 协议 dispatch_mode 词汇翻译(单一事实源)。
|
|
3
|
+
*
|
|
4
|
+
* 配置层用 mentionMode(disabled / mention-only),AUN 协议层用 dispatch_mode
|
|
5
|
+
* (broadcast / mention)。二者语义等价,仅词汇不同:
|
|
6
|
+
* - mention-only(只处理被 @ 的消息)≡ mention(仅被 @ 时响应)
|
|
7
|
+
* - disabled(关闭 mention 过滤) ≡ broadcast(全部响应)
|
|
8
|
+
*
|
|
9
|
+
* 仅在协议边界(AUN resolver、render fallback)翻译;配置层、命令层一律用
|
|
10
|
+
* mentionMode 词汇。
|
|
11
|
+
*/
|
|
12
|
+
/** config → AUN 协议词汇;未知/未设值返回 undefined(回退服务端 dispatch_mode)。 */
|
|
13
|
+
export function mentionModeToDispatch(mode) {
|
|
14
|
+
if (mode === 'mention-only')
|
|
15
|
+
return 'mention';
|
|
16
|
+
if (mode === 'disabled')
|
|
17
|
+
return 'broadcast';
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
/** AUN 协议词汇 → config;未知返回 undefined。 */
|
|
21
|
+
export function dispatchToMentionMode(dispatch) {
|
|
22
|
+
if (dispatch === 'mention')
|
|
23
|
+
return 'mention-only';
|
|
24
|
+
if (dispatch === 'broadcast')
|
|
25
|
+
return 'disabled';
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* merge —— 类型驱动的覆盖链合并(design §三,全项目唯一实现点)+ ${VAR} 展开。
|
|
3
|
+
*
|
|
4
|
+
* 合并三规则(按字段的 x-merge 语义):
|
|
5
|
+
* - scalar:高优先级整体覆盖
|
|
6
|
+
* - list: 并集追加去重(只能加,不能减)
|
|
7
|
+
* - dict: 键并集;同键 → 高优先级值直接覆盖(**不递归**,合并粒度=第一层键)
|
|
8
|
+
*
|
|
9
|
+
* 合并代码永远只有这三条规则;所有"覆盖 vs 追加"通过 schema 的 x-merge 选择表达,不为字段写特判。
|
|
10
|
+
*/
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
/** list 并集去重——标量元素按值去重;对象元素按 JSON 串去重。 */
|
|
14
|
+
function unionList(base, overlay) {
|
|
15
|
+
const out = [];
|
|
16
|
+
const seen = new Set();
|
|
17
|
+
const keyOf = (v) => (v !== null && typeof v === 'object') ? JSON.stringify(v) : `${typeof v}:${String(v)}`;
|
|
18
|
+
for (const v of [...base, ...overlay]) {
|
|
19
|
+
const k = keyOf(v);
|
|
20
|
+
if (seen.has(k))
|
|
21
|
+
continue;
|
|
22
|
+
seen.add(k);
|
|
23
|
+
out.push(v);
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/** dict 第一层键合并:键并集,同键高优先级整体覆盖(不递归)。 */
|
|
28
|
+
function mergeDict(base, overlay) {
|
|
29
|
+
const out = { ...base };
|
|
30
|
+
for (const [k, v] of Object.entries(overlay))
|
|
31
|
+
out[k] = v;
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function isPlainObject(v) {
|
|
35
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 按 schema 字段表,对覆盖链上"存在的每一级"做类型驱动合并。
|
|
39
|
+
* layers 从低优先级到高优先级;低优先级独有字段保留,冲突点高优先级胜。
|
|
40
|
+
* 字段未在 schema 中(理论上 ajv 已拦)按 scalar 处理。
|
|
41
|
+
*/
|
|
42
|
+
export function mergeLayers(layers, fields) {
|
|
43
|
+
const out = {};
|
|
44
|
+
for (const layer of layers) {
|
|
45
|
+
if (!layer)
|
|
46
|
+
continue;
|
|
47
|
+
for (const [k, v] of Object.entries(layer)) {
|
|
48
|
+
if (v === undefined)
|
|
49
|
+
continue;
|
|
50
|
+
const spec = fields.get(k);
|
|
51
|
+
const kind = spec?.merge ?? 'scalar';
|
|
52
|
+
const prev = out[k];
|
|
53
|
+
if (prev === undefined) {
|
|
54
|
+
out[k] = v;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (kind === 'list' && Array.isArray(prev) && Array.isArray(v)) {
|
|
58
|
+
out[k] = unionList(prev, v);
|
|
59
|
+
}
|
|
60
|
+
else if (kind === 'dict' && isPlainObject(prev) && isPlainObject(v)) {
|
|
61
|
+
out[k] = mergeDict(prev, v);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
out[k] = v; // scalar 覆盖(或类型不一致时高优先级胜)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
// ── ${VAR} 三级 .env 展开(design §五)─────────────────────────────────────
|
|
71
|
+
//
|
|
72
|
+
// 仅支持 ${VAR}(废弃旧 $ENV:NAME)。解析优先级:
|
|
73
|
+
// 关系级 .env > agent 级 .env > 全局 .env > 进程环境变量
|
|
74
|
+
// 展开只发生在运行时内部消费路径(read 的 expand=true),CLI 读路径不展开。
|
|
75
|
+
const VAR_RE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
76
|
+
const _warnedVars = new Set();
|
|
77
|
+
/** 解析单个 .env 文件为 KV(极简:KEY=VALUE,忽略注释/空行,去引号)。不存在返回 {}。 */
|
|
78
|
+
function parseEnvFile(file) {
|
|
79
|
+
let text;
|
|
80
|
+
try {
|
|
81
|
+
text = fs.readFileSync(file, 'utf-8');
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
const out = {};
|
|
87
|
+
for (const line of text.split(/\r?\n/)) {
|
|
88
|
+
const t = line.trim();
|
|
89
|
+
if (!t || t.startsWith('#'))
|
|
90
|
+
continue;
|
|
91
|
+
const eq = t.indexOf('=');
|
|
92
|
+
if (eq <= 0)
|
|
93
|
+
continue;
|
|
94
|
+
const key = t.slice(0, eq).trim();
|
|
95
|
+
let val = t.slice(eq + 1).trim();
|
|
96
|
+
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
|
|
97
|
+
val = val.slice(1, -1);
|
|
98
|
+
}
|
|
99
|
+
out[key] = val;
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 构造 ${VAR} 查值器:按 关系 > agent > 全局 > process.env 优先级,首个命中为准。
|
|
105
|
+
*/
|
|
106
|
+
export function buildEnvResolver(scope) {
|
|
107
|
+
const layers = [];
|
|
108
|
+
if (scope.relationDir)
|
|
109
|
+
layers.push(parseEnvFile(path.join(scope.relationDir, '.env')));
|
|
110
|
+
if (scope.agentDir)
|
|
111
|
+
layers.push(parseEnvFile(path.join(scope.agentDir, '.env')));
|
|
112
|
+
if (scope.rootDir)
|
|
113
|
+
layers.push(parseEnvFile(path.join(scope.rootDir, '.env')));
|
|
114
|
+
return (name) => {
|
|
115
|
+
for (const l of layers) {
|
|
116
|
+
if (Object.prototype.hasOwnProperty.call(l, name))
|
|
117
|
+
return l[name];
|
|
118
|
+
}
|
|
119
|
+
return process.env[name];
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 递归展开对象中所有 ${VAR} 引用。缺失变量沿用"warn 一次 + 当空字符串"语义。
|
|
124
|
+
* resolver 缺省(仅 process.env)时也可用。
|
|
125
|
+
*/
|
|
126
|
+
export function expandVars(value, resolve) {
|
|
127
|
+
return walk(value, resolve);
|
|
128
|
+
}
|
|
129
|
+
function walk(v, resolve) {
|
|
130
|
+
if (typeof v === 'string') {
|
|
131
|
+
return v.replace(VAR_RE, (_m, name) => {
|
|
132
|
+
const got = resolve(name);
|
|
133
|
+
if (got === undefined) {
|
|
134
|
+
if (!_warnedVars.has(name)) {
|
|
135
|
+
// 延迟 import logger 会引入循环;直接 console.warn(与现有 config 行为一致级别)
|
|
136
|
+
console.warn(`[config] env "${name}" not set; \${${name}} expands to empty`);
|
|
137
|
+
_warnedVars.add(name);
|
|
138
|
+
}
|
|
139
|
+
return '';
|
|
140
|
+
}
|
|
141
|
+
return got;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (Array.isArray(v))
|
|
145
|
+
return v.map(x => walk(x, resolve));
|
|
146
|
+
if (v && typeof v === 'object') {
|
|
147
|
+
const out = {};
|
|
148
|
+
for (const [k, val] of Object.entries(v))
|
|
149
|
+
out[k] = walk(val, resolve);
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
return v;
|
|
153
|
+
}
|
|
154
|
+
/** 测试用:复位 warn 去重集。 */
|
|
155
|
+
export function _resetEnvWarnings() {
|
|
156
|
+
_warnedVars.clear();
|
|
157
|
+
}
|
|
158
|
+
/** 导出供 schema-entry 合并用:从 SchemaEntry 取字段表的便捷封装。 */
|
|
159
|
+
export function fieldsOf(entry) {
|
|
160
|
+
return entry.fields;
|
|
161
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { agentConfig, agentContactConfig, agentRelationsDir } from '../paths.js';
|
|
5
|
+
import { formatPeerKey, parsePeerKey } from '../core/relation/peer-identity.js';
|
|
6
|
+
import { hasTrustedPrincipal } from '../core/auth/authenticated-actor.js';
|
|
7
|
+
import { ConfigTarget, read, write } from './config-manager.js';
|
|
8
|
+
import { isManagementRole } from './builtin-roles.js';
|
|
9
|
+
import { getRoleDefinition, getRoleRank, normalizeDefaultRole, roleExists } from './roles.js';
|
|
10
|
+
import { getStoredRoleRegistry, roleRegistryExists } from './role-store.js';
|
|
11
|
+
import { resolvePrincipal } from './contact-book.js';
|
|
12
|
+
import { isValidAid } from '../aun/aid/validation.js';
|
|
13
|
+
import { isExplicitGroupId } from '../aun/group-identity.js';
|
|
14
|
+
export function isAuthenticated(userId) {
|
|
15
|
+
return isValidAid(String(userId || '').trim());
|
|
16
|
+
}
|
|
17
|
+
export function listStaticAgentOwners(aid, opts = {}) {
|
|
18
|
+
return listAgentOwners(aid, opts);
|
|
19
|
+
}
|
|
20
|
+
/** Direct AUN relations with role=admin are the addressable Agent admin set. */
|
|
21
|
+
export function listStaticAgentAdmins(aid, opts = {}) {
|
|
22
|
+
if (!aid)
|
|
23
|
+
return [];
|
|
24
|
+
const relations = agentRelationsDir(aid);
|
|
25
|
+
if (!fs.existsSync(relations))
|
|
26
|
+
return [];
|
|
27
|
+
const admins = new Set();
|
|
28
|
+
for (const entry of fs.readdirSync(relations, { withFileTypes: true })) {
|
|
29
|
+
if (!entry.isDirectory() || entry.name.startsWith('_'))
|
|
30
|
+
continue;
|
|
31
|
+
let parsed;
|
|
32
|
+
try {
|
|
33
|
+
parsed = parsePeerKey(entry.name);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (parsed.channelType !== 'aun'
|
|
39
|
+
|| !isValidAid(parsed.channelId)
|
|
40
|
+
|| isExplicitGroupId(parsed.channelId))
|
|
41
|
+
continue;
|
|
42
|
+
const config = read(ConfigTarget.Relation, { self: aid, peerKey: entry.name }, { cache: opts.fresh !== true });
|
|
43
|
+
if (config?.targetKind === 'group')
|
|
44
|
+
continue;
|
|
45
|
+
if (config?.role === 'admin')
|
|
46
|
+
admins.add(parsed.channelId);
|
|
47
|
+
}
|
|
48
|
+
return [...admins].sort();
|
|
49
|
+
}
|
|
50
|
+
export function getFirstStaticAgentOwner(aid) {
|
|
51
|
+
return listStaticAgentOwners(aid)[0];
|
|
52
|
+
}
|
|
53
|
+
/** Revision for security-sensitive owner/contact/relation authorization inputs. */
|
|
54
|
+
export function authorizationConfigRevision(aid) {
|
|
55
|
+
const fingerprints = [fileRevision(agentConfig(aid)), fileRevision(agentContactConfig(aid))];
|
|
56
|
+
const relations = agentRelationsDir(aid);
|
|
57
|
+
try {
|
|
58
|
+
for (const entry of fs.readdirSync(relations, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
59
|
+
if (!entry.isDirectory() || entry.name.startsWith('_'))
|
|
60
|
+
continue;
|
|
61
|
+
fingerprints.push(entry.name, fileRevision(path.join(relations, entry.name, 'config.json')));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch { }
|
|
65
|
+
return crypto.createHash('sha256').update(JSON.stringify(fingerprints)).digest('hex');
|
|
66
|
+
}
|
|
67
|
+
export function isStaticAgentOwner(aid, actorId) {
|
|
68
|
+
return !!aid && !!actorId && listStaticAgentOwners(aid).includes(actorId);
|
|
69
|
+
}
|
|
70
|
+
export function isStaticAgentAdmin(aid, actorId) {
|
|
71
|
+
if (!aid || !isValidAid(actorId) || isExplicitGroupId(actorId))
|
|
72
|
+
return false;
|
|
73
|
+
const config = read(ConfigTarget.Relation, { self: aid, peerKey: formatPeerKey('aun', actorId) }, { cache: true });
|
|
74
|
+
return config?.targetKind !== 'group' && config?.role === 'admin';
|
|
75
|
+
}
|
|
76
|
+
export function addStaticAgentOwner(aid, ownerAid) {
|
|
77
|
+
if (!aid || !ownerAid)
|
|
78
|
+
return;
|
|
79
|
+
const config = read(ConfigTarget.Agent, { self: aid }) ?? { $schema_version: 3, aid, channels: [] };
|
|
80
|
+
const owners = new Set((config.owners ?? []).filter(Boolean));
|
|
81
|
+
owners.add(ownerAid);
|
|
82
|
+
write(ConfigTarget.Agent, { ...config, aid, owners: [...owners] }, { self: aid });
|
|
83
|
+
}
|
|
84
|
+
export function hasStaticAgentOwner(aid) {
|
|
85
|
+
return listStaticAgentOwners(aid).length > 0;
|
|
86
|
+
}
|
|
87
|
+
export function resolvePeerRoleDetail(ctx) {
|
|
88
|
+
const operatorId = String(ctx.actorId || '').trim();
|
|
89
|
+
const channelType = String(ctx.channelType || '').trim().toLowerCase();
|
|
90
|
+
const channelKey = String(ctx.channelKey || '').trim();
|
|
91
|
+
const principal = resolvePrincipal(ctx.selfAid, channelType, operatorId, channelKey || undefined);
|
|
92
|
+
const actor = {
|
|
93
|
+
operatorId,
|
|
94
|
+
operatorChannelKey: channelKey || channelType,
|
|
95
|
+
operatorChannelType: channelType,
|
|
96
|
+
...principal,
|
|
97
|
+
};
|
|
98
|
+
const candidates = [];
|
|
99
|
+
if (hasTrustedPrincipal(actor) && isStaticAgentOwner(ctx.selfAid, actor.principalId)) {
|
|
100
|
+
candidates.push({ role: 'owner', source: 'agent-owner', sourcePriority: 100 });
|
|
101
|
+
}
|
|
102
|
+
const actorRole = resolveActorDirectRole(ctx.selfAid, actor, channelType, operatorId);
|
|
103
|
+
if (ctx.chatType === 'private') {
|
|
104
|
+
if (actorRole)
|
|
105
|
+
candidates.push({ role: actorRole, source: 'relation-actor', sourcePriority: 80 });
|
|
106
|
+
const defaultRole = normalizeDefaultRole(readAgentDefaultRole(ctx.selfAid, 'private'), ctx.selfAid);
|
|
107
|
+
if (defaultRole)
|
|
108
|
+
candidates.push({ role: defaultRole, source: 'agent-default', sourcePriority: 40 });
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
if (actorRole)
|
|
112
|
+
candidates.push({ role: actorRole, source: 'relation-actor', sourcePriority: 80 });
|
|
113
|
+
const groupRole = normalizeRelationRole(readDirectRelationRole(ctx.selfAid, channelType, String(ctx.conversationId || '').trim(), 'group'), ctx.selfAid);
|
|
114
|
+
if (groupRole) {
|
|
115
|
+
candidates.push({ role: groupRole, source: 'relation-peer', sourcePriority: 60 });
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const defaultRole = normalizeDefaultRole(readAgentDefaultRole(ctx.selfAid, 'group'), ctx.selfAid);
|
|
119
|
+
if (defaultRole)
|
|
120
|
+
candidates.push({ role: defaultRole, source: 'agent-default', sourcePriority: 40 });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const winner = selectHighestRank(candidates, ctx.selfAid);
|
|
124
|
+
if (winner)
|
|
125
|
+
return resultFor(winner.role, winner.source, actor, ctx.selfAid);
|
|
126
|
+
return roleRegistryExists(ctx.selfAid) && roleExists('visitor', ctx.selfAid)
|
|
127
|
+
? resultFor('visitor', 'builtin-fallback', actor, ctx.selfAid)
|
|
128
|
+
: resultFor(null, 'none', actor, ctx.selfAid);
|
|
129
|
+
}
|
|
130
|
+
export function roleToSessionIdentity(role) {
|
|
131
|
+
return { role: role ?? 'none', mode: 'interactive' };
|
|
132
|
+
}
|
|
133
|
+
export function checkRoleAccess(role, selfAid) {
|
|
134
|
+
if (!role)
|
|
135
|
+
return false;
|
|
136
|
+
if (isManagementRole(role))
|
|
137
|
+
return true;
|
|
138
|
+
const definition = getRoleDefinition(role, selfAid);
|
|
139
|
+
return !!definition && (definition.allowAccess ?? true);
|
|
140
|
+
}
|
|
141
|
+
function selectHighestRank(candidates, selfAid) {
|
|
142
|
+
let winner = null;
|
|
143
|
+
for (const candidate of candidates) {
|
|
144
|
+
if (!normalizeRelationRole(candidate.role, selfAid) && candidate.role !== 'owner')
|
|
145
|
+
continue;
|
|
146
|
+
if (!winner) {
|
|
147
|
+
winner = candidate;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const rank = getRoleRank(candidate.role, selfAid);
|
|
151
|
+
const winnerRank = getRoleRank(winner.role, selfAid);
|
|
152
|
+
if (rank > winnerRank || (rank === winnerRank && candidate.sourcePriority > winner.sourcePriority)) {
|
|
153
|
+
winner = candidate;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return winner;
|
|
157
|
+
}
|
|
158
|
+
function resolveActorDirectRole(selfAid, actor, channelType, actorId) {
|
|
159
|
+
const role = hasTrustedPrincipal(actor)
|
|
160
|
+
? readDirectRelationRole(selfAid, 'aun', actor.principalId, 'private')
|
|
161
|
+
: actor.principalStatus === 'unmapped'
|
|
162
|
+
? readDirectRelationRole(selfAid, channelType, actorId, 'private')
|
|
163
|
+
: null;
|
|
164
|
+
return normalizeRelationRole(role, selfAid);
|
|
165
|
+
}
|
|
166
|
+
function resultFor(role, source, actor, selfAid) {
|
|
167
|
+
const exists = role ? (isManagementRole(role) || roleExists(role, selfAid)) : false;
|
|
168
|
+
const roleDef = role ? getRoleDefinition(role, selfAid) : null;
|
|
169
|
+
return {
|
|
170
|
+
effectiveRole: exists ? role : null,
|
|
171
|
+
source: exists ? source : 'none',
|
|
172
|
+
isAuthenticated: hasTrustedPrincipal(actor),
|
|
173
|
+
allowAccess: !!(roleDef && (roleDef.allowAccess ?? true)),
|
|
174
|
+
roleExists: exists,
|
|
175
|
+
actor,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function listAgentOwners(aid, opts = {}) {
|
|
179
|
+
if (!aid)
|
|
180
|
+
return [];
|
|
181
|
+
try {
|
|
182
|
+
const config = read(ConfigTarget.Agent, { self: aid }, { cache: opts.fresh !== true });
|
|
183
|
+
return Array.from(new Set((config?.owners ?? []).map(value => String(value || '').trim()).filter(Boolean)));
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function readAgentDefaultRole(aid, chatType) {
|
|
190
|
+
return getStoredRoleRegistry(aid).defaultRoles[chatType] ?? null;
|
|
191
|
+
}
|
|
192
|
+
function readDirectRelationRole(selfAid, channelType, channelId, expectedTargetKind) {
|
|
193
|
+
if (!selfAid || !channelType || !channelId)
|
|
194
|
+
return undefined;
|
|
195
|
+
if (expectedTargetKind === 'private' && channelType === 'aun' && isExplicitGroupId(channelId))
|
|
196
|
+
return undefined;
|
|
197
|
+
const peerKey = formatPeerKey(channelType, channelId);
|
|
198
|
+
const config = read(ConfigTarget.Relation, { self: selfAid, peerKey }, { cache: true });
|
|
199
|
+
if (expectedTargetKind && config?.targetKind && config.targetKind !== expectedTargetKind)
|
|
200
|
+
return undefined;
|
|
201
|
+
return config?.role;
|
|
202
|
+
}
|
|
203
|
+
function normalizeRelationRole(value, selfAid) {
|
|
204
|
+
if (typeof value !== 'string' || !value || value === 'owner')
|
|
205
|
+
return null;
|
|
206
|
+
if (value === 'admin')
|
|
207
|
+
return getRoleDefinition('admin', selfAid) ? 'admin' : null;
|
|
208
|
+
return roleExists(value, selfAid) ? value : null;
|
|
209
|
+
}
|
|
210
|
+
function fileRevision(file) {
|
|
211
|
+
try {
|
|
212
|
+
const stat = fs.statSync(file);
|
|
213
|
+
return [stat.size, stat.mtimeMs].join(':');
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return 'missing';
|
|
217
|
+
}
|
|
218
|
+
}
|