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,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 引擎 —— 主动流(proactive)
|
|
3
|
+
*
|
|
4
|
+
* 行为自合并前的 modes/proactive(ProactiveMode)下沉,语义不变:
|
|
5
|
+
* 工具调用才回复,普通文本作为思考过程(thought 投影);含首发表态、
|
|
6
|
+
* 工具汇报提醒、队列未读提醒、Unknown skill 兜底。
|
|
7
|
+
*
|
|
8
|
+
* flow 是无状态单例:per-message 运行时状态存 ctx.state['proactive'],
|
|
9
|
+
* 依赖全部由调用点显式传入。
|
|
10
|
+
*/
|
|
11
|
+
const STATE_KEY = 'proactive';
|
|
12
|
+
const TOOL_REPORT_INTERVAL = 10;
|
|
13
|
+
function isHumanFacingMessage(message) {
|
|
14
|
+
if (message.source === 'trigger')
|
|
15
|
+
return false;
|
|
16
|
+
if (message.chatType === 'group')
|
|
17
|
+
return true;
|
|
18
|
+
return message.chatType === 'private' && message.peerType === 'human';
|
|
19
|
+
}
|
|
20
|
+
function buildState(message, cfg) {
|
|
21
|
+
// 默认值不在此硬编码:候选/出厂默认由模式 schema 声明,宿主组装 modeConfig 时注入
|
|
22
|
+
// (coordinator.schemaDefaults)。此处只读注入后的布尔——键缺失即视为关闭。
|
|
23
|
+
const preTool1stMsgChk = cfg.pre_tool_1stmsgchk === true;
|
|
24
|
+
const toolUseReminder = cfg.tool_use_reminder === true;
|
|
25
|
+
const humanFacing = isHumanFacingMessage(message);
|
|
26
|
+
return {
|
|
27
|
+
firstToolDone: false,
|
|
28
|
+
toolCount: 0,
|
|
29
|
+
lastQueueReminderLen: 0,
|
|
30
|
+
chatType: message.chatType,
|
|
31
|
+
peerType: message.peerType,
|
|
32
|
+
preTool1stMsgChk,
|
|
33
|
+
toolUseReminder,
|
|
34
|
+
firstSendRequired: preTool1stMsgChk && humanFacing,
|
|
35
|
+
toolReportRequired: toolUseReminder && humanFacing,
|
|
36
|
+
toolReportInterval: TOOL_REPORT_INTERVAL,
|
|
37
|
+
toolReportPending: false,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export const proactiveFlow = {
|
|
41
|
+
chatMode: 'proactive',
|
|
42
|
+
// ─── 入站决策:构造 runtimeState ───
|
|
43
|
+
handleInbound(message, ctx) {
|
|
44
|
+
ctx.logger.debug('[V1Engine] proactive inbound chatType=' + message.chatType + ' peerId=' + message.peerId);
|
|
45
|
+
const state = buildState(message, ctx.modeConfig ?? {});
|
|
46
|
+
return {
|
|
47
|
+
action: 'process',
|
|
48
|
+
queueBehavior: 'enqueue',
|
|
49
|
+
runtimeState: { proactive: state },
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
// ─── 出站决策:activity.batch → thought 投影 ───
|
|
53
|
+
handleOutbound(payload, ctx) {
|
|
54
|
+
ctx.logger.debug('[V1Engine] proactive outbound kind=' + (payload.kind ?? 'unknown'));
|
|
55
|
+
if (payload.kind === 'activity.batch') {
|
|
56
|
+
if (!ctx.channel.capabilities.supportsThought) {
|
|
57
|
+
return { method: 'suppress', reason: 'channel does not support thought' };
|
|
58
|
+
}
|
|
59
|
+
return { method: 'direct', type: 'thought' };
|
|
60
|
+
}
|
|
61
|
+
return { method: 'direct', type: 'message' };
|
|
62
|
+
},
|
|
63
|
+
// ─── beforeProcess:把 runtimeState 落入 ctx.state,供后续钩子共享 ───
|
|
64
|
+
beforeProcess(ctx) {
|
|
65
|
+
const state = buildState(ctx.message, ctx.modeConfig ?? {});
|
|
66
|
+
ctx.state.set(STATE_KEY, state);
|
|
67
|
+
},
|
|
68
|
+
// ─── configureRun:policyHook 首工具表态 ───
|
|
69
|
+
configureRun(ctx) {
|
|
70
|
+
const state = ctx.state.get(STATE_KEY);
|
|
71
|
+
if (!state || (!state.firstSendRequired && !state.toolReportRequired))
|
|
72
|
+
return undefined;
|
|
73
|
+
return {
|
|
74
|
+
policyHook: (toolName, toolInput) => {
|
|
75
|
+
const isSendCommand = ctx.isSendCommand(toolName, toolInput);
|
|
76
|
+
if (state.firstSendRequired && !state.firstToolDone) {
|
|
77
|
+
if (!isSendCommand) {
|
|
78
|
+
const cmdHint = state.chatType === 'group' ? 'ec group send' : 'ec msg send';
|
|
79
|
+
const target = state.chatType === 'group' ? '群里' : '对方';
|
|
80
|
+
return { block: true, reason: `请先用 ${cmdHint} 向${target}说明你的意图,再执行其他工具` };
|
|
81
|
+
}
|
|
82
|
+
state.firstToolDone = true;
|
|
83
|
+
}
|
|
84
|
+
if (state.toolReportPending) {
|
|
85
|
+
if (!isSendCommand) {
|
|
86
|
+
const cmdHint = state.chatType === 'group' ? 'ec group send' : 'ec msg send';
|
|
87
|
+
const target = state.chatType === 'group' ? '群里' : '对方';
|
|
88
|
+
return { block: true, reason: `工具调用已达到 ${state.toolCount} 次,请先用 ${cmdHint} 向${target}汇报当前情况和下一步意图,再执行其他工具` };
|
|
89
|
+
}
|
|
90
|
+
state.toolReportPending = false;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
// ─── onToolUse:队列未读提醒 + 工具汇报提醒 ───
|
|
97
|
+
onToolUse(ctx) {
|
|
98
|
+
const state = ctx.state.get(STATE_KEY);
|
|
99
|
+
if (!state || !state.toolUseReminder)
|
|
100
|
+
return;
|
|
101
|
+
// 队列未读变化提醒
|
|
102
|
+
const queueLen = ctx.getQueueLength();
|
|
103
|
+
if (queueLen !== state.lastQueueReminderLen) {
|
|
104
|
+
state.lastQueueReminderLen = queueLen;
|
|
105
|
+
if (queueLen > 0) {
|
|
106
|
+
const queueMsg = queueLen >= 5
|
|
107
|
+
? `⚠️ 有 ${queueLen} 条消息未读,请尽快完成当前任务,或使用 ec ctl queue 读取后同步处理。`
|
|
108
|
+
: `⚠️ 有 ${queueLen} 条消息未读,可使用 ec ctl queue 读取。`;
|
|
109
|
+
ctx.injectToModel(queueMsg);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// 工具计数(排除表态命令白名单)
|
|
113
|
+
const isAllowedTool = ctx.isSendCommand(ctx.toolName, ctx.toolInput);
|
|
114
|
+
if (state.toolReportRequired && !isAllowedTool)
|
|
115
|
+
state.toolCount++;
|
|
116
|
+
// 每 N 次工具调用警告
|
|
117
|
+
if (state.toolReportRequired && state.toolCount > 0 && state.toolCount % state.toolReportInterval === 0) {
|
|
118
|
+
state.toolReportPending = true;
|
|
119
|
+
const cmdHint = state.chatType === 'group' ? 'ec group send' : 'ec msg send';
|
|
120
|
+
const target = state.chatType === 'group' ? '群里' : '对方';
|
|
121
|
+
ctx.injectToModel(`⚠️ 工具调用已达到 ${state.toolCount} 次,请立即用 ${cmdHint} 向${target}汇报当前情况和下一步意图。`);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
// ─── onComplete:标志位检查 ───
|
|
125
|
+
async onComplete(ctx) {
|
|
126
|
+
if (/\[PROACTIVE:REPLY_CONFIRMED_(SENT|NONE)\]/.test(ctx.lastReplyText)) {
|
|
127
|
+
await ctx.updateSessionMeta({ lastProactiveFlag: true });
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
// ─── afterProcess:Unknown skill 兜底 ───
|
|
131
|
+
async afterProcess(ctx) {
|
|
132
|
+
if (!ctx.streamResult.hasReceivedText && /^Unknown skill:\s+\S+/i.test(ctx.fullText.trim())) {
|
|
133
|
+
// SDK 本地兜底:直接发送绕过 silent renderer
|
|
134
|
+
await ctx.send({ kind: 'result.text', text: ctx.fullText, isFinal: true });
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Mode System - Extension Capabilities
|
|
3
|
+
*
|
|
4
|
+
* 扩展能力接口:采用可选接口模式(方案 B)
|
|
5
|
+
* - 简单模式不需要实现用不到的方法
|
|
6
|
+
* - 通过类型守卫判断能力('methodName' in mode)
|
|
7
|
+
* - 接口职责单一,符合接口隔离原则
|
|
8
|
+
*/
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// 类型守卫工具
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* 检查模式是否支持辅助会话
|
|
14
|
+
*/
|
|
15
|
+
export function hasAuxiliarySession(mode) {
|
|
16
|
+
return typeof mode === 'object' && mode !== null && 'getAuxiliarySession' in mode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 检查模式是否支持线索跟踪
|
|
20
|
+
*/
|
|
21
|
+
export function hasThreadTracking(mode) {
|
|
22
|
+
return typeof mode === 'object' && mode !== null && 'getThreadManager' in mode;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 检查模式是否支持工作流
|
|
26
|
+
*/
|
|
27
|
+
export function hasWorkflow(mode) {
|
|
28
|
+
return typeof mode === 'object' && mode !== null && 'getWorkflowEngine' in mode;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 检查模式是否支持批量处理
|
|
32
|
+
*/
|
|
33
|
+
export function hasBatchProcessing(mode) {
|
|
34
|
+
return typeof mode === 'object' && mode !== null && 'processBatch' in mode;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 检查模式是否支持状态持久化
|
|
38
|
+
*/
|
|
39
|
+
export function hasStatePersistence(mode) {
|
|
40
|
+
return typeof mode === 'object' && mode !== null && 'saveState' in mode;
|
|
41
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SingleSessionMode } from './single-session/index.js';
|
|
2
|
+
export function registerBuiltinModes(registry) {
|
|
3
|
+
// single-session 为首选响应模式(responseMode 解析链的最终兜底)。
|
|
4
|
+
// 合并了原 interactive/proactive——投递方式由 chatMode 参数决定,不再是独立模式。
|
|
5
|
+
registry.registerBuiltin(new SingleSessionMode(), true);
|
|
6
|
+
}
|
|
7
|
+
export { SingleSessionMode } from './single-session/index.js';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { FIFOQueue } from '../../queues/fifo-queue.js';
|
|
2
|
+
import { flowForChatMode } from '../../engines/v1/index.js';
|
|
3
|
+
import { loadSchema } from '../../../config/schema-registry.js';
|
|
4
|
+
/**
|
|
5
|
+
* 模式桶 schema —— 候选值与默认值的**唯一事实源**,从 kits/schemas/single-session.schema.1.json
|
|
6
|
+
* 读取(随包分发、config schema 子命令可展示、write 时桶专项校验共用同一份)。
|
|
7
|
+
* `default` 即运行时出厂默认,由宿主组装 modeConfig 时提取注入(coordinator.schemaDefaults),
|
|
8
|
+
* flow 不再硬编码默认。chatMode 无 default——由宿主按 chatmode 场景表解析后强制注入。
|
|
9
|
+
*/
|
|
10
|
+
const CONFIG_SCHEMA = loadSchema('single-session').raw;
|
|
11
|
+
/**
|
|
12
|
+
* 单会话响应模式(architecture.md §4.1)—— 合并原 interactive / proactive。
|
|
13
|
+
*
|
|
14
|
+
* 本层是薄包装:不含处理行为,全部钩子委托 V1 引擎的 flow。chatMode 决定用哪个
|
|
15
|
+
* flow(interactive / proactive),取值来自 modeConfig.chatMode(宿主按配置层级
|
|
16
|
+
* 解析后注入,见 implementation-plan.md §三;无 auto 值)。
|
|
17
|
+
*/
|
|
18
|
+
export class SingleSessionMode {
|
|
19
|
+
id = 'single-session';
|
|
20
|
+
displayName = '单会话模式';
|
|
21
|
+
description = '单会话直接响应,按 chatMode 决定投递方式。';
|
|
22
|
+
type = 'builtin';
|
|
23
|
+
applicableScenes = ['private', 'group'];
|
|
24
|
+
configSchema = CONFIG_SCHEMA;
|
|
25
|
+
queue = new FIFOQueue();
|
|
26
|
+
context;
|
|
27
|
+
async initialize(context) {
|
|
28
|
+
this.context = context;
|
|
29
|
+
context.logger.debug('[ResponseSystem] single-session initialized chatMode=' + this.chatMode());
|
|
30
|
+
}
|
|
31
|
+
async cleanup() { await this.queue.clear(); }
|
|
32
|
+
/**
|
|
33
|
+
* 本会话生效的 chatmode——从 modeConfig 读取;缺省 interactive(宿主注入前的兜底)。
|
|
34
|
+
* 大小写不敏感:宿主注入的是小写 `chatmode`,但兼容历史/外部注入的 `chatMode`
|
|
35
|
+
* (二者语义同一,不应同时存在)。
|
|
36
|
+
*/
|
|
37
|
+
chatMode() {
|
|
38
|
+
const cfg = this.context?.modeConfig;
|
|
39
|
+
const value = cfg?.chatmode ?? cfg?.chatMode;
|
|
40
|
+
return value === 'proactive' ? 'proactive' : 'interactive';
|
|
41
|
+
}
|
|
42
|
+
flow() {
|
|
43
|
+
return flowForChatMode(this.chatMode());
|
|
44
|
+
}
|
|
45
|
+
async handleInbound(message) {
|
|
46
|
+
if (!this.context)
|
|
47
|
+
throw new Error('[single-session] not initialized');
|
|
48
|
+
return this.flow().handleInbound(message, this.context);
|
|
49
|
+
}
|
|
50
|
+
async handleOutbound(payload) {
|
|
51
|
+
if (!this.context)
|
|
52
|
+
throw new Error('[single-session] not initialized');
|
|
53
|
+
return this.flow().handleOutbound(payload, this.context);
|
|
54
|
+
}
|
|
55
|
+
getQueue() { return this.queue; }
|
|
56
|
+
// ─── 处理流程钩子:存在才委托(proactive flow 提供全套,interactive 仅 afterProcess)───
|
|
57
|
+
beforeProcess(ctx) {
|
|
58
|
+
return this.flow().beforeProcess?.(ctx);
|
|
59
|
+
}
|
|
60
|
+
configureRun(ctx) {
|
|
61
|
+
return this.flow().configureRun?.(ctx);
|
|
62
|
+
}
|
|
63
|
+
onToolUse(ctx) {
|
|
64
|
+
return this.flow().onToolUse?.(ctx);
|
|
65
|
+
}
|
|
66
|
+
onComplete(ctx) {
|
|
67
|
+
return this.flow().onComplete?.(ctx);
|
|
68
|
+
}
|
|
69
|
+
afterProcess(ctx) {
|
|
70
|
+
return this.flow().afterProcess?.(ctx);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FIFO Queue - First In First Out
|
|
3
|
+
*
|
|
4
|
+
* 最简单的队列实现,按入队顺序出队
|
|
5
|
+
*/
|
|
6
|
+
export class FIFOQueue {
|
|
7
|
+
queue = [];
|
|
8
|
+
async enqueue(message, priority) {
|
|
9
|
+
this.queue.push(message);
|
|
10
|
+
}
|
|
11
|
+
async dequeue() {
|
|
12
|
+
return this.queue.shift();
|
|
13
|
+
}
|
|
14
|
+
dequeueSync() {
|
|
15
|
+
return this.queue.shift();
|
|
16
|
+
}
|
|
17
|
+
async peek() {
|
|
18
|
+
return this.queue[0];
|
|
19
|
+
}
|
|
20
|
+
peekSync() {
|
|
21
|
+
return this.queue[0];
|
|
22
|
+
}
|
|
23
|
+
size() {
|
|
24
|
+
return this.queue.length;
|
|
25
|
+
}
|
|
26
|
+
async clear() {
|
|
27
|
+
this.queue = [];
|
|
28
|
+
}
|
|
29
|
+
async reorder(strategy) {
|
|
30
|
+
if (strategy === 'fifo') {
|
|
31
|
+
// Already FIFO, no-op
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
else if (strategy === 'lifo') {
|
|
35
|
+
// Reverse the queue
|
|
36
|
+
this.queue.reverse();
|
|
37
|
+
}
|
|
38
|
+
else if (strategy === 'priority') {
|
|
39
|
+
// Sort by messageId (simple priority: earlier messageId = higher priority)
|
|
40
|
+
// TODO: 实际应该根据 priority 字段排序,但当前 InboundMessage 没有该字段
|
|
41
|
+
// 这里先按入队顺序保持不变(等价于 FIFO)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LIFO Queue - Last In First Out (Stack)
|
|
3
|
+
*
|
|
4
|
+
* 后入先出,最新的消息优先处理
|
|
5
|
+
*/
|
|
6
|
+
export class LIFOQueue {
|
|
7
|
+
queue = [];
|
|
8
|
+
async enqueue(message, priority) {
|
|
9
|
+
this.queue.push(message);
|
|
10
|
+
}
|
|
11
|
+
async dequeue() {
|
|
12
|
+
return this.queue.pop(); // ← 从队尾取,实现后进先出
|
|
13
|
+
}
|
|
14
|
+
dequeueSync() {
|
|
15
|
+
return this.queue.pop();
|
|
16
|
+
}
|
|
17
|
+
async peek() {
|
|
18
|
+
return this.queue[this.queue.length - 1];
|
|
19
|
+
}
|
|
20
|
+
peekSync() {
|
|
21
|
+
return this.queue[this.queue.length - 1];
|
|
22
|
+
}
|
|
23
|
+
size() {
|
|
24
|
+
return this.queue.length;
|
|
25
|
+
}
|
|
26
|
+
async clear() {
|
|
27
|
+
this.queue = [];
|
|
28
|
+
}
|
|
29
|
+
async reorder(strategy) {
|
|
30
|
+
if (strategy === 'lifo') {
|
|
31
|
+
// Already LIFO, no-op
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
else if (strategy === 'fifo') {
|
|
35
|
+
// Reverse to FIFO order
|
|
36
|
+
this.queue.reverse();
|
|
37
|
+
}
|
|
38
|
+
else if (strategy === 'priority') {
|
|
39
|
+
// Keep current order (no priority info)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority Queue - Priority-based ordering
|
|
3
|
+
*
|
|
4
|
+
* 按优先级排序,高优先级优先处理
|
|
5
|
+
*/
|
|
6
|
+
export class PriorityQueue {
|
|
7
|
+
queue = [];
|
|
8
|
+
insertCounter = 0;
|
|
9
|
+
async enqueue(message, priority = 0) {
|
|
10
|
+
const item = {
|
|
11
|
+
message,
|
|
12
|
+
priority,
|
|
13
|
+
insertOrder: this.insertCounter++,
|
|
14
|
+
};
|
|
15
|
+
// 插入排序:按优先级降序,同优先级按插入顺序升序
|
|
16
|
+
let insertIndex = this.queue.length;
|
|
17
|
+
for (let i = 0; i < this.queue.length; i++) {
|
|
18
|
+
if (this.queue[i].priority < priority ||
|
|
19
|
+
(this.queue[i].priority === priority && this.queue[i].insertOrder > item.insertOrder)) {
|
|
20
|
+
insertIndex = i;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
this.queue.splice(insertIndex, 0, item);
|
|
25
|
+
}
|
|
26
|
+
async dequeue() {
|
|
27
|
+
const item = this.queue.shift();
|
|
28
|
+
return item?.message;
|
|
29
|
+
}
|
|
30
|
+
dequeueSync() {
|
|
31
|
+
const item = this.queue.shift();
|
|
32
|
+
return item?.message;
|
|
33
|
+
}
|
|
34
|
+
async peek() {
|
|
35
|
+
return this.queue[0]?.message;
|
|
36
|
+
}
|
|
37
|
+
peekSync() {
|
|
38
|
+
return this.queue[0]?.message;
|
|
39
|
+
}
|
|
40
|
+
size() {
|
|
41
|
+
return this.queue.length;
|
|
42
|
+
}
|
|
43
|
+
async clear() {
|
|
44
|
+
this.queue = [];
|
|
45
|
+
this.insertCounter = 0;
|
|
46
|
+
}
|
|
47
|
+
async reorder(strategy) {
|
|
48
|
+
if (strategy === 'priority') {
|
|
49
|
+
// Already priority-sorted, no-op
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Extract messages
|
|
53
|
+
const messages = this.queue.map(item => item.message);
|
|
54
|
+
if (strategy === 'fifo') {
|
|
55
|
+
// Sort by insert order (ascending)
|
|
56
|
+
this.queue.sort((a, b) => a.insertOrder - b.insertOrder);
|
|
57
|
+
}
|
|
58
|
+
else if (strategy === 'lifo') {
|
|
59
|
+
// Sort by insert order (descending)
|
|
60
|
+
this.queue.sort((a, b) => b.insertOrder - a.insertOrder);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Mode Registry
|
|
3
|
+
*
|
|
4
|
+
* 响应模式注册表:管理所有已注册的响应模式(内置 + 扩展)。
|
|
5
|
+
*
|
|
6
|
+
* 设计:
|
|
7
|
+
* - 内置模式(builtin):随包发布,在启动时注册
|
|
8
|
+
* - 扩展模式(extension):用户自定义,运行时注册
|
|
9
|
+
* - 扩展不可覆盖内置(id 冲突时拒绝)
|
|
10
|
+
*/
|
|
11
|
+
export class ResponseModeRegistry {
|
|
12
|
+
modes = new Map();
|
|
13
|
+
/** 首选响应模式 id:当关系级/agent 级均未配 responseMode 时的兜底。 */
|
|
14
|
+
preferredId;
|
|
15
|
+
/**
|
|
16
|
+
* 注册内置模式(type 必须为 'builtin')
|
|
17
|
+
* @param preferred 标记为首选响应模式(注册表默认);仅允许一个,重复设置以最后一次为准
|
|
18
|
+
*/
|
|
19
|
+
registerBuiltin(mode, preferred = false) {
|
|
20
|
+
if (mode.type !== 'builtin') {
|
|
21
|
+
throw new Error(`[Registry] registerBuiltin requires type='builtin', got '${mode.type}' for mode '${mode.id}'`);
|
|
22
|
+
}
|
|
23
|
+
if (this.modes.has(mode.id)) {
|
|
24
|
+
throw new Error(`[Registry] mode id '${mode.id}' already registered`);
|
|
25
|
+
}
|
|
26
|
+
this.modes.set(mode.id, mode);
|
|
27
|
+
if (preferred)
|
|
28
|
+
this.preferredId = mode.id;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 首选响应模式(responseMode 解析链的最终兜底:关系级 > agent 级 > 此项)。
|
|
32
|
+
* @throws 若从未标记首选模式(启动注册应保证存在)
|
|
33
|
+
*/
|
|
34
|
+
getPreferred() {
|
|
35
|
+
if (!this.preferredId) {
|
|
36
|
+
throw new Error('[Registry] no preferred response mode registered — a builtin must be registered with preferred=true at startup');
|
|
37
|
+
}
|
|
38
|
+
const mode = this.modes.get(this.preferredId);
|
|
39
|
+
if (!mode) {
|
|
40
|
+
throw new Error(`[Registry] preferred mode '${this.preferredId}' not found in registry`);
|
|
41
|
+
}
|
|
42
|
+
return mode;
|
|
43
|
+
}
|
|
44
|
+
/** 首选响应模式 id(未设置返回 undefined)。 */
|
|
45
|
+
getPreferredId() {
|
|
46
|
+
return this.preferredId;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 注册扩展模式(type 必须为 'extension',不可覆盖内置)
|
|
50
|
+
*/
|
|
51
|
+
registerExtension(mode) {
|
|
52
|
+
if (mode.type !== 'extension') {
|
|
53
|
+
throw new Error(`[Registry] registerExtension requires type='extension', got '${mode.type}' for mode '${mode.id}'`);
|
|
54
|
+
}
|
|
55
|
+
const existing = this.modes.get(mode.id);
|
|
56
|
+
if (existing) {
|
|
57
|
+
if (existing.type === 'builtin') {
|
|
58
|
+
throw new Error(`[Registry] extension '${mode.id}' cannot override builtin mode`);
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`[Registry] extension id '${mode.id}' already registered`);
|
|
61
|
+
}
|
|
62
|
+
this.modes.set(mode.id, mode);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 注销扩展模式(内置模式不可注销)
|
|
66
|
+
*/
|
|
67
|
+
unregister(id) {
|
|
68
|
+
const mode = this.modes.get(id);
|
|
69
|
+
if (!mode)
|
|
70
|
+
return;
|
|
71
|
+
if (mode.type === 'builtin') {
|
|
72
|
+
throw new Error(`[Registry] cannot unregister builtin mode '${id}'`);
|
|
73
|
+
}
|
|
74
|
+
this.modes.delete(id);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 获取指定模式(不存在返回 undefined)
|
|
78
|
+
*/
|
|
79
|
+
get(id) {
|
|
80
|
+
return this.modes.get(id);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 列出所有模式(可选按场景过滤)
|
|
84
|
+
*/
|
|
85
|
+
list(scene) {
|
|
86
|
+
const all = Array.from(this.modes.values());
|
|
87
|
+
if (!scene)
|
|
88
|
+
return all;
|
|
89
|
+
return all.filter(m => m.applicableScenes.includes(scene));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 是否存在指定模式
|
|
93
|
+
*/
|
|
94
|
+
has(id) {
|
|
95
|
+
return this.modes.has(id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Mode Resolver
|
|
3
|
+
*
|
|
4
|
+
* 模式解析:决定某个会话该用哪个响应模式。
|
|
5
|
+
*
|
|
6
|
+
* responseMode 是**标量**参数,走特殊路线(不同于 chatmode/mentionMode/model 的普通配置链):
|
|
7
|
+
* 候选清单与默认值来自**注册表**,不来自 schema。解析优先级(高→低):
|
|
8
|
+
* 1. 关系级 responseMode($RELATIONS_DIR/<peerKey>/config.json)
|
|
9
|
+
* 2. agent 级 responseMode($AGENT_DIR/config.json)
|
|
10
|
+
* 3. 注册表首选响应模式(registry.getPreferred(),当前为 single-session)
|
|
11
|
+
*
|
|
12
|
+
* 关系级 > agent 级由 ConfigManager 按 `x-merge: scalar` 合并完成,因此本解析器
|
|
13
|
+
* 收到的是**合并后的标量值**;只需「有值用值、无值用注册表首选」。
|
|
14
|
+
*
|
|
15
|
+
* 注:旧的 response_modes 块(default_private/default_group/configs/overrides)已废除。
|
|
16
|
+
* chatMode 从顶层 chatmode 字典读、与选模式正交;模式特有参数从顶层 config 块读。
|
|
17
|
+
*/
|
|
18
|
+
export class ResponseModeResolver {
|
|
19
|
+
registry;
|
|
20
|
+
constructor(registry) {
|
|
21
|
+
this.registry = registry;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 解析会话的响应模式。
|
|
25
|
+
*
|
|
26
|
+
* @param responseModeId 合并后的标量 responseMode(关系级>agent级,可空)
|
|
27
|
+
*/
|
|
28
|
+
resolve(responseModeId) {
|
|
29
|
+
if (responseModeId) {
|
|
30
|
+
const mode = this.registry.get(responseModeId);
|
|
31
|
+
if (mode)
|
|
32
|
+
return { mode, source: 'config' };
|
|
33
|
+
// 配了不存在的模式:不抛错(避免单个坏配置卡死会话),回落注册表首选
|
|
34
|
+
}
|
|
35
|
+
return { mode: this.registry.getPreferred(), source: 'preferred' };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New response-system selector. It is intentionally small while V1 migration is
|
|
3
|
+
* in progress; V2 modes can be added without changing user-facing mode ids.
|
|
4
|
+
*/
|
|
5
|
+
export class ResponseModeSelector {
|
|
6
|
+
registry;
|
|
7
|
+
constructor(registry) {
|
|
8
|
+
this.registry = registry;
|
|
9
|
+
}
|
|
10
|
+
async select(modeId, context) {
|
|
11
|
+
const mode = this.registry.get(modeId);
|
|
12
|
+
if (!mode) {
|
|
13
|
+
throw new Error(`[ResponseModeSelector] mode not found: ${modeId}`);
|
|
14
|
+
}
|
|
15
|
+
await mode.initialize(context);
|
|
16
|
+
context.logger.debug('[ResponseSystem] selector selected mode=' + mode.id + ' engine=' + (mode.engineType ?? 'v1'));
|
|
17
|
+
return {
|
|
18
|
+
id: mode.id,
|
|
19
|
+
engineType: mode.engineType ?? 'v1',
|
|
20
|
+
mode,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|