evolcore 0.0.28 → 0.0.29
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 +12 -0
- package/bin/ec-safe-output.js +270 -54
- package/dist/agents/baseagent-availability.js +37 -1
- package/dist/agents/baseagent.js +19 -9
- package/dist/agents/claude-runner.js +171 -13
- package/dist/agents/codex/app-server-client.js +6 -2
- package/dist/agents/codex/diagnostics.js +4 -3
- package/dist/agents/codex-runner.js +396 -95
- package/dist/agents/gemini-runner.js +35 -17
- package/dist/aun/group/history.js +130 -90
- package/dist/aun/group/operations.js +1 -3
- package/dist/aun/menu/transport.js +5 -3
- package/dist/aun/msg/managed-operation.js +70 -0
- package/dist/aun/msg/p2p.js +1 -3
- package/dist/aun/msg/upload.js +2 -2
- package/dist/aun/outbox.js +1 -37
- package/dist/channels/aun.js +249 -89
- package/dist/channels/daemon.js +18 -1
- package/dist/channels/feishu.js +1 -2
- package/dist/cli/agent-command.js +23 -3
- package/dist/cli/agent-create.js +68 -2
- package/dist/cli/agent.js +12 -2
- package/dist/cli/aun-commands.js +87 -13
- package/dist/cli/cli-argv.js +26 -0
- package/dist/cli/daemon-commands.js +40 -10
- package/dist/cli/data-command.js +4 -4
- package/dist/cli/handoff-command.js +2 -0
- package/dist/cli/index.js +18 -1
- package/dist/cli/managed-command-guard.js +10 -0
- package/dist/cli/memory-command.js +441 -0
- package/dist/cli/restart-monitor.js +62 -6
- package/dist/cli/skill-command.js +41 -0
- package/dist/cli/task-context.js +2 -23
- package/dist/cli/trigger-command.js +9 -1
- package/dist/cli/watch-msg-diag.js +209 -0
- package/dist/config/config-field-policy.js +52 -3
- package/dist/config/config-manager.js +17 -4
- package/dist/config/contact-book-store.js +2 -2
- package/dist/config/mention-mode.js +7 -2
- package/dist/config/merge.js +28 -9
- package/dist/config/resolved-config-op.js +1 -1
- package/dist/config/runtime-env.js +137 -0
- package/dist/config/schema-registry.js +11 -1
- package/dist/config-store.js +10 -10
- package/dist/core/audit/event-key.js +3 -1
- package/dist/core/audit/log-integrity.js +4 -0
- package/dist/core/auth/agent-delegation.js +2 -1
- package/dist/core/auth/auth-gateway.js +13 -6
- package/dist/core/auth/authorization-audit.js +54 -19
- package/dist/core/auth/operation-authorizer.js +17 -0
- package/dist/core/auth/operation-catalog.js +9 -0
- package/dist/core/causation/context.js +5 -1
- package/dist/core/command/agent-control.js +1 -2
- package/dist/core/command/command-handler.js +51 -23
- package/dist/core/command/memory-slash.js +270 -0
- package/dist/core/command/menu-catalog.js +1 -0
- package/dist/core/command/menu-handler.js +315 -60
- package/dist/core/command/menu-protocol.js +42 -4
- package/dist/core/command/slash-gate.js +10 -10
- package/dist/core/command/slash-handler.js +206 -64
- package/dist/core/data-migration.js +282 -505
- package/dist/core/event-catalog.js +26 -0
- package/dist/core/evolagent-registry.js +6 -0
- package/dist/core/evolagent.js +0 -10
- package/dist/core/handoff/store.js +1 -20
- package/dist/core/inference/text-inference.js +57 -1
- package/dist/core/memory/consolidation-context.js +505 -0
- package/dist/core/memory/consolidation-ops-records.js +124 -0
- package/dist/core/memory/consolidation-trigger.js +394 -0
- package/dist/core/memory/index-manager.js +308 -0
- package/dist/core/memory/launch-consolidation.js +395 -0
- package/dist/core/memory/memory-admin.js +234 -0
- package/dist/core/memory/memory-document.js +100 -0
- package/dist/core/memory/memory-session-policy.js +41 -0
- package/dist/core/memory/memory-signature.js +257 -0
- package/dist/core/memory/memory-writer.js +432 -0
- package/dist/core/memory/staleness.js +117 -0
- package/dist/core/message/auto-mention-gate.js +454 -0
- package/dist/core/message/im-renderer.js +69 -16
- package/dist/core/message/message-bridge.js +287 -21
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +114 -27
- package/dist/core/message/pending-hints.js +329 -161
- package/dist/core/message/response-engine.js +567 -80
- package/dist/core/permission/ec-command-parser.js +1029 -80
- package/dist/core/permission/protected-paths.js +376 -126
- package/dist/core/permission/sandbox-runtime.js +40 -12
- package/dist/core/permission/tool-error-code.js +96 -13
- package/dist/core/permission/tool-policy.js +276 -23
- package/dist/core/role/runtime-policy.js +3 -7
- package/dist/core/session/{runner-task-history.js → runner-event-summary.js} +1 -1
- package/dist/core/session/session-fs-store.js +0 -76
- package/dist/core/session/session-idle-monitor.js +355 -0
- package/dist/core/session/session-manager.js +478 -17
- package/dist/core/session/session-mapper.js +33 -16
- package/dist/core/session/session-renew.js +217 -155
- package/dist/core/session/{session-turns.js → session-transcript.js} +35 -6
- package/dist/core/skill/global-watcher.js +282 -0
- package/dist/core/skill/index-generator.js +84 -0
- package/dist/core/skill/startup.js +73 -0
- package/dist/core/skill/switch-resolver.js +115 -0
- package/dist/core/task/task-activity-store.js +219 -0
- package/dist/eck/kit-renderer.js +30 -3
- package/dist/eck/manifest-engine.js +26 -4
- package/dist/index.js +708 -18
- package/dist/ipc.js +564 -2
- package/dist/paths.js +30 -9
- package/dist/response-system/engines/v1/proactive-flow.js +116 -15
- package/dist/response-system/modes/single-session/index.js +3 -0
- package/dist/trigger/feedback.js +1 -0
- package/dist/trigger/manager.js +0 -10
- package/dist/trigger/scheduler.js +11 -0
- package/dist/trigger/validation.js +22 -0
- package/dist/utils/avatar-upload.js +59 -18
- package/dist/utils/error-dict.json +6 -3
- package/dist/utils/error-utils.js +27 -0
- package/dist/utils/logger.js +32 -10
- package/dist/utils/media-cache.js +84 -0
- package/dist/utils/msg-diag.js +97 -0
- package/dist/utils/welcome.js +37 -8
- package/kits/docs/AUTHORING.md +314 -0
- package/kits/docs/GUIDE.md +2 -0
- package/kits/docs/INDEX.md +2 -0
- package/kits/docs/aun/CHEATSHEET.md +4 -0
- package/kits/docs/aun/SDK.md +60 -0
- package/kits/docs/context-assembly.md +10 -6
- package/kits/docs/evolcore/INDEX.md +17 -3
- package/kits/docs/evolcore/agent-create.md +24 -0
- package/kits/docs/evolcore/agent.md +5 -2
- package/kits/docs/evolcore/config.md +1 -1
- package/kits/docs/evolcore/ec-capabilities.md +364 -0
- package/kits/docs/evolcore/group.md +34 -18
- package/kits/docs/evolcore/memory-architecture.md +78 -0
- package/kits/docs/evolcore/memory-consolidation-batches.md +133 -0
- package/kits/docs/evolcore/memory-consolidation.md +263 -0
- package/kits/docs/evolcore/memory-tags.md +63 -0
- package/kits/docs/evolcore/memory.md +110 -0
- package/kits/docs/evolcore/menu-client.md +27 -11
- package/kits/{schemas → docs/evolcore}/menu-exec-schema-commands.md +12 -6
- package/kits/docs/evolcore/menu-protocol.md +213 -0
- package/kits/docs/evolcore/msg.md +2 -0
- package/kits/docs/evolcore/trigger.md +7 -5
- package/kits/docs/path-registry.md +6 -8
- package/kits/docs/prompt-loading-architecture.md +5 -3
- package/kits/docs/venues/group.md +5 -4
- package/kits/eck_manifest.json +294 -88
- package/kits/eck_manifest.memory.json +257 -0
- package/kits/rules/03-identity.md +8 -8
- package/kits/rules/05-venue.md +4 -2
- package/kits/rules/06-channel.md +1 -1
- package/kits/schemas/_meta.json +276 -47
- package/kits/schemas/agent-config.schema.12.json +38 -2
- package/kits/schemas/agent-config.schema.13.json +591 -0
- package/kits/schemas/daemon.schema.6.json +9 -9
- package/kits/schemas/defaults.schema.5.json +29 -0
- package/kits/schemas/relation-config.schema.8.json +14 -1
- package/kits/schemas/relation-config.schema.9.json +129 -0
- package/kits/schemas/role-config.schema.1.json +3 -3
- package/kits/skills/.switches.json +3 -0
- package/kits/skills/ec-skill/SKILL.md +217 -0
- package/kits/skills/ec-skill/scripts/cli.mjs +128 -0
- package/kits/skills/ec-skill/scripts/deps.mjs +107 -0
- package/kits/skills/ec-skill/scripts/frontmatter.mjs +104 -0
- package/kits/skills/ec-skill/scripts/skill.mjs +629 -0
- package/kits/skills/ec-skill/scripts/template/SKILL.md.tmpl +30 -0
- package/kits/templates/decision/auto-mention.md +25 -0
- package/kits/templates/decision/session-renew.md +22 -0
- package/kits/templates/memory-consolidation/forget.md +104 -0
- package/kits/templates/memory-consolidation/generalize.md +76 -0
- package/kits/templates/memory-consolidation/notes.md +133 -0
- package/kits/templates/memory-consolidation/profile.md +58 -0
- package/kits/templates/memory-consolidation/promote.md +72 -0
- package/kits/templates/memory-consolidation/workflow.md +75 -0
- package/kits/templates/system-fragments/bootstrap.md +14 -5
- package/kits/templates/system-fragments/commands.md +1 -0
- package/kits/templates/system-fragments/group-history.md +6 -0
- package/kits/templates/system-fragments/identity.md +0 -3
- package/kits/templates/system-fragments/memory.md +79 -0
- package/kits/templates/system-fragments/reply.md +1 -0
- package/kits/templates/system-fragments/venue.md +1 -1
- package/package.json +4 -6
- package/dist/trigger/legacy-session-history.js +0 -19
- package/kits/templates/system-fragments/group-unread-history.md +0 -7
|
@@ -12,6 +12,7 @@ import { loadDaemonConfig } from '../../config-store.js';
|
|
|
12
12
|
import { remoteAccessService } from '../auth/remote-access-store.js';
|
|
13
13
|
import { read as cfgRead, resolveEffective, routeFieldPath, write as cfgWrite, } from '../../config/config-manager.js';
|
|
14
14
|
import { execAgentAction } from './agent-control.js';
|
|
15
|
+
import { handleMemorySlash, memoryHelpEntries } from './memory-slash.js';
|
|
15
16
|
import { authorizeOperation, buildAuthSubject } from '../auth/auth-gateway.js';
|
|
16
17
|
import { authorizationNextStep, formatAuthorizationDenial } from '../auth/authorization-denial.js';
|
|
17
18
|
import { resolvePermissionMode, writeScope } from '../model/config-scope.js';
|
|
@@ -29,6 +30,7 @@ import { launchMonitorAndConfirm, resolveMonitorLaunch, cleanupMonitorStage } fr
|
|
|
29
30
|
import { scanInstances } from '../../utils/instance-registry.js';
|
|
30
31
|
import { inspectDataMigrationRequirement } from '../data-migration.js';
|
|
31
32
|
import { guardIdleCommand, guardGroupSlashCommand, guardKnownCommand, guardRoleCommand, guardThreadCommand, isRecognizedSlashCommand, normalizeSlashContent, probeSessionActivity, } from './slash-gate.js';
|
|
33
|
+
import { MAX_AUN_ATTACHMENT_SIZE } from '../../aun/msg/upload.js';
|
|
32
34
|
const allEfforts = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
33
35
|
const PERMISSION_MODE_KEYS = PUBLIC_PERMISSION_MODES;
|
|
34
36
|
function defaultSlashChatmode(field) {
|
|
@@ -88,19 +90,33 @@ function resolveSlashMentionModeTarget(params) {
|
|
|
88
90
|
?? this.resolveSelfAID?.(params.channel);
|
|
89
91
|
if (!self)
|
|
90
92
|
return { error: '找不到当前 agent,无法读写 mentionMode', code: 'MISSING_AID' };
|
|
91
|
-
|
|
93
|
+
const actualChatType = params.session?.chatType || params.chatType;
|
|
94
|
+
if (actualChatType !== 'group') {
|
|
95
|
+
return { sel: { self }, fieldPath: 'mentionMode', scope: 'agent' };
|
|
96
|
+
}
|
|
97
|
+
const groupId = params.session?.metadata?.groupId || params.channelId;
|
|
98
|
+
if (!groupId)
|
|
99
|
+
return { error: '找不到当前群,无法读写 relation mentionMode', code: 'MISSING_PEER' };
|
|
100
|
+
const channelType = params.session?.channelType
|
|
101
|
+
|| this.resolveChannelType?.(params.channel)
|
|
102
|
+
|| params.channel.split('#')[0];
|
|
103
|
+
return {
|
|
104
|
+
sel: { self, peerKey: formatPeerKey(channelType, groupId) },
|
|
105
|
+
fieldPath: 'mentionMode',
|
|
106
|
+
scope: 'relation',
|
|
107
|
+
};
|
|
92
108
|
}
|
|
93
109
|
function readSlashMentionMode(target, fallback = null) {
|
|
94
110
|
try {
|
|
95
111
|
const mode = resolveEffective(target.sel, { cache: true }).mentionMode;
|
|
96
|
-
return mode === 'disabled' || mode === 'mention-only' ? mode : fallback;
|
|
112
|
+
return mode === 'disabled' || mode === 'mention-only' || mode === 'auto' ? mode : fallback;
|
|
97
113
|
}
|
|
98
114
|
catch {
|
|
99
115
|
return fallback;
|
|
100
116
|
}
|
|
101
117
|
}
|
|
102
118
|
function writeSlashMentionMode(target, value) {
|
|
103
|
-
const route = routeFieldPath(target.fieldPath,
|
|
119
|
+
const route = routeFieldPath(target.fieldPath, target.scope);
|
|
104
120
|
const cur = cfgRead(route.target, target.sel) || {};
|
|
105
121
|
if (value === null)
|
|
106
122
|
delete cur.mentionMode;
|
|
@@ -637,7 +653,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
637
653
|
' /effort - 查看推理强度',
|
|
638
654
|
' /baseagent - 查看 Agent 后端',
|
|
639
655
|
' /perm - 查看权限模式',
|
|
640
|
-
' /
|
|
656
|
+
' /mention - 查看群聊 @ 处理模式',
|
|
641
657
|
' /ask <选项> - 回答待处理问题',
|
|
642
658
|
' /pause - 在下一次工具调用前暂停任务',
|
|
643
659
|
' /resume - 继续已暂停的任务',
|
|
@@ -647,7 +663,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
647
663
|
...(threadId ? [' /renew - 轮换当前话题的后端会话'] : []),
|
|
648
664
|
] : []),
|
|
649
665
|
'',
|
|
650
|
-
'
|
|
666
|
+
'模型、推理强度、后端与权限在群聊中仅支持查询;@ 模式可由管理员切换。',
|
|
651
667
|
];
|
|
652
668
|
return { kind: 'command.result', text: lines.join('\n') };
|
|
653
669
|
}
|
|
@@ -659,10 +675,8 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
659
675
|
const canAnswerPermission = canAccessSlashOperation('permission.answer', 'relation');
|
|
660
676
|
const canReadChatmode = canAccessSlashOperation('chatmode.current', 'relation');
|
|
661
677
|
const canSetChatmode = canAccessSlashOperation('chatmode.update', 'relation');
|
|
662
|
-
const canReadMentionmode =
|
|
663
|
-
|
|
664
|
-
const canSetMentionmode = activeChatType === 'group'
|
|
665
|
-
&& canAccessSlashOperation('mentionmode.update', 'relation');
|
|
678
|
+
const canReadMentionmode = canAccessSlashOperation('mentionmode.current', 'relation');
|
|
679
|
+
const canSetMentionmode = canAccessSlashOperation('mentionmode.update', 'relation');
|
|
666
680
|
const canUseFile = canAccessSlashOperation('file.fetch', 'filesystem');
|
|
667
681
|
const appendProcessCommands = (lines) => {
|
|
668
682
|
if (!isDaemonOwner)
|
|
@@ -682,7 +696,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
682
696
|
'',
|
|
683
697
|
'💬 聊天设置:',
|
|
684
698
|
...(canReadChatmode || canSetChatmode ? [` /chatmode${canSetChatmode ? ' [interactive|proactive]' : ''} - 查看${canSetChatmode ? '或切换' : ''}会话模式`] : []),
|
|
685
|
-
...(canReadMentionmode || canSetMentionmode ? [` /
|
|
699
|
+
...(canReadMentionmode || canSetMentionmode ? [` /mention${canSetMentionmode ? ' [mention-only|disabled]' : ''} - 查看${canSetMentionmode ? '或切换' : ''}群聊 @ 处理模式`] : []),
|
|
686
700
|
] : []),
|
|
687
701
|
...(canReadPermission || canAnswerPermission ? [
|
|
688
702
|
'',
|
|
@@ -772,7 +786,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
772
786
|
'💬 聊天设置:',
|
|
773
787
|
' /activity [all|text|none] - 查看/控制中间输出显示模式',
|
|
774
788
|
...(canReadChatmode || canSetChatmode ? [` /chatmode${canSetChatmode ? ' [interactive|proactive]' : ''} - 查看${canSetChatmode ? '/切换' : ''}会话模式(被动响应或主动推进)`] : []),
|
|
775
|
-
...(canReadMentionmode || canSetMentionmode ? [` /
|
|
789
|
+
...(canReadMentionmode || canSetMentionmode ? [` /mention${canSetMentionmode ? ' [mention-only|disabled]' : ''} - 查看${canSetMentionmode ? '/切换' : ''}群聊 @ 处理模式`] : []),
|
|
776
790
|
'',
|
|
777
791
|
'🔐 权限管理:',
|
|
778
792
|
...(canReadPermission ? [' /perm - 查看当前权限模式'] : []),
|
|
@@ -792,6 +806,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
792
806
|
' /restart - 重启服务',
|
|
793
807
|
' /reload [aid] - 热重载 Agent 配置',
|
|
794
808
|
' /fa <提示词> - 单次使用宿主级 fullaccess 执行(别名: /fullaccess)',
|
|
809
|
+
' /pair - 获取远程控制配对码',
|
|
795
810
|
] : []),
|
|
796
811
|
...(!isDaemonOwner && isAdmin ? [
|
|
797
812
|
' /reload - 热重载当前 Agent 配置',
|
|
@@ -835,6 +850,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
835
850
|
// /evolhelp 命令:返回 JSON 格式的命令列表(供程序解析)
|
|
836
851
|
if (normalizedContent === '/evolhelp') {
|
|
837
852
|
if (groupSlash) {
|
|
853
|
+
const canSetMentionmode = canAccessSlashOperation('mentionmode.update', 'relation');
|
|
838
854
|
const commands = [
|
|
839
855
|
{ command: '/help', description: '显示帮助信息', category: '帮助', roles: ['visitor', 'member', 'admin', 'owner'] },
|
|
840
856
|
{ command: '/status', description: '显示会话状态', category: '运维', roles: ['visitor', 'member', 'admin', 'owner'] },
|
|
@@ -843,7 +859,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
843
859
|
{ command: '/effort', description: '查看推理强度', category: 'Agent 与模型', roles: [identity.role] },
|
|
844
860
|
{ command: '/baseagent', description: '查看 Agent 后端', category: 'Agent 与模型', roles: [identity.role] },
|
|
845
861
|
{ command: '/perm', description: '查看当前权限模式', category: '权限管理', roles: [identity.role] },
|
|
846
|
-
{ command: '/
|
|
862
|
+
{ command: '/mention', args: canSetMentionmode ? '[mention-only|disabled|auto|clear]' : undefined, description: canSetMentionmode ? '查看或切换群聊 @ 处理模式' : '查看群聊 @ 处理模式', category: '聊天设置', roles: [identity.role] },
|
|
847
863
|
{ command: '/ask', args: '<选项>', description: '回答 Agent 的交互式问题', category: '运维', roles: ['visitor', 'member', 'admin', 'owner'] },
|
|
848
864
|
{ command: '/pause', description: '在下一次工具调用前暂停当前任务', category: '运维', roles: ['admin', 'owner'] },
|
|
849
865
|
{ command: '/resume', description: '继续已暂停的当前任务', category: '运维', roles: ['admin', 'owner'] },
|
|
@@ -852,6 +868,10 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
852
868
|
if (isAdmin) {
|
|
853
869
|
commands.push({ command: '/compact', description: '压缩会话上下文', category: '会话管理', roles: ['admin', 'owner'] }, ...(threadId ? [{ command: '/renew', description: '轮换当前话题 backend', category: '会话管理', roles: ['admin', 'owner'] }] : []));
|
|
854
870
|
}
|
|
871
|
+
// 记忆管理紧跟权限管理
|
|
872
|
+
const groupMemoryEntries = memoryHelpEntries({ chatType: 'group', role: identity.role, isAdmin, isOwnerSelf: false });
|
|
873
|
+
const lastPermIdx = commands.map(c => c.category).lastIndexOf('权限管理');
|
|
874
|
+
commands.splice(lastPermIdx >= 0 ? lastPermIdx + 1 : commands.length, 0, ...groupMemoryEntries);
|
|
855
875
|
return { kind: 'command.result', text: JSON.stringify({ commands, categories: [...new Set(commands.map(c => c.category))] }) };
|
|
856
876
|
}
|
|
857
877
|
const cmds = [];
|
|
@@ -863,10 +883,8 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
863
883
|
const canAnswerPermission = canAccessSlashOperation('permission.answer', 'relation');
|
|
864
884
|
const canReadChatmode = canAccessSlashOperation('chatmode.current', 'relation');
|
|
865
885
|
const canSetChatmode = canAccessSlashOperation('chatmode.update', 'relation');
|
|
866
|
-
const canReadMentionmode =
|
|
867
|
-
|
|
868
|
-
const canSetMentionmode = activeChatType === 'group'
|
|
869
|
-
&& canAccessSlashOperation('mentionmode.update', 'relation');
|
|
886
|
+
const canReadMentionmode = canAccessSlashOperation('mentionmode.current', 'relation');
|
|
887
|
+
const canSetMentionmode = canAccessSlashOperation('mentionmode.update', 'relation');
|
|
870
888
|
const canUseFile = canAccessSlashOperation('file.fetch', 'filesystem');
|
|
871
889
|
// 项目
|
|
872
890
|
cmds.push({ command: '/pwd', description: '显示当前项目路径', category: '项目', roles: ['admin', 'owner'] });
|
|
@@ -895,6 +913,14 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
895
913
|
cmds.push({ command: '/perm', description: '查看当前角色决定的权限模式', category: '权限管理', roles: [identity.role] });
|
|
896
914
|
if (canAnswerPermission)
|
|
897
915
|
cmds.push({ command: '/perm', args: 'allow|always|deny', description: '审批权限请求', category: '权限管理', roles: [identity.role] });
|
|
916
|
+
// 记忆管理(紧跟权限管理):能一键执行的都展开成无参数条目
|
|
917
|
+
const memoryOwnerForHelp = this.agentRegistry?.get?.(authSubject.selfAid ?? '')?.config?.owners?.[0];
|
|
918
|
+
cmds.push(...memoryHelpEntries({
|
|
919
|
+
chatType: 'private',
|
|
920
|
+
role: identity.role,
|
|
921
|
+
isAdmin,
|
|
922
|
+
isOwnerSelf: isOwner && !!memoryOwnerForHelp && (authSubject.principalId ?? userId) === memoryOwnerForHelp,
|
|
923
|
+
}));
|
|
898
924
|
// 运维
|
|
899
925
|
cmds.push({ command: '/status', description: '显示会话状态', category: '运维', roles: ['visitor', 'member', 'admin', 'owner'] });
|
|
900
926
|
cmds.push({ command: '/pause', description: '在下一次工具调用前暂停当前任务', category: '运维', roles: ['admin', 'owner'] });
|
|
@@ -924,7 +950,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
924
950
|
if (canReadChatmode || canSetChatmode)
|
|
925
951
|
cmds.push({ command: '/chatmode', ...(canSetChatmode ? { args: '[interactive|proactive]' } : {}), description: `查看${canSetChatmode ? '/切换' : ''}会话模式(被动响应或主动推进)`, category: '聊天设置', roles: [identity.role] });
|
|
926
952
|
if (canReadMentionmode || canSetMentionmode)
|
|
927
|
-
cmds.push({ command: '/
|
|
953
|
+
cmds.push({ command: '/mention', ...(canSetMentionmode ? { args: '[mention-only|disabled]' } : {}), description: `查看${canSetMentionmode ? '/切换' : ''}群聊 @ 处理模式`, category: '聊天设置', roles: [identity.role] });
|
|
928
954
|
// 交互
|
|
929
955
|
cmds.push({ command: '/ask', args: '<选项>', description: '回答 Agent 的交互式问题', category: '运维', roles: ['visitor', 'member', 'admin', 'owner'] });
|
|
930
956
|
// 帮助
|
|
@@ -1242,9 +1268,34 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1242
1268
|
}
|
|
1243
1269
|
}
|
|
1244
1270
|
this.eventBus.publish({ type: 'agent:baseagent-changed', aid: owningAgent.aid, baseagent: args, previousBaseagent, scope: 'agent', timestamp: Date.now() });
|
|
1271
|
+
// 与 /new 一致:按 关系>角色>agent 解析新 backend 实际生效的 model/effort,
|
|
1272
|
+
// 而不是只显示 baseagent 名。
|
|
1273
|
+
const newBaseagentRunner = this.getAgent(channel, newSession.baseagent);
|
|
1274
|
+
const newModelTarget = resolveSlashRelationTarget.call(this, {
|
|
1275
|
+
session: newSession,
|
|
1276
|
+
channel,
|
|
1277
|
+
channelId,
|
|
1278
|
+
userId,
|
|
1279
|
+
selfAID,
|
|
1280
|
+
role: newSession.identity?.role || identity.role,
|
|
1281
|
+
chatType,
|
|
1282
|
+
});
|
|
1283
|
+
const newModelSelector = 'error' in newModelTarget
|
|
1284
|
+
? { self: selfAID ?? newSession.selfAID ?? this.resolveSelfAID(channel) }
|
|
1285
|
+
: newModelTarget;
|
|
1286
|
+
let sessionModelConfig = {};
|
|
1287
|
+
try {
|
|
1288
|
+
sessionModelConfig = (resolveEffective(newModelSelector, { cache: true }).baseagents || {})[args] || {};
|
|
1289
|
+
}
|
|
1290
|
+
catch { }
|
|
1291
|
+
const sessionBackendModel = sessionModelConfig.model || newBaseagentRunner?.getModel?.() || owningAgent?.model;
|
|
1292
|
+
const sessionBackendEffort = sessionModelConfig.effort
|
|
1293
|
+
?? newBaseagentRunner?.getEffort?.()
|
|
1294
|
+
?? owningAgent?.effort;
|
|
1295
|
+
const sessionBackendBits = [args, sessionBackendModel, sessionBackendEffort].filter(Boolean).join(' · ');
|
|
1245
1296
|
return {
|
|
1246
1297
|
kind: 'system.notice',
|
|
1247
|
-
text: `✓
|
|
1298
|
+
text: `✓ 已切换新后端 : ${sessionBackendBits}`,
|
|
1248
1299
|
subtype: 'session.created',
|
|
1249
1300
|
};
|
|
1250
1301
|
}
|
|
@@ -2156,51 +2207,54 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2156
2207
|
return null;
|
|
2157
2208
|
return { kind: 'command.result', text: `✅ 会话模式已切换: ${arg}` };
|
|
2158
2209
|
}
|
|
2159
|
-
// /
|
|
2160
|
-
//
|
|
2161
|
-
if (normalizedContent === '/
|
|
2210
|
+
// /mention 命令:查看/切换群聊 @ 处理模式(mention-only | disabled | auto)
|
|
2211
|
+
// 写入层级按会话类型自动选择:群聊 → relation 级(当前群),私聊 → agent 级(Agent 全局默认)
|
|
2212
|
+
if (normalizedContent === '/mention' || normalizedContent.startsWith('/mention ')) {
|
|
2162
2213
|
const mentionSession = await getExistingSessionForCommand();
|
|
2163
2214
|
if (!mentionSession)
|
|
2164
2215
|
return { kind: 'command.error', text: '❌ 当前没有活跃会话' };
|
|
2165
2216
|
const mentionChatType = mentionSession.chatType || activeChatType;
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
const arg = normalizedContent.slice('/mentionmode'.length).trim();
|
|
2217
|
+
const isGroupChat = mentionChatType === 'group';
|
|
2218
|
+
const commandName = '/mention';
|
|
2219
|
+
const arg = normalizedContent.slice(commandName.length).trim();
|
|
2170
2220
|
const mentionTarget = resolveSlashMentionModeTarget.call(this, {
|
|
2171
2221
|
session: mentionSession,
|
|
2172
2222
|
channel,
|
|
2223
|
+
channelId,
|
|
2173
2224
|
selfAID,
|
|
2174
2225
|
role: mentionSession.identity?.role || identity.role,
|
|
2226
|
+
chatType: mentionChatType,
|
|
2175
2227
|
});
|
|
2176
2228
|
if ('error' in mentionTarget) {
|
|
2177
2229
|
return { kind: 'command.error', text: `❌ ${mentionTarget.error}` };
|
|
2178
2230
|
}
|
|
2179
2231
|
const mentionFallback = mentionSession.metadata?.mentionMode ?? null;
|
|
2180
2232
|
const currentMode = readSlashMentionMode(mentionTarget, mentionFallback);
|
|
2233
|
+
const scopeLabel = mentionTarget.scope === 'relation' ? '本群' : 'Agent 全局';
|
|
2181
2234
|
if (!arg) {
|
|
2182
|
-
const displayMode = currentMode ?? '
|
|
2235
|
+
const displayMode = currentMode ?? '未设置(跟随上级设置)';
|
|
2183
2236
|
if (groupSlash)
|
|
2184
|
-
return { kind: 'command.result', text: `@
|
|
2237
|
+
return { kind: 'command.result', text: `@ 处理模式(${scopeLabel}): ${displayMode}` };
|
|
2185
2238
|
// 尝试发送 CommandCard 卡片
|
|
2186
2239
|
if (isAdmin) {
|
|
2187
2240
|
const modes = [
|
|
2188
2241
|
{ key: 'mention-only', name: '提及模式', desc: '仅当被 @ 提及(含 @all)时响应群消息' },
|
|
2189
2242
|
{ key: 'disabled', name: '全响应模式', desc: '群内所有消息都触发响应' },
|
|
2243
|
+
{ key: 'auto', name: '自动模式', desc: '根据群上下文判断是否需要响应' },
|
|
2190
2244
|
];
|
|
2191
2245
|
const interaction = {
|
|
2192
2246
|
type: 'interaction',
|
|
2193
|
-
id: `
|
|
2247
|
+
id: `mention-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`,
|
|
2194
2248
|
channelId,
|
|
2195
2249
|
sessionId: mentionSession.id,
|
|
2196
2250
|
initiatorId: userId,
|
|
2197
2251
|
kind: {
|
|
2198
2252
|
kind: 'command-card',
|
|
2199
|
-
title:
|
|
2253
|
+
title: `📡 @ 处理模式(${scopeLabel})`,
|
|
2200
2254
|
body: modes.map(m => `${m.key === currentMode ? '✓' : '•'} **${m.key}** (${m.name}) - ${m.desc}`).join('\n'),
|
|
2201
2255
|
buttons: modes.map(m => ({
|
|
2202
2256
|
label: m.key === currentMode ? `✓ ${m.key}` : m.key,
|
|
2203
|
-
command: `/
|
|
2257
|
+
command: `/mention ${m.key}`,
|
|
2204
2258
|
style: (m.key === currentMode ? 'primary' : 'default'),
|
|
2205
2259
|
disabled: m.key === currentMode,
|
|
2206
2260
|
})),
|
|
@@ -2214,23 +2268,23 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2214
2268
|
}
|
|
2215
2269
|
// 降级:文本
|
|
2216
2270
|
if (isAdmin) {
|
|
2217
|
-
return { kind: 'command.result', text: `@
|
|
2271
|
+
return { kind: 'command.result', text: `@ 处理模式(${scopeLabel}): ${displayMode} 用法: /mention <mention-only|disabled|auto|clear>` };
|
|
2218
2272
|
}
|
|
2219
|
-
return { kind: 'command.result', text: `@
|
|
2273
|
+
return { kind: 'command.result', text: `@ 处理模式(${scopeLabel}): ${displayMode}` };
|
|
2220
2274
|
}
|
|
2221
|
-
if (arg !== 'mention-only' && arg !== 'disabled' && arg !== 'clear') {
|
|
2222
|
-
return { kind: 'command.error', text: `❌ 无效模式: ${arg}\n可选: mention-only / disabled / clear\n用法: /
|
|
2275
|
+
if (arg !== 'mention-only' && arg !== 'disabled' && arg !== 'auto' && arg !== 'clear') {
|
|
2276
|
+
return { kind: 'command.error', text: `❌ 无效模式: ${arg}\n可选: mention-only / disabled / auto / clear\n用法: /mention <模式>` };
|
|
2223
2277
|
}
|
|
2224
2278
|
const mentionAuthDenied = await authorizeIntent({
|
|
2225
2279
|
intent: {
|
|
2226
2280
|
operation: 'mentionmode.update',
|
|
2227
|
-
scope:
|
|
2281
|
+
scope: mentionTarget.scope,
|
|
2228
2282
|
source: 'slash',
|
|
2229
2283
|
args: { value: arg, self: mentionTarget.sel.self },
|
|
2230
2284
|
},
|
|
2231
2285
|
identity,
|
|
2232
2286
|
session: mentionSession,
|
|
2233
|
-
explicitChatType:
|
|
2287
|
+
explicitChatType: mentionChatType,
|
|
2234
2288
|
channel,
|
|
2235
2289
|
channelId,
|
|
2236
2290
|
userId,
|
|
@@ -2243,7 +2297,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2243
2297
|
writeSlashMentionMode(mentionTarget, null);
|
|
2244
2298
|
if (this.shouldSuppressCardTriggerResult(source, channel))
|
|
2245
2299
|
return null;
|
|
2246
|
-
return { kind: 'command.result', text:
|
|
2300
|
+
return { kind: 'command.result', text: `✅ 已清除${scopeLabel}覆盖,将跟随上级设置` };
|
|
2247
2301
|
}
|
|
2248
2302
|
if (arg === currentMode) {
|
|
2249
2303
|
return { kind: 'command.result', text: `当前已是 ${arg}` };
|
|
@@ -2251,7 +2305,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2251
2305
|
writeSlashMentionMode(mentionTarget, arg);
|
|
2252
2306
|
if (this.shouldSuppressCardTriggerResult(source, channel))
|
|
2253
2307
|
return null;
|
|
2254
|
-
return { kind: 'command.result', text: `✅ @
|
|
2308
|
+
return { kind: 'command.result', text: `✅ @ 处理模式(${scopeLabel})已切换: ${currentMode ?? '未设置'} → ${arg}` };
|
|
2255
2309
|
}
|
|
2256
2310
|
// /stop 命令:中断当前任务
|
|
2257
2311
|
if (normalizedContent.startsWith('/stop ')) {
|
|
@@ -2570,22 +2624,27 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2570
2624
|
const mentionModeTarget = resolveSlashMentionModeTarget.call(this, {
|
|
2571
2625
|
session,
|
|
2572
2626
|
channel,
|
|
2627
|
+
channelId,
|
|
2573
2628
|
selfAID,
|
|
2574
2629
|
role: sessionRole,
|
|
2630
|
+
chatType: session.chatType,
|
|
2575
2631
|
});
|
|
2576
2632
|
const mentionModeFallback = session.metadata?.mentionMode ?? null;
|
|
2577
2633
|
const mentionMode = 'error' in mentionModeTarget
|
|
2578
|
-
? (mentionModeFallback ?? '
|
|
2579
|
-
: (readSlashMentionMode(mentionModeTarget, mentionModeFallback) ?? '
|
|
2634
|
+
? (mentionModeFallback ?? '未设置')
|
|
2635
|
+
: (readSlashMentionMode(mentionModeTarget, mentionModeFallback) ?? '未设置');
|
|
2636
|
+
const mentionScopeLabel = 'error' in mentionModeTarget
|
|
2637
|
+
? '本群'
|
|
2638
|
+
: mentionModeTarget.scope === 'relation' ? '本群' : 'Agent 全局';
|
|
2580
2639
|
const chatModeLine = `会话模式: ${chatMode}`;
|
|
2581
|
-
const mentionModeLine =
|
|
2640
|
+
const mentionModeLine = `@ 处理模式(${mentionScopeLabel}): ${mentionMode}`;
|
|
2582
2641
|
if (isAdmin) {
|
|
2583
2642
|
const gitInfo = await getGitWorkingDirInfo(session.projectPath);
|
|
2584
2643
|
lines.push(`📊 ${isThread ? '话题' : '会话'}状态 (Agent: ${agentName}):`, `渠道: ${this.resolveChannelType(channel)} / 项目: ${projectName} / 会话: ${displaySessionTitle(session.name, '(未命名)')}`, `会话ID: ${session.id}`, `项目路径: ${session.projectPath}`);
|
|
2585
2644
|
if (gitInfo) {
|
|
2586
2645
|
lines.push(`Git: ${gitInfo}`);
|
|
2587
2646
|
}
|
|
2588
|
-
lines.push(`会话状态: ${sessionStatus} / 轮数: ${sessionTurns} / 已记录子任务数: ${sessionSubtasks}`, sessionRoleLine, chatModeLine,
|
|
2647
|
+
lines.push(`会话状态: ${sessionStatus} / 轮数: ${sessionTurns} / 已记录子任务数: ${sessionSubtasks}`, sessionRoleLine, chatModeLine, mentionModeLine);
|
|
2589
2648
|
if (health.consecutiveErrors > 0) {
|
|
2590
2649
|
lines.push(`异常计数: ${health.consecutiveErrors}`);
|
|
2591
2650
|
}
|
|
@@ -2593,7 +2652,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2593
2652
|
}
|
|
2594
2653
|
else {
|
|
2595
2654
|
lines.push(`📊 ${isThread ? '话题' : '会话'}状态 (Agent: ${agentName}):`, `渠道: ${channel} / 项目: ${projectName} / ${session.baseagent}会话`);
|
|
2596
|
-
lines.push(`状态: ${sessionStatus} / 轮数: ${sessionTurns} / 已记录子任务数: ${sessionSubtasks}`, sessionRoleLine, chatModeLine,
|
|
2655
|
+
lines.push(`状态: ${sessionStatus} / 轮数: ${sessionTurns} / 已记录子任务数: ${sessionSubtasks}`, sessionRoleLine, chatModeLine, mentionModeLine, `最后活跃: ${timeStr}`);
|
|
2597
2656
|
}
|
|
2598
2657
|
if (health.lastError) {
|
|
2599
2658
|
lines.push('');
|
|
@@ -2614,11 +2673,17 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2614
2673
|
await interruptPausedSessionBeforeReplacement(session || activeSession);
|
|
2615
2674
|
const projectPath = this.getEffectiveDefaultPath(channel);
|
|
2616
2675
|
if (sendMessage && session) {
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2676
|
+
const creatingText = `⏳ 正在创建新会话${sessionName ? `: ${sessionName}` : ''}...`;
|
|
2677
|
+
// 私聊改回普通文本:AUN 私聊里 system.notice 会渲染成系统通知样式,
|
|
2678
|
+
// 这里希望它像 /compact 等命令的占位提示一样,按普通消息发送。
|
|
2679
|
+
const creatingPayload = activeChatType === 'private'
|
|
2680
|
+
? { kind: 'command.result', text: creatingText }
|
|
2681
|
+
: {
|
|
2682
|
+
kind: 'system.notice',
|
|
2683
|
+
text: creatingText,
|
|
2684
|
+
subtype: 'session.creating',
|
|
2685
|
+
};
|
|
2686
|
+
await sendMessage(channelId, creatingText, this.getReplyContext(session), creatingPayload);
|
|
2622
2687
|
}
|
|
2623
2688
|
const newSessionBaseagent = this.agentRegistry?.resolveByChannel(channel)?.baseagent || this.parseDefaultBaseagent();
|
|
2624
2689
|
const previousMetadata = session?.metadata || activeSession?.metadata || {};
|
|
@@ -2635,7 +2700,22 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2635
2700
|
...(previousMetadata.peerName ? { peerName: previousMetadata.peerName } : {}),
|
|
2636
2701
|
...(previousMetadata.peerType ? { peerType: previousMetadata.peerType } : {}),
|
|
2637
2702
|
};
|
|
2638
|
-
|
|
2703
|
+
// 源会话快照(执行 /new 的那个会话):供记忆整理触发用,
|
|
2704
|
+
// 不依赖旧会话是否还有活动 taskCtx(/new 后旧会话任务可能已结束)。
|
|
2705
|
+
const sourceForConsolidation = session || activeSession;
|
|
2706
|
+
const newSession = await this.sessionManager.createNewSession(channel, channelId, projectPath, sessionName, newSessionBaseagent, newSessionIdentityMetadata, {
|
|
2707
|
+
sourceSessionId: sourceForConsolidation?.id,
|
|
2708
|
+
sourceChannel: sourceForConsolidation?.channelType || channel,
|
|
2709
|
+
sourceChannelId: channelId,
|
|
2710
|
+
sourceChatType: activeChatType,
|
|
2711
|
+
sourceThreadId: sourceForConsolidation?.threadId || undefined,
|
|
2712
|
+
sourceSelfAid: sourceForConsolidation?.selfAID
|
|
2713
|
+
|| selfAID
|
|
2714
|
+
|| this.getOwningAgent(channel)?.aid
|
|
2715
|
+
|| this.resolveSelfAID(channel)
|
|
2716
|
+
|| undefined,
|
|
2717
|
+
sourcePeerId: sourceForConsolidation?.metadata?.peerId || userId || undefined,
|
|
2718
|
+
});
|
|
2639
2719
|
const previousSession = session || activeSession;
|
|
2640
2720
|
const handoffSelfAid = previousSession?.selfAID
|
|
2641
2721
|
|| selfAID
|
|
@@ -2689,7 +2769,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2689
2769
|
const backendBits = [newBaseagent, backendModel, backendEffort].filter(Boolean).join(' · ');
|
|
2690
2770
|
return {
|
|
2691
2771
|
kind: 'system.notice',
|
|
2692
|
-
text: `✓ 已创建新会话${sessionName ? `: ${sessionName}` : ''}
|
|
2772
|
+
text: `✓ 已创建新会话${sessionName ? `: ${sessionName}` : ''} : ${backendBits}${handoffDiscardWarning ? `\n${handoffDiscardWarning}` : ''}`,
|
|
2693
2773
|
subtype: 'session.created',
|
|
2694
2774
|
};
|
|
2695
2775
|
}
|
|
@@ -3268,9 +3348,9 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
3268
3348
|
if (stat.isDirectory()) {
|
|
3269
3349
|
return { kind: 'command.error', text: '❌ 暂不支持发送目录\n目录打包发送将在后续版本支持' };
|
|
3270
3350
|
}
|
|
3271
|
-
const MAX_SIZE =
|
|
3351
|
+
const MAX_SIZE = MAX_AUN_ATTACHMENT_SIZE;
|
|
3272
3352
|
if (stat.size > MAX_SIZE) {
|
|
3273
|
-
return { kind: 'command.error', text: `❌ 文件过大: ${(stat.size / 1024 / 1024).toFixed(1)} MB (限制
|
|
3353
|
+
return { kind: 'command.error', text: `❌ 文件过大: ${(stat.size / 1024 / 1024).toFixed(1)} MB (限制 ${MAX_SIZE / 1024 / 1024} MB)` };
|
|
3274
3354
|
}
|
|
3275
3355
|
// 找目标 channelId
|
|
3276
3356
|
let targetChannelId = channelId;
|
|
@@ -3695,23 +3775,23 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
3695
3775
|
}
|
|
3696
3776
|
}
|
|
3697
3777
|
// /rewind 命令:查看历史 / 回退会话
|
|
3698
|
-
if (
|
|
3778
|
+
if (/^\/rewind(?:\s|$)/.test(normalizedContent)) {
|
|
3699
3779
|
const session = await getExistingSessionForCommand();
|
|
3700
3780
|
if (!session)
|
|
3701
3781
|
return { kind: 'command.error', text: '❌ 当前没有活跃会话' };
|
|
3702
|
-
const rewindBaseagent = session.baseagent;
|
|
3703
|
-
if (!rewindBaseagent) {
|
|
3704
|
-
return { kind: 'command.error', text: '❌ 当前会话缺少 baseagent 绑定,拒绝隐式切换' };
|
|
3705
|
-
}
|
|
3706
|
-
const rewindAgent = this.getAgent(channel, rewindBaseagent);
|
|
3707
|
-
if (!session.agentSessionId) {
|
|
3708
|
-
return { kind: 'command.error', text: '❌ 当前会话无历史记录\n\n请先发送一条消息,然后再使用 /rewind' };
|
|
3709
|
-
}
|
|
3710
|
-
if (!rewindAgent.getSessionMessages) {
|
|
3711
|
-
return { kind: 'command.error', text: `❌ 当前 Agent (${rewindAgent.name}) 不支持 /rewind` };
|
|
3712
|
-
}
|
|
3713
3782
|
const args = normalizedContent.slice('/rewind'.length).trim();
|
|
3714
3783
|
if (!args) {
|
|
3784
|
+
const rewindBaseagent = session.baseagent;
|
|
3785
|
+
if (!rewindBaseagent) {
|
|
3786
|
+
return { kind: 'command.error', text: '❌ 当前会话缺少 baseagent 绑定,拒绝隐式切换' };
|
|
3787
|
+
}
|
|
3788
|
+
const rewindAgent = this.getAgent(channel, rewindBaseagent);
|
|
3789
|
+
if (!session.agentSessionId) {
|
|
3790
|
+
return { kind: 'command.error', text: '❌ 当前会话无历史记录\n\n请先发送一条消息,然后再使用 /rewind' };
|
|
3791
|
+
}
|
|
3792
|
+
if (!rewindAgent.getSessionMessages) {
|
|
3793
|
+
return { kind: 'command.error', text: `❌ 当前 Agent (${rewindAgent.name}) 不支持 /rewind` };
|
|
3794
|
+
}
|
|
3715
3795
|
return { kind: 'command.result', text: await this.handleRewindList(session, rewindAgent) };
|
|
3716
3796
|
}
|
|
3717
3797
|
// 带参(执行回退,会删除文件/改对话)需 admin+
|
|
@@ -3729,6 +3809,46 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
3729
3809
|
if (!['chat', 'file', 'all'].includes(mode)) {
|
|
3730
3810
|
return { kind: 'command.error', text: `❌ 无效模式 "${mode}",可选:chat | file | all` };
|
|
3731
3811
|
}
|
|
3812
|
+
if (session.threadId) {
|
|
3813
|
+
// 话题只开放 N>1;N=1 会清空 backend binding,仍保留原有禁止边界。
|
|
3814
|
+
if (turnNum === 1) {
|
|
3815
|
+
return { kind: 'command.error', text: '❌ 话题会话暂不支持 /rewind 1,仅开放 N>1' };
|
|
3816
|
+
}
|
|
3817
|
+
const outcome = await withIdleTopicBackend(session.id, session.threadId, async (current) => {
|
|
3818
|
+
if (!current.baseagent) {
|
|
3819
|
+
return '❌ 当前会话缺少 baseagent 绑定,拒绝隐式切换';
|
|
3820
|
+
}
|
|
3821
|
+
if (!current.agentSessionId) {
|
|
3822
|
+
return '❌ 当前会话无历史记录\n\n请先发送一条消息,然后再使用 /rewind';
|
|
3823
|
+
}
|
|
3824
|
+
const currentAgent = this.getAgent(channel, current.baseagent);
|
|
3825
|
+
if (!currentAgent.getSessionMessages) {
|
|
3826
|
+
return `❌ 当前 Agent (${currentAgent.name}) 不支持 /rewind`;
|
|
3827
|
+
}
|
|
3828
|
+
return this.handleRewind(current, currentAgent, turnNum, mode);
|
|
3829
|
+
}, session);
|
|
3830
|
+
if (!outcome.ok) {
|
|
3831
|
+
if (outcome.reason === 'busy') {
|
|
3832
|
+
return { kind: 'command.error', text: '⚠️ 当前话题会话忙碌,无法回退,请稍后再试\n使用 /stop 中断当前任务后重试' };
|
|
3833
|
+
}
|
|
3834
|
+
if (outcome.reason === 'unknown') {
|
|
3835
|
+
return { kind: 'command.error', text: '⚠️ 当前话题会话状态未知,无法安全回退,请稍后再试' };
|
|
3836
|
+
}
|
|
3837
|
+
return { kind: 'command.error', text: '❌ 当前话题会话不存在或归属已变化' };
|
|
3838
|
+
}
|
|
3839
|
+
return { kind: 'command.result', text: outcome.value };
|
|
3840
|
+
}
|
|
3841
|
+
const rewindBaseagent = session.baseagent;
|
|
3842
|
+
if (!rewindBaseagent) {
|
|
3843
|
+
return { kind: 'command.error', text: '❌ 当前会话缺少 baseagent 绑定,拒绝隐式切换' };
|
|
3844
|
+
}
|
|
3845
|
+
const rewindAgent = this.getAgent(channel, rewindBaseagent);
|
|
3846
|
+
if (!session.agentSessionId) {
|
|
3847
|
+
return { kind: 'command.error', text: '❌ 当前会话无历史记录\n\n请先发送一条消息,然后再使用 /rewind' };
|
|
3848
|
+
}
|
|
3849
|
+
if (!rewindAgent.getSessionMessages) {
|
|
3850
|
+
return { kind: 'command.error', text: `❌ 当前 Agent (${rewindAgent.name}) 不支持 /rewind` };
|
|
3851
|
+
}
|
|
3732
3852
|
await interruptPausedSessionBeforeReplacement(session);
|
|
3733
3853
|
return { kind: 'command.result', text: await this.handleRewind(session, rewindAgent, turnNum, mode) };
|
|
3734
3854
|
}
|
|
@@ -3780,6 +3900,28 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
3780
3900
|
}
|
|
3781
3901
|
}
|
|
3782
3902
|
// /trigger 命令
|
|
3903
|
+
if (normalizedContent === '/memory' || normalizedContent.startsWith('/memory ')) {
|
|
3904
|
+
const memoryAgent = this.agentRegistry?.get?.(authSubject.selfAid ?? '');
|
|
3905
|
+
const memoryOwnerAid = memoryAgent?.config?.owners?.[0];
|
|
3906
|
+
const memorySession = await getExistingSessionForCommand();
|
|
3907
|
+
return await handleMemorySlash({
|
|
3908
|
+
content: normalizedContent,
|
|
3909
|
+
selfAid: authSubject.selfAid,
|
|
3910
|
+
peerKey: authSubject.peerKey,
|
|
3911
|
+
chatType: activeChatType === 'group' ? 'group' : 'private',
|
|
3912
|
+
role: identity.role,
|
|
3913
|
+
isAdmin,
|
|
3914
|
+
isOwnerSelf: isOwner && !!memoryOwnerAid && (authSubject.principalId ?? userId) === memoryOwnerAid,
|
|
3915
|
+
ownerAid: memoryOwnerAid,
|
|
3916
|
+
memoryConfig: memoryAgent?.config?.memory,
|
|
3917
|
+
channelType: authSubject.channelType,
|
|
3918
|
+
peerId: activeChatType === 'group' ? channelId : (userId ?? channelId),
|
|
3919
|
+
threadId,
|
|
3920
|
+
sessionId: memorySession?.id,
|
|
3921
|
+
baseagent: memorySession?.baseagent,
|
|
3922
|
+
launcher: this.memoryConsolidationLauncher,
|
|
3923
|
+
});
|
|
3924
|
+
}
|
|
3783
3925
|
if (normalizedContent === '/trigger' || normalizedContent.startsWith('/trigger ')) {
|
|
3784
3926
|
const triggerAuthDenied = await authorizeIntent({
|
|
3785
3927
|
intent: {
|