evolclaw 3.2.0 → 3.4.0
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 +53 -0
- package/README.md +7 -4
- package/dist/agents/{resolve.js → baseagent.js} +34 -5
- package/dist/agents/claude-runner.js +120 -31
- package/dist/agents/codex-app-server-client.js +364 -0
- package/dist/agents/codex-runner.js +1152 -140
- package/dist/agents/gemini-runner.js +2 -2
- package/dist/agents/runner-types.js +58 -0
- package/dist/aun/aid/store.js +1 -1
- package/dist/aun/outbox.js +14 -2
- package/dist/aun/storage/download.js +1 -1
- package/dist/aun/storage/upload.js +13 -1
- package/dist/channels/aun.js +869 -358
- package/dist/channels/dingtalk.js +77 -140
- package/dist/channels/feishu.js +125 -154
- package/dist/channels/qqbot.js +75 -138
- package/dist/channels/wechat.js +75 -136
- package/dist/channels/wecom.js +75 -138
- package/dist/cli/agent-command.js +591 -0
- package/dist/cli/agent.js +23 -8
- package/dist/cli/aun-commands.js +1444 -0
- package/dist/cli/ctl-command.js +78 -0
- package/dist/cli/daemon-commands.js +2707 -0
- package/dist/cli/index.js +23 -4905
- package/dist/cli/init.js +33 -6
- package/dist/cli/model.js +1 -1
- package/dist/cli/restart-monitor.js +539 -0
- package/dist/cli/stats.js +558 -0
- package/dist/cli/version.js +87 -0
- package/dist/cli/watch-logs.js +33 -0
- package/dist/cli/watch-msg.js +5 -2
- package/dist/config-store.js +12 -6
- package/dist/core/channel-loader.js +88 -83
- package/dist/core/command/command-handler.js +1189 -0
- package/dist/core/command/menu-handler.js +1478 -0
- package/dist/core/command/slash-gate.js +142 -0
- package/dist/core/command/slash-handler.js +2090 -0
- package/dist/core/evolagent-registry.js +82 -0
- package/dist/core/evolagent.js +17 -1
- package/dist/core/interaction-router.js +8 -0
- package/dist/core/message/command-handler-agent-control.js +63 -1
- package/dist/core/message/im-renderer.js +91 -51
- package/dist/core/message/items-formatter.js +9 -1
- package/dist/core/message/message-bridge.js +73 -24
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-processor.js +432 -94
- package/dist/core/message/message-queue.js +70 -2
- package/dist/core/message/pending-hints.js +232 -0
- package/dist/core/model/model-catalog.js +1 -1
- package/dist/core/model/model-scope.js +2 -2
- package/dist/core/permission.js +25 -12
- package/dist/core/relation/peer-identity.js +16 -1
- package/dist/core/session/adapters/codex-session-file-adapter.js +4 -2
- package/dist/core/session/session-manager.js +86 -26
- package/dist/core/session/session-title.js +26 -0
- package/dist/core/stats/billing.js +151 -0
- package/dist/core/stats/budget.js +93 -0
- package/dist/core/stats/db.js +334 -0
- package/dist/core/stats/eck-vars.js +84 -0
- package/dist/core/stats/index.js +10 -0
- package/dist/core/stats/normalizer.js +78 -0
- package/dist/core/stats/query.js +760 -0
- package/dist/core/stats/writer.js +115 -0
- package/dist/core/trigger/manager.js +34 -0
- package/dist/core/trigger/parser.js +9 -3
- package/dist/core/trigger/scheduler.js +20 -17
- package/dist/data/error-dict.json +7 -0
- package/dist/{agents → eck}/manifest-engine.js +20 -1
- package/dist/{agents → eck}/message-renderer.js +24 -1
- package/dist/index.js +174 -9
- package/dist/ipc.js +116 -1
- package/dist/utils/cross-platform.js +58 -5
- package/dist/utils/ecweb-launch.js +49 -0
- package/dist/utils/ecweb-pair.js +20 -0
- package/dist/utils/error-utils.js +18 -5
- package/dist/utils/npm-ops.js +38 -8
- package/dist/utils/stats.js +77 -6
- package/kits/docs/evolclaw/INDEX.md +3 -1
- package/kits/docs/evolclaw/fs-architecture.md +1215 -0
- package/kits/docs/evolclaw/fs.md +131 -0
- package/kits/docs/evolclaw/group-fs.md +209 -0
- package/kits/docs/evolclaw/stats.md +70 -0
- package/kits/docs/venues/aun-group.md +29 -6
- package/kits/docs/venues/group.md +5 -4
- package/kits/eck_message_manifest.json +30 -3
- package/kits/rules/05-venue.md +1 -1
- package/kits/templates/message-fragments/inject-default.md +2 -0
- package/package.json +5 -6
- package/dist/agents/baseagent-normalize.js +0 -19
- package/dist/core/command-handler.js +0 -3876
- package/dist/core/relation/peer-key.js +0 -16
- package/dist/evolclaw-config.js +0 -11
- package/dist/utils/channel-helpers.js +0 -46
- /package/dist/core/{cache/file-cache.js → daemon-file-cache.js} +0 -0
- /package/dist/{agents → eck}/kit-renderer.js +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// 支持的命令列表
|
|
2
|
+
const commands = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/setmodel', '/effort', '/baseagent', '/slist', '/session', '/rename', '/stop', '/compact', '/repair', '/safe', '/fork', '/del', '/perm', '/file', '/check', '/rewind', '/activity', '/chatmode', '/dispatch', '/ask', '/resume', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade'];
|
|
3
|
+
const deprecatedCommands = ['/clear'];
|
|
4
|
+
// 命令别名映射
|
|
5
|
+
const aliases = {
|
|
6
|
+
'/s': '/session',
|
|
7
|
+
'/name': '/rename',
|
|
8
|
+
'/rw': '/rewind',
|
|
9
|
+
'/base': '/baseagent',
|
|
10
|
+
};
|
|
11
|
+
// 命令快速路径前缀(所有命令都不进入消息队列)
|
|
12
|
+
const quickCommandPrefixes = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/setmodel', '/effort', '/baseagent', '/slist', '/session', '/rename', '/repair', '/fork', '/stop', '/clear', '/compact', '/safe', '/del', '/perm', '/file', '/check', '/s ', '/name', '/rewind', '/rw', '/rw ', '/activity', '/chatmode', '/dispatch', '/ask', '/resume', '/base ', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade'];
|
|
13
|
+
/**
|
|
14
|
+
* 计算两个字符串的 Levenshtein 距离(编辑距离)
|
|
15
|
+
*/
|
|
16
|
+
function levenshteinDistance(str1, str2) {
|
|
17
|
+
const len1 = str1.length;
|
|
18
|
+
const len2 = str2.length;
|
|
19
|
+
const matrix = [];
|
|
20
|
+
for (let i = 0; i <= len1; i++) {
|
|
21
|
+
matrix[i] = [i];
|
|
22
|
+
}
|
|
23
|
+
for (let j = 0; j <= len2; j++) {
|
|
24
|
+
matrix[0][j] = j;
|
|
25
|
+
}
|
|
26
|
+
for (let i = 1; i <= len1; i++) {
|
|
27
|
+
for (let j = 1; j <= len2; j++) {
|
|
28
|
+
if (str1[i - 1] === str2[j - 1]) {
|
|
29
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // 替换
|
|
33
|
+
matrix[i][j - 1] + 1, // 插入
|
|
34
|
+
matrix[i - 1][j] + 1 // 删除
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return matrix[len1][len2];
|
|
40
|
+
}
|
|
41
|
+
export function isQuickCommand(content) {
|
|
42
|
+
return content === '/s' || quickCommandPrefixes.some(cmd => content.startsWith(cmd));
|
|
43
|
+
}
|
|
44
|
+
export function normalizeSlashContent(content) {
|
|
45
|
+
for (const [alias, full] of Object.entries(aliases)) {
|
|
46
|
+
if (content === alias || content.startsWith(alias + ' ')) {
|
|
47
|
+
return content.replace(alias, full);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return content;
|
|
51
|
+
}
|
|
52
|
+
export function isRecognizedSlashCommand(content) {
|
|
53
|
+
return commands.some(cmd => content.startsWith(cmd)) ||
|
|
54
|
+
deprecatedCommands.some(cmd => content === cmd || content.startsWith(cmd + ' '));
|
|
55
|
+
}
|
|
56
|
+
export function guardThreadCommand(content, threadId) {
|
|
57
|
+
if (!threadId)
|
|
58
|
+
return undefined;
|
|
59
|
+
const threadBlocked = ['/new', '/slist', '/s', '/session', '/fork', '/del', '/baseagent'];
|
|
60
|
+
const isBlocked = threadBlocked.some(c => content === c || content.startsWith(c + ' '));
|
|
61
|
+
if (!isBlocked)
|
|
62
|
+
return undefined;
|
|
63
|
+
return { kind: 'command.error', text: '⚠️ 话题中不支持此命令' };
|
|
64
|
+
}
|
|
65
|
+
export function guardRoleCommand(content, activeChatType, isAdmin) {
|
|
66
|
+
if (!content.startsWith('/'))
|
|
67
|
+
return undefined;
|
|
68
|
+
// guest 在群聊和私聊中均可访问的只读命令:纯查询形态(带参写操作由各 handler 内部守卫拦截)
|
|
69
|
+
const guestGroupCommands = [
|
|
70
|
+
'/status', '/help', '/evolhelp', '/check', '/chatmode', '/dispatch',
|
|
71
|
+
'/model', '/setmodel', '/effort', '/baseagent', '/perm', '/activity', '/safe', '/stop',
|
|
72
|
+
'/resume', '/trigger',
|
|
73
|
+
];
|
|
74
|
+
const userCommands = activeChatType === 'group' && !isAdmin
|
|
75
|
+
? guestGroupCommands
|
|
76
|
+
: [
|
|
77
|
+
...guestGroupCommands,
|
|
78
|
+
// 私聊 guest 额外可用:会话自管理 + 私聊专属的 /rewind 历史查看
|
|
79
|
+
'/slist', '/new', '/session', '/rename', '/name', '/del', '/s ', '/rewind',
|
|
80
|
+
];
|
|
81
|
+
const isUserCommand = userCommands.some(cmd => content === cmd.trimEnd() || content.startsWith(cmd));
|
|
82
|
+
if (isUserCommand || isAdmin)
|
|
83
|
+
return undefined;
|
|
84
|
+
return {
|
|
85
|
+
kind: 'command.error',
|
|
86
|
+
text: activeChatType === 'group'
|
|
87
|
+
? '❌ 无权限:当前群聊仅支持 /status 和 /help'
|
|
88
|
+
: '❌ 无权限:此命令仅限管理员使用',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export async function guardIdleCommand(opts) {
|
|
92
|
+
// 空闲检查:某些命令需要等待当前会话空闲
|
|
93
|
+
// 原则:仅对"写/破坏性"形态拦截,纯读/用法提示的无参形态始终放行
|
|
94
|
+
// - 始终需要 idle(无参即写):/compact /repair /fork /new
|
|
95
|
+
// - 仅带参时需要 idle(无参是列表/用法):/session /baseagent /rewind
|
|
96
|
+
// - /chatmode:在 handler 内部自行做写操作的 idle 检查
|
|
97
|
+
// - /dispatch:在 handler 内部自行做写操作的 idle 检查
|
|
98
|
+
// - /safe:已禁用 no-op,不再要求 idle
|
|
99
|
+
const idleAlways = ['/compact', '/repair', '/fork', '/new'];
|
|
100
|
+
const idleWhenArg = ['/session', '/baseagent', '/rewind'];
|
|
101
|
+
const needsIdle = idleAlways.some(cmd => opts.content === cmd || opts.content.startsWith(cmd + ' ')) ||
|
|
102
|
+
idleWhenArg.some(cmd => opts.content.startsWith(cmd + ' '));
|
|
103
|
+
if (!needsIdle)
|
|
104
|
+
return undefined;
|
|
105
|
+
if (opts.threadId) {
|
|
106
|
+
// 话题中:检查话题 session 是否在处理(不创建)
|
|
107
|
+
const threadSession = await opts.sessionManager.getThreadSession(opts.channel, opts.channelId, opts.threadId);
|
|
108
|
+
if (threadSession) {
|
|
109
|
+
const threadAgent = opts.getAgentForSession(threadSession);
|
|
110
|
+
const isBusy = threadAgent.hasActiveStream(threadSession.id) ||
|
|
111
|
+
opts.messageQueue?.isProcessing(threadSession.id);
|
|
112
|
+
if (isBusy) {
|
|
113
|
+
return { kind: 'command.error', text: '⚠️ 当前正在处理消息,请稍后再试\n使用 /stop 中断当前任务后重试' };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (opts.activeSession) {
|
|
118
|
+
const isBusy = opts.activeAgent.hasActiveStream(opts.activeSession.id) ||
|
|
119
|
+
opts.messageQueue?.isProcessing(opts.activeSession.id);
|
|
120
|
+
if (isBusy) {
|
|
121
|
+
return { kind: 'command.error', text: '⚠️ 当前正在处理消息,请稍后再试\n使用 /stop 中断当前任务后重试' };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
export function guardKnownCommand(content) {
|
|
127
|
+
// 检查是否以 / 开头(可能是命令)
|
|
128
|
+
if (!content.startsWith('/'))
|
|
129
|
+
return undefined;
|
|
130
|
+
const inputCmd = content.split(' ')[0];
|
|
131
|
+
const isValidCommand = isRecognizedSlashCommand(content);
|
|
132
|
+
if (isValidCommand)
|
|
133
|
+
return undefined;
|
|
134
|
+
const similar = commands.find(cmd => {
|
|
135
|
+
const distance = levenshteinDistance(inputCmd, cmd);
|
|
136
|
+
return distance <= 2;
|
|
137
|
+
});
|
|
138
|
+
if (similar) {
|
|
139
|
+
return { kind: 'command.error', text: `❌ 未知命令: ${inputCmd}\n💡 你是不是想输入: ${similar}\n\n输入 /help 查看所有可用命令` };
|
|
140
|
+
}
|
|
141
|
+
return { kind: 'command.error', text: `❌ 未知命令: ${inputCmd}\n\n输入 /help 查看所有可用命令` };
|
|
142
|
+
}
|