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
|
@@ -13,7 +13,7 @@ import { createInterface } from 'readline';
|
|
|
13
13
|
import fs from 'fs';
|
|
14
14
|
import path from 'path';
|
|
15
15
|
import os from 'os';
|
|
16
|
-
import { resolveGoogleConfig } from './
|
|
16
|
+
import { resolveGoogleConfig } from './baseagent.js';
|
|
17
17
|
import { commandExists } from '../utils/cross-platform.js';
|
|
18
18
|
import { GeminiSessionFileAdapter } from '../core/session/adapters/gemini-session-file-adapter.js';
|
|
19
19
|
import { logger } from '../utils/logger.js';
|
|
@@ -41,7 +41,7 @@ const GEMINI_MODELS = [
|
|
|
41
41
|
// ── Gemini Runner ──
|
|
42
42
|
export class GeminiRunner {
|
|
43
43
|
name = 'gemini';
|
|
44
|
-
capabilities = { clear: true, compact: false, fork: false };
|
|
44
|
+
capabilities = { clear: true, compact: false, fork: false, askUserQuestion: false, planApproval: false, fileRewind: 'unsupported' };
|
|
45
45
|
resolved;
|
|
46
46
|
model;
|
|
47
47
|
activeProcesses = new Map();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ── 类型守卫 ──
|
|
2
|
+
export function hasModelSwitcher(agent) {
|
|
3
|
+
return typeof agent.setModel === 'function' && typeof agent.listModels === 'function';
|
|
4
|
+
}
|
|
5
|
+
export function hasPermissionController(agent) {
|
|
6
|
+
return typeof agent.setMode === 'function' && typeof agent.listModes === 'function';
|
|
7
|
+
}
|
|
8
|
+
export function hasCompact(agent) {
|
|
9
|
+
return typeof agent.compact === 'function';
|
|
10
|
+
}
|
|
11
|
+
// ── Token usage helper functions ──
|
|
12
|
+
export function numericToken(value) {
|
|
13
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
|
14
|
+
}
|
|
15
|
+
export function contextTokensForUsage(usage, isClaudeModel) {
|
|
16
|
+
if (!usage)
|
|
17
|
+
return 0;
|
|
18
|
+
if (!isClaudeModel)
|
|
19
|
+
return numericToken(usage.input_tokens);
|
|
20
|
+
return numericToken(usage.input_tokens)
|
|
21
|
+
+ numericToken(usage.cache_creation_input_tokens)
|
|
22
|
+
+ numericToken(usage.cache_read_input_tokens);
|
|
23
|
+
}
|
|
24
|
+
export function usageForContext(usage) {
|
|
25
|
+
const iterations = Array.isArray(usage?.iterations) ? usage.iterations : undefined;
|
|
26
|
+
const lastIteration = iterations?.slice().reverse().find(it => contextTokensForUsage(it, true) > 0);
|
|
27
|
+
return lastIteration ?? usage;
|
|
28
|
+
}
|
|
29
|
+
/** Models whose base ID uses a 1M context window when sent to the SDK with [1m]. */
|
|
30
|
+
export const ONE_M_CONTEXT_MODEL_PREFIXES = ['claude-opus-4-8', 'claude-sonnet-4-6'];
|
|
31
|
+
const ONE_M_CONTEXT_MODEL_ALIASES = ['opus', 'sonnet'];
|
|
32
|
+
const CLAUDE_CONTEXT_MODEL_ALIASES = ['opus', 'sonnet', 'haiku'];
|
|
33
|
+
export function isClaudeContextUsageModel(model) {
|
|
34
|
+
if (!model)
|
|
35
|
+
return false;
|
|
36
|
+
const baseModel = model.replace(/\[1m\]$/i, '');
|
|
37
|
+
return /^claude-/i.test(baseModel) || CLAUDE_CONTEXT_MODEL_ALIASES.includes(baseModel);
|
|
38
|
+
}
|
|
39
|
+
export function isOneMillionContextModel(model) {
|
|
40
|
+
if (!model)
|
|
41
|
+
return false;
|
|
42
|
+
if (ONE_M_CONTEXT_MODEL_ALIASES.includes(model))
|
|
43
|
+
return true;
|
|
44
|
+
if (/\[1m\]$/i.test(model))
|
|
45
|
+
return true;
|
|
46
|
+
if (/deepseek-v4/i.test(model))
|
|
47
|
+
return true;
|
|
48
|
+
const baseModel = model.replace(/\[1m\]$/i, '');
|
|
49
|
+
return ONE_M_CONTEXT_MODEL_PREFIXES.some(prefix => baseModel === prefix || baseModel.startsWith(`${prefix}-`));
|
|
50
|
+
}
|
|
51
|
+
/** Real context window size: 1M models = 1000000, otherwise 200000. */
|
|
52
|
+
export function realContextWindowForModel(model) {
|
|
53
|
+
return isOneMillionContextModel(model) ? 1000000 : 200000;
|
|
54
|
+
}
|
|
55
|
+
/** autoCompact trigger threshold: 1M models = 900000, otherwise 200000. */
|
|
56
|
+
export function autoCompactWindowForModel(model) {
|
|
57
|
+
return isOneMillionContextModel(model) ? 900000 : 200000;
|
|
58
|
+
}
|
package/dist/aun/aid/store.js
CHANGED
|
@@ -39,7 +39,7 @@ export class AidLoadError extends Error {
|
|
|
39
39
|
*/
|
|
40
40
|
export async function getAidStore(opts) {
|
|
41
41
|
const { aunPath: defaultAunPath } = await import('../../paths.js');
|
|
42
|
-
const { loadEvolclawConfig } = await import('../../
|
|
42
|
+
const { loadEvolclawConfig } = await import('../../config-store.js');
|
|
43
43
|
const { AIDStore } = await import('@agentunion/fastaun');
|
|
44
44
|
const aunPath = opts.aunPath ?? defaultAunPath();
|
|
45
45
|
const encryptionSeed = loadEvolclawConfig().aun?.encryptionSeed
|
package/dist/aun/outbox.js
CHANGED
|
@@ -59,10 +59,14 @@ export function enqueue(aid, opts) {
|
|
|
59
59
|
aid,
|
|
60
60
|
channelId: opts.channelId,
|
|
61
61
|
type: opts.type,
|
|
62
|
+
contentKind: opts.contentKind,
|
|
63
|
+
payload: opts.payload,
|
|
62
64
|
text: opts.text,
|
|
63
65
|
filePath: opts.filePath,
|
|
66
|
+
logText: opts.logText,
|
|
64
67
|
context: opts.context,
|
|
65
68
|
ttl: opts.ttl ?? DEFAULT_TTL,
|
|
69
|
+
postSend: opts.postSend,
|
|
66
70
|
};
|
|
67
71
|
const dir = outboxDir();
|
|
68
72
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -97,6 +101,7 @@ export async function drain(aid, sender) {
|
|
|
97
101
|
const entries = readEntries(aid);
|
|
98
102
|
if (entries.length === 0)
|
|
99
103
|
return { sent: 0, expired: 0, failed: 0 };
|
|
104
|
+
const drainedIds = new Set(entries.map(e => e.id));
|
|
100
105
|
let sent = 0;
|
|
101
106
|
let expired = 0;
|
|
102
107
|
let failed = 0;
|
|
@@ -107,21 +112,28 @@ export async function drain(aid, sender) {
|
|
|
107
112
|
continue;
|
|
108
113
|
}
|
|
109
114
|
try {
|
|
115
|
+
entry.attempts = (entry.attempts ?? 0) + 1;
|
|
110
116
|
const ok = await sender(entry);
|
|
111
117
|
if (ok) {
|
|
112
118
|
sent++;
|
|
113
119
|
}
|
|
114
120
|
else {
|
|
115
121
|
failed++;
|
|
122
|
+
entry.lastError = 'sender returned false';
|
|
116
123
|
remaining.push(entry);
|
|
117
124
|
}
|
|
118
125
|
}
|
|
119
|
-
catch {
|
|
126
|
+
catch (e) {
|
|
120
127
|
failed++;
|
|
128
|
+
entry.lastError = e instanceof Error ? e.message : String(e);
|
|
121
129
|
remaining.push(entry);
|
|
122
130
|
}
|
|
123
131
|
}
|
|
124
|
-
|
|
132
|
+
const current = readEntries(aid);
|
|
133
|
+
const currentIds = new Set(current.map(e => e.id));
|
|
134
|
+
const retainedNewEntries = current.filter(e => !drainedIds.has(e.id));
|
|
135
|
+
const retainedFailedEntries = remaining.filter(e => currentIds.has(e.id));
|
|
136
|
+
writeEntries(aid, [...retainedFailedEntries, ...retainedNewEntries]);
|
|
125
137
|
return { sent, expired, failed };
|
|
126
138
|
}
|
|
127
139
|
export function hasPending(aid) {
|
|
@@ -11,7 +11,7 @@ export async function storageDownload(aid, url, localPath, opts) {
|
|
|
11
11
|
const ownerAid = cleaned.slice(0, slashIdx);
|
|
12
12
|
const objectKey = cleaned.slice(slashIdx + 1);
|
|
13
13
|
const ticketResult = await rpcCall(aid, 'storage.create_download_ticket', {
|
|
14
|
-
|
|
14
|
+
owner_aid: ownerAid,
|
|
15
15
|
object_key: objectKey,
|
|
16
16
|
}, { aunPath: opts?.aunPath });
|
|
17
17
|
if (!ticketResult.ok) {
|
|
@@ -27,9 +27,21 @@ export async function storageUpload(aid, localFile, remotePath, opts) {
|
|
|
27
27
|
const completeResult = await rpcCall(aid, 'storage.complete_upload', {
|
|
28
28
|
object_key: remotePath,
|
|
29
29
|
sha256,
|
|
30
|
+
is_private: !(opts?.isPublic),
|
|
30
31
|
}, { aunPath: opts?.aunPath });
|
|
31
32
|
if (!completeResult.ok) {
|
|
32
33
|
return { ok: false, objectKey: remotePath, error: JSON.stringify(completeResult.error) };
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
// 公开上传时获取可访问的 URL
|
|
36
|
+
let publicUrl;
|
|
37
|
+
if (opts?.isPublic) {
|
|
38
|
+
const ticketResult = await rpcCall(aid, 'storage.create_download_ticket', {
|
|
39
|
+
object_key: remotePath,
|
|
40
|
+
expire_in_seconds: 86400 * 30, // 30天
|
|
41
|
+
}, { aunPath: opts?.aunPath });
|
|
42
|
+
if (ticketResult.ok) {
|
|
43
|
+
publicUrl = `https://${aid}/storage/${remotePath}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { ok: true, objectKey: remotePath, publicUrl };
|
|
35
47
|
}
|