evolcore 0.0.8 → 0.0.9
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 +24 -0
- package/README.md +37 -3
- package/dist/agents/baseagent.js +111 -19
- package/dist/agents/claude-runner.js +30 -2
- package/dist/agents/codex-app-server-client.js +31 -0
- package/dist/agents/codex-runner.js +3 -0
- package/dist/aun/msg/group.js +9 -9
- package/dist/aun/msg/p2p.js +11 -6
- package/dist/aun/msg/upload.js +43 -29
- package/dist/aun/outbox.js +48 -5
- package/dist/channels/aun.js +199 -50
- package/dist/cli/aun-commands.js +10 -7
- package/dist/cli/daemon-commands.js +19 -4
- package/dist/cli/index.js +11 -1
- package/dist/cli/init.js +103 -4
- package/dist/cli/model.js +5 -5
- package/dist/config/builtin-role-templates.js +4 -3
- package/dist/config/config-field-policy.js +6 -2
- package/dist/config/config-manager.js +48 -11
- package/dist/config/role-schema.js +18 -3
- package/dist/config/role-service.js +3 -3
- package/dist/config/role-store.js +4 -3
- package/dist/config-store.js +4 -0
- package/dist/core/auth/operation-authorizer.js +3 -1
- package/dist/core/bootstrap-service.js +0 -12
- package/dist/core/channel-loader.js +5 -1
- package/dist/core/command/command-handler.js +1 -1
- package/dist/core/command/evol-menu-version-gate.js +3 -2
- package/dist/core/command/menu-handler.js +33 -22
- package/dist/core/command/menu-protocol.js +7 -4
- package/dist/core/command/slash-handler.js +4 -4
- package/dist/core/inference/text-inference.js +18 -5
- package/dist/core/message/message-bridge.js +17 -6
- package/dist/core/message/response-engine.js +22 -3
- package/dist/core/model/config-scope.js +3 -3
- package/dist/core/permission/tool-policy.js +18 -0
- package/dist/index.js +43 -26
- package/dist/ipc.js +1 -1
- package/dist/product.js +1 -0
- package/dist/utils/autostart.js +27 -0
- package/dist/utils/ecweb-utils.js +15 -2
- package/dist/utils/macos-autostart.js +179 -0
- package/dist/utils/windows-autostart.js +130 -0
- package/ecagent/dist/agent-loop.d.ts +1 -1
- package/ecagent/dist/agent-loop.js +1 -1
- package/ecagent/dist/agent.d.ts +1 -1
- package/ecagent/dist/agent.js +1 -1
- package/ecagent/dist/harness/agent-harness.d.ts +1 -1
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts +1 -1
- package/ecagent/dist/harness/compaction/compaction.d.ts +1 -1
- package/ecagent/dist/harness/compaction/utils.d.ts +1 -1
- package/ecagent/dist/harness/messages.d.ts +1 -1
- package/ecagent/dist/harness/session/session.d.ts +1 -1
- package/ecagent/dist/harness/types.d.ts +1 -1
- package/ecagent/dist/proxy.d.ts +1 -1
- package/ecagent/dist/proxy.js +1 -1
- package/ecagent/dist/types.d.ts +1 -1
- package/kits/migrations/migrate-role-config-v5.mjs +27 -2
- package/kits/schemas/agent-config.schema.10.json +19 -1
- package/kits/schemas/daemon.schema.4.json +4 -0
- package/kits/schemas/defaults.schema.4.json +15 -1
- package/kits/schemas/relation-config.schema.8.json +22 -1
- package/kits/schemas/role-config.schema.1.json +2 -2
- package/package.json +2 -4
- package/ecagent/dist/agent-loop.d.ts.map +0 -1
- package/ecagent/dist/agent-loop.js.map +0 -1
- package/ecagent/dist/agent.d.ts.map +0 -1
- package/ecagent/dist/agent.js.map +0 -1
- package/ecagent/dist/harness/agent-harness.d.ts.map +0 -1
- package/ecagent/dist/harness/agent-harness.js.map +0 -1
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +0 -1
- package/ecagent/dist/harness/compaction/branch-summarization.js.map +0 -1
- package/ecagent/dist/harness/compaction/compaction.d.ts.map +0 -1
- package/ecagent/dist/harness/compaction/compaction.js.map +0 -1
- package/ecagent/dist/harness/compaction/utils.d.ts.map +0 -1
- package/ecagent/dist/harness/compaction/utils.js.map +0 -1
- package/ecagent/dist/harness/env/nodejs.d.ts.map +0 -1
- package/ecagent/dist/harness/env/nodejs.js.map +0 -1
- package/ecagent/dist/harness/messages.d.ts.map +0 -1
- package/ecagent/dist/harness/messages.js.map +0 -1
- package/ecagent/dist/harness/prompt-templates.d.ts.map +0 -1
- package/ecagent/dist/harness/prompt-templates.js.map +0 -1
- package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +0 -1
- package/ecagent/dist/harness/session/jsonl-repo.js.map +0 -1
- package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +0 -1
- package/ecagent/dist/harness/session/jsonl-storage.js.map +0 -1
- package/ecagent/dist/harness/session/memory-repo.d.ts.map +0 -1
- package/ecagent/dist/harness/session/memory-repo.js.map +0 -1
- package/ecagent/dist/harness/session/memory-storage.d.ts.map +0 -1
- package/ecagent/dist/harness/session/memory-storage.js.map +0 -1
- package/ecagent/dist/harness/session/repo-utils.d.ts.map +0 -1
- package/ecagent/dist/harness/session/repo-utils.js.map +0 -1
- package/ecagent/dist/harness/session/session.d.ts.map +0 -1
- package/ecagent/dist/harness/session/session.js.map +0 -1
- package/ecagent/dist/harness/session/uuid.d.ts.map +0 -1
- package/ecagent/dist/harness/session/uuid.js.map +0 -1
- package/ecagent/dist/harness/skills.d.ts.map +0 -1
- package/ecagent/dist/harness/skills.js.map +0 -1
- package/ecagent/dist/harness/system-prompt.d.ts.map +0 -1
- package/ecagent/dist/harness/system-prompt.js.map +0 -1
- package/ecagent/dist/harness/types.d.ts.map +0 -1
- package/ecagent/dist/harness/types.js.map +0 -1
- package/ecagent/dist/harness/utils/shell-output.d.ts.map +0 -1
- package/ecagent/dist/harness/utils/shell-output.js.map +0 -1
- package/ecagent/dist/harness/utils/truncate.d.ts.map +0 -1
- package/ecagent/dist/harness/utils/truncate.js.map +0 -1
- package/ecagent/dist/index.d.ts.map +0 -1
- package/ecagent/dist/index.js.map +0 -1
- package/ecagent/dist/node.d.ts.map +0 -1
- package/ecagent/dist/node.js.map +0 -1
- package/ecagent/dist/proxy.d.ts.map +0 -1
- package/ecagent/dist/proxy.js.map +0 -1
- package/ecagent/dist/runtime/api/lazy.d.ts.map +0 -1
- package/ecagent/dist/runtime/api/lazy.js.map +0 -1
- package/ecagent/dist/runtime/api/pi-messages.d.ts.map +0 -1
- package/ecagent/dist/runtime/api/pi-messages.js.map +0 -1
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +0 -1
- package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +0 -1
- package/ecagent/dist/runtime/auth/context.d.ts.map +0 -1
- package/ecagent/dist/runtime/auth/context.js.map +0 -1
- package/ecagent/dist/runtime/auth/credential-store.d.ts.map +0 -1
- package/ecagent/dist/runtime/auth/credential-store.js.map +0 -1
- package/ecagent/dist/runtime/auth/helpers.d.ts.map +0 -1
- package/ecagent/dist/runtime/auth/helpers.js.map +0 -1
- package/ecagent/dist/runtime/auth/resolve.d.ts.map +0 -1
- package/ecagent/dist/runtime/auth/resolve.js.map +0 -1
- package/ecagent/dist/runtime/auth/types.d.ts.map +0 -1
- package/ecagent/dist/runtime/auth/types.js.map +0 -1
- package/ecagent/dist/runtime/compat.d.ts.map +0 -1
- package/ecagent/dist/runtime/compat.js.map +0 -1
- package/ecagent/dist/runtime/index.d.ts.map +0 -1
- package/ecagent/dist/runtime/index.js.map +0 -1
- package/ecagent/dist/runtime/models.d.ts.map +0 -1
- package/ecagent/dist/runtime/models.js.map +0 -1
- package/ecagent/dist/runtime/oauth.d.ts.map +0 -1
- package/ecagent/dist/runtime/oauth.js.map +0 -1
- package/ecagent/dist/runtime/providers/faux.d.ts.map +0 -1
- package/ecagent/dist/runtime/providers/faux.js.map +0 -1
- package/ecagent/dist/runtime/types.d.ts.map +0 -1
- package/ecagent/dist/runtime/types.js.map +0 -1
- package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/diagnostics.js.map +0 -1
- package/ecagent/dist/runtime/utils/event-stream.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/event-stream.js.map +0 -1
- package/ecagent/dist/runtime/utils/headers.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/headers.js.map +0 -1
- package/ecagent/dist/runtime/utils/json-parse.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/json-parse.js.map +0 -1
- package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/oauth/types.js.map +0 -1
- package/ecagent/dist/runtime/utils/overflow.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/overflow.js.map +0 -1
- package/ecagent/dist/runtime/utils/provider-env.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/provider-env.js.map +0 -1
- package/ecagent/dist/runtime/utils/retry.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/retry.js.map +0 -1
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/typebox-helpers.js.map +0 -1
- package/ecagent/dist/runtime/utils/validation.d.ts.map +0 -1
- package/ecagent/dist/runtime/utils/validation.js.map +0 -1
- package/ecagent/dist/types.d.ts.map +0 -1
- package/ecagent/dist/types.js.map +0 -1
- package/ecagent/package.json +0 -93
- package/ecagent/src/agent-loop.ts +0 -792
- package/ecagent/src/agent.ts +0 -575
- package/ecagent/src/harness/agent-harness.ts +0 -1029
- package/ecagent/src/harness/compaction/branch-summarization.ts +0 -261
- package/ecagent/src/harness/compaction/compaction.ts +0 -753
- package/ecagent/src/harness/compaction/utils.ts +0 -144
- package/ecagent/src/harness/env/nodejs.ts +0 -569
- package/ecagent/src/harness/messages.ts +0 -164
- package/ecagent/src/harness/prompt-templates.ts +0 -267
- package/ecagent/src/harness/session/jsonl-repo.ts +0 -179
- package/ecagent/src/harness/session/jsonl-storage.ts +0 -314
- package/ecagent/src/harness/session/memory-repo.ts +0 -50
- package/ecagent/src/harness/session/memory-storage.ts +0 -133
- package/ecagent/src/harness/session/repo-utils.ts +0 -51
- package/ecagent/src/harness/session/session.ts +0 -338
- package/ecagent/src/harness/session/uuid.ts +0 -54
- package/ecagent/src/harness/skills.ts +0 -375
- package/ecagent/src/harness/system-prompt.ts +0 -34
- package/ecagent/src/harness/types.ts +0 -838
- package/ecagent/src/harness/utils/shell-output.ts +0 -135
- package/ecagent/src/harness/utils/truncate.ts +0 -344
- package/ecagent/src/index.ts +0 -46
- package/ecagent/src/node.ts +0 -2
- package/ecagent/src/proxy.ts +0 -367
- package/ecagent/src/runtime/api/lazy.ts +0 -70
- package/ecagent/src/runtime/api/pi-messages.lazy.ts +0 -4
- package/ecagent/src/runtime/api/pi-messages.ts +0 -436
- package/ecagent/src/runtime/auth/context.ts +0 -45
- package/ecagent/src/runtime/auth/credential-store.ts +0 -47
- package/ecagent/src/runtime/auth/helpers.ts +0 -46
- package/ecagent/src/runtime/auth/resolve.ts +0 -141
- package/ecagent/src/runtime/auth/types.ts +0 -182
- package/ecagent/src/runtime/compat.ts +0 -158
- package/ecagent/src/runtime/index.ts +0 -31
- package/ecagent/src/runtime/models.ts +0 -452
- package/ecagent/src/runtime/oauth.ts +0 -1
- package/ecagent/src/runtime/providers/faux.ts +0 -538
- package/ecagent/src/runtime/types.ts +0 -718
- package/ecagent/src/runtime/utils/diagnostics.ts +0 -45
- package/ecagent/src/runtime/utils/event-stream.ts +0 -88
- package/ecagent/src/runtime/utils/headers.ts +0 -18
- package/ecagent/src/runtime/utils/json-parse.ts +0 -124
- package/ecagent/src/runtime/utils/oauth/types.ts +0 -79
- package/ecagent/src/runtime/utils/overflow.ts +0 -165
- package/ecagent/src/runtime/utils/provider-env.ts +0 -52
- package/ecagent/src/runtime/utils/retry.ts +0 -101
- package/ecagent/src/runtime/utils/typebox-helpers.ts +0 -24
- package/ecagent/src/runtime/utils/validation.ts +0 -310
- package/ecagent/src/types.ts +0 -430
- package/ecagent/tsconfig.build.json +0 -32
|
@@ -27,9 +27,11 @@ export function showActivitiesPolicy(mode, chatType, _identity) {
|
|
|
27
27
|
// ── ChannelLoader ──────────────────────────────────────────────────────────
|
|
28
28
|
export class ChannelLoader {
|
|
29
29
|
processDebug;
|
|
30
|
+
aunDefaultEncrypt;
|
|
30
31
|
plugins = new Map();
|
|
31
|
-
constructor(processDebug) {
|
|
32
|
+
constructor(processDebug, aunDefaultEncrypt) {
|
|
32
33
|
this.processDebug = processDebug;
|
|
34
|
+
this.aunDefaultEncrypt = aunDefaultEncrypt;
|
|
33
35
|
}
|
|
34
36
|
register(plugin) {
|
|
35
37
|
if (this.plugins.has(plugin.name)) {
|
|
@@ -51,6 +53,7 @@ export class ChannelLoader {
|
|
|
51
53
|
agentName: agent.aid,
|
|
52
54
|
defaultProjectPath: agent.config.projects?.defaultPath ?? process.cwd(),
|
|
53
55
|
debug: this.processDebug,
|
|
56
|
+
aunDefaultEncrypt: this.aunDefaultEncrypt,
|
|
54
57
|
};
|
|
55
58
|
// Build the full list of config instances to create.
|
|
56
59
|
// AUN is synthesised from agent.aid; any explicit aun entry in channels[] is skipped.
|
|
@@ -266,6 +269,7 @@ export function buildReloadHooks(deps) {
|
|
|
266
269
|
agentName: agent.aid ?? agent.config?.aid,
|
|
267
270
|
defaultProjectPath: agent.config?.projects?.defaultPath ?? process.cwd(),
|
|
268
271
|
debug: channelLoader.processDebug,
|
|
272
|
+
aunDefaultEncrypt: channelLoader.aunDefaultEncrypt,
|
|
269
273
|
};
|
|
270
274
|
const plugin = channelLoader.getPlugin(cfgInst.type);
|
|
271
275
|
if (!plugin)
|
|
@@ -372,7 +372,7 @@ export class CommandHandler {
|
|
|
372
372
|
const effortDecision = validateRuntimeStringFieldOverride({
|
|
373
373
|
selfAid: definition.agentAid,
|
|
374
374
|
role,
|
|
375
|
-
field: `baseagents.${base}
|
|
375
|
+
field: `baseagents.${base}.effort`,
|
|
376
376
|
value: definition.execution.effort,
|
|
377
377
|
});
|
|
378
378
|
if (!effortDecision.ok)
|
|
@@ -30,9 +30,10 @@ export function isEvolMenuVersionGateEnabled() {
|
|
|
30
30
|
export function isAunMenuTokenRequired() {
|
|
31
31
|
return loadDaemonConfig().aun?.menuTokenRequired === true;
|
|
32
32
|
}
|
|
33
|
-
export function evolMenuResponseTransportMetadata(
|
|
33
|
+
export function evolMenuResponseTransportMetadata() {
|
|
34
34
|
return {
|
|
35
|
-
|
|
35
|
+
// Clear inherited request state so AUNChannel applies daemon aun.defaultEncrypt.
|
|
36
|
+
encrypted: undefined,
|
|
36
37
|
protectedHeaders: { ec_version: readInstalledEvolcoreVersion() },
|
|
37
38
|
};
|
|
38
39
|
}
|
|
@@ -9,6 +9,7 @@ import { resolvePaths, getPackageRoot, daemonControlDir } from '../../paths.js';
|
|
|
9
9
|
import { buildEnvelope } from '../message/message-utils.js';
|
|
10
10
|
import path from 'path';
|
|
11
11
|
import fs from 'fs';
|
|
12
|
+
import os from 'os';
|
|
12
13
|
import crypto from 'crypto';
|
|
13
14
|
import { execFileSync } from 'child_process';
|
|
14
15
|
import { CronExpressionParser } from 'cron-parser';
|
|
@@ -452,9 +453,6 @@ function menuConfigSource(fieldPath, sel) {
|
|
|
452
453
|
return null;
|
|
453
454
|
}
|
|
454
455
|
function menuModelConfigFieldPath(target) {
|
|
455
|
-
if (target.field === 'effort' && target.baseagent === 'codex') {
|
|
456
|
-
return `baseagents.${target.baseagent}.reasoning`;
|
|
457
|
-
}
|
|
458
456
|
return target.fieldPath;
|
|
459
457
|
}
|
|
460
458
|
function menuChatmodeScope(args) {
|
|
@@ -1881,7 +1879,6 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
|
|
|
1881
1879
|
const target = resolveCapabilityTarget.call(this, { channel, args, session, evolagent, fromControlChannel });
|
|
1882
1880
|
if ('error' in target)
|
|
1883
1881
|
return target;
|
|
1884
|
-
const identity = this.sessionManager.resolveIdentity(channel, userId, ...menuIdentityArgs(session));
|
|
1885
1882
|
const data = queryCapabilityTypes(target.ctx, target.config, type);
|
|
1886
1883
|
return { data: sanitizeCapabilityQueryForRole(data, identity.role) };
|
|
1887
1884
|
}
|
|
@@ -2179,11 +2176,13 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
|
|
|
2179
2176
|
if (!subject.isDaemonOwner) {
|
|
2180
2177
|
return { error: '操作需要 owner 权限', code: 'FORBIDDEN' };
|
|
2181
2178
|
}
|
|
2182
|
-
const owningAgent = this.getOwningAgent(channel);
|
|
2183
2179
|
const data = {
|
|
2184
2180
|
aid: loadDaemonConfig().aid ?? null,
|
|
2185
2181
|
pid: process.pid,
|
|
2186
|
-
|
|
2182
|
+
nodejs: process.version,
|
|
2183
|
+
hostname: os.hostname(),
|
|
2184
|
+
platform: process.platform,
|
|
2185
|
+
arch: process.arch,
|
|
2187
2186
|
uptime: Math.floor(process.uptime()),
|
|
2188
2187
|
};
|
|
2189
2188
|
try {
|
|
@@ -2204,14 +2203,6 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
|
|
|
2204
2203
|
const ecwebPkg = resolveGlobalPkg(WEB_PACKAGE_NAME);
|
|
2205
2204
|
if (ecwebPkg?.version)
|
|
2206
2205
|
data.ecwebVersion = ecwebPkg.version;
|
|
2207
|
-
const channels = owningAgent?.channelInstanceNames?.() ?? [];
|
|
2208
|
-
if (channels.length) {
|
|
2209
|
-
// 将 channelKey 字符串(如 "feishu#aid#name")解析为对象 { type, instName }
|
|
2210
|
-
data.channels = channels.map((key) => {
|
|
2211
|
-
const parts = key.split('#');
|
|
2212
|
-
return { type: parts[0], instName: parts[2] || parts[0] };
|
|
2213
|
-
});
|
|
2214
|
-
}
|
|
2215
2206
|
// 收集主机级可用的所有 baseagent 类型(检测已安装的 CLI + 版本)
|
|
2216
2207
|
const baseagents = [];
|
|
2217
2208
|
for (const cmd of ['claude', 'gemini', 'codex']) {
|
|
@@ -2260,7 +2251,9 @@ export async function execMenuUpdate(cmd, value, channel, channelId, userId, ove
|
|
|
2260
2251
|
if (cmdBase === '/perm') {
|
|
2261
2252
|
return { error: 'permissionMode 只能通过角色策略编辑器修改', code: 'ROLE_POLICY_MANAGED' };
|
|
2262
2253
|
}
|
|
2263
|
-
|
|
2254
|
+
// JSON Menu 入口在 validateMenuRequest 中要求 activity 显式 scope;保留
|
|
2255
|
+
// 底层 execMenuUpdate 的旧默认行为,兼容旧版 slash/内部直调调用方。
|
|
2256
|
+
const scopeError = validateConfigWriteScope(cmdBase, args, { includeActivity: false });
|
|
2264
2257
|
if (scopeError)
|
|
2265
2258
|
return { error: scopeError.message, code: scopeError.code };
|
|
2266
2259
|
args = withoutLegacySessionConfigArgs(args);
|
|
@@ -3517,26 +3510,43 @@ const SYSTEM_CONTROL_NAME_MAP = {
|
|
|
3517
3510
|
config: '/config', capability: '/capability', role: '/role',
|
|
3518
3511
|
group: '/group', connect: '/connect',
|
|
3519
3512
|
};
|
|
3513
|
+
function menuCommandToken(cmd) {
|
|
3514
|
+
if (typeof cmd !== 'string')
|
|
3515
|
+
return undefined;
|
|
3516
|
+
return cmd.trim().split(/\s+/, 1)[0] || undefined;
|
|
3517
|
+
}
|
|
3520
3518
|
function isProcessLevelMenu(name, cmd) {
|
|
3519
|
+
const cmdToken = menuCommandToken(cmd);
|
|
3521
3520
|
return name === 'system' || name === 'agent' || name === 'gateway' || name === 'config'
|
|
3522
|
-
||
|
|
3521
|
+
|| cmdToken === '/system' || cmdToken === '/agent' || cmdToken === '/gateway' || cmdToken === '/config';
|
|
3523
3522
|
}
|
|
3524
3523
|
async function execMenuForSystemControl(payload, context) {
|
|
3525
3524
|
const id = payload?.id ?? '';
|
|
3526
3525
|
const name = payload?.name;
|
|
3527
|
-
|
|
3526
|
+
const compatCmd = menuCommandToken(payload?.cmd);
|
|
3527
|
+
// `menu.query(/file)` returns file metadata and is authorized as
|
|
3528
|
+
// `file.fetch`, while `menu.action(file/fetch)` sends the file. Neither
|
|
3529
|
+
// operation is available through Host/control: file operations must be
|
|
3530
|
+
// addressed to the current Agent AID so the Agent project boundary applies.
|
|
3531
|
+
const isFileFetch = (payload?.type === 'menu.query'
|
|
3532
|
+
|| (payload?.type === 'menu.action' && payload?.action === 'fetch'))
|
|
3533
|
+
&& (name === 'file' || compatCmd === '/file');
|
|
3534
|
+
if (isFileFetch) {
|
|
3535
|
+
return ecwebErr(id, name, 'NOT_SUPPORTED', 'Host/control 不支持 file.fetch,请通过目标 Agent AID 请求');
|
|
3536
|
+
}
|
|
3537
|
+
if (name === 'cli' || compatCmd === '/cli') {
|
|
3528
3538
|
const message = context.source === 'ecweb'
|
|
3529
3539
|
? 'cli 不在 ECWeb 控制范围'
|
|
3530
3540
|
: 'cli 不在控制 channel 范围';
|
|
3531
3541
|
return { type: 'menu.response', id, name, error: { code: 'NOT_SUPPORTED', message } };
|
|
3532
3542
|
}
|
|
3533
3543
|
const isProcessLevel = isProcessLevelMenu(name, payload?.cmd);
|
|
3534
|
-
const isRoleRequest = name === 'role' ||
|
|
3535
|
-
const isConnectRequest = name === 'connect' ||
|
|
3544
|
+
const isRoleRequest = name === 'role' || compatCmd === '/role';
|
|
3545
|
+
const isConnectRequest = name === 'connect' || compatCmd === '/connect';
|
|
3536
3546
|
const requiresAgentTarget = isRoleRequest || isConnectRequest || [
|
|
3537
3547
|
'observable', 'baseagent', 'model', 'effort', 'trigger', 'capability', 'group',
|
|
3538
3548
|
].includes(name)
|
|
3539
|
-
|| ['/observable', '/baseagent', '/model', '/effort', '/trigger', '/capability', '/group'].includes(
|
|
3549
|
+
|| ['/observable', '/baseagent', '/model', '/effort', '/trigger', '/capability', '/group'].includes(compatCmd ?? '');
|
|
3540
3550
|
const target = isProcessLevel
|
|
3541
3551
|
? { channel: SYSTEM_CONTROL_CHANNEL }
|
|
3542
3552
|
: resolveExternalMenuAgentChannel(this, payload, SYSTEM_CONTROL_CHANNEL, requiresAgentTarget);
|
|
@@ -3635,8 +3645,9 @@ export async function execMenuForControl(payload, peerId) {
|
|
|
3635
3645
|
if (validationError)
|
|
3636
3646
|
return menuFailure({ id, ...(name ? { name } : {}) }, validationError);
|
|
3637
3647
|
const owners = loadDaemonConfig().owners ?? [];
|
|
3638
|
-
const
|
|
3639
|
-
const
|
|
3648
|
+
const compatCmd = menuCommandToken(payload?.cmd);
|
|
3649
|
+
const isRoleRequest = name === 'role' || compatCmd === '/role';
|
|
3650
|
+
const isConnectRequest = name === 'connect' || compatCmd === '/connect';
|
|
3640
3651
|
if (!isRoleRequest && !isConnectRequest && !isProcessLevelOwner(peerId, owners)) {
|
|
3641
3652
|
return menuFailure({ id, ...(name ? { name } : {}) }, { code: 'ROLE_ACCESS_DENIED', message: '控制 channel 操作需要 owner 权限' });
|
|
3642
3653
|
}
|
|
@@ -15,6 +15,7 @@ const EXPLICIT_SCOPE_UPDATE_NAMES = new Set([
|
|
|
15
15
|
'mentionmode',
|
|
16
16
|
'group',
|
|
17
17
|
'permission',
|
|
18
|
+
'activity',
|
|
18
19
|
]);
|
|
19
20
|
const EXPLICIT_SCOPE_UPDATE_COMMANDS = new Set([
|
|
20
21
|
'/model',
|
|
@@ -24,18 +25,20 @@ const EXPLICIT_SCOPE_UPDATE_COMMANDS = new Set([
|
|
|
24
25
|
'/mentionmode',
|
|
25
26
|
'/group',
|
|
26
27
|
'/perm',
|
|
28
|
+
'/activity',
|
|
27
29
|
]);
|
|
28
30
|
function firstCommandToken(value) {
|
|
29
31
|
if (typeof value !== 'string')
|
|
30
32
|
return undefined;
|
|
31
33
|
return value.trim().split(/\s+/, 1)[0] || undefined;
|
|
32
34
|
}
|
|
33
|
-
function requiresExplicitConfigWriteScope(nameOrCmd) {
|
|
35
|
+
function requiresExplicitConfigWriteScope(nameOrCmd, includeActivity = true) {
|
|
34
36
|
const token = firstCommandToken(nameOrCmd);
|
|
35
|
-
return !!token && (EXPLICIT_SCOPE_UPDATE_NAMES.has(token) || EXPLICIT_SCOPE_UPDATE_COMMANDS.has(token))
|
|
37
|
+
return !!token && (EXPLICIT_SCOPE_UPDATE_NAMES.has(token) || EXPLICIT_SCOPE_UPDATE_COMMANDS.has(token))
|
|
38
|
+
&& (includeActivity || (token !== 'activity' && token !== '/activity'));
|
|
36
39
|
}
|
|
37
|
-
export function validateConfigWriteScope(nameOrCmd, args) {
|
|
38
|
-
if (!requiresExplicitConfigWriteScope(nameOrCmd))
|
|
40
|
+
export function validateConfigWriteScope(nameOrCmd, args, options) {
|
|
41
|
+
if (!requiresExplicitConfigWriteScope(nameOrCmd, options?.includeActivity ?? true))
|
|
39
42
|
return null;
|
|
40
43
|
const rawScope = args?.scope;
|
|
41
44
|
if (rawScope === undefined || rawScope === null || (typeof rawScope === 'string' && rawScope.trim().length === 0)) {
|
|
@@ -1146,7 +1146,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1146
1146
|
}
|
|
1147
1147
|
catch { }
|
|
1148
1148
|
const configuredModel = modelConfig.model;
|
|
1149
|
-
const configuredEffort = modelConfig
|
|
1149
|
+
const configuredEffort = modelConfig.effort;
|
|
1150
1150
|
const rawModels = hasModelSwitcher(modelAgent) ? await modelAgent.listModels() : [];
|
|
1151
1151
|
const models = hasModelSwitcher(modelAgent)
|
|
1152
1152
|
? filterModelsForRole(identity.role, fallbackBaseagent, rawModels, modelAgent.resolveModelId?.bind(modelAgent))
|
|
@@ -1468,7 +1468,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1468
1468
|
}
|
|
1469
1469
|
catch { }
|
|
1470
1470
|
const configuredModel = modelConfig.model;
|
|
1471
|
-
const configuredEffort = modelConfig
|
|
1471
|
+
const configuredEffort = modelConfig.effort;
|
|
1472
1472
|
const currentModel = hasModelSwitcher(effortAgent) ? (configuredModel || effortAgent.getModel()) : effortAgent.name;
|
|
1473
1473
|
const efforts = getAvailableEfforts(effortAgent, currentModel);
|
|
1474
1474
|
const currentEffort = configuredEffort ?? effortAgent.getEffort?.() ?? 'auto';
|
|
@@ -1530,7 +1530,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1530
1530
|
}
|
|
1531
1531
|
catch { }
|
|
1532
1532
|
const configuredModel = modelConfig.model;
|
|
1533
|
-
const configuredEffort = modelConfig
|
|
1533
|
+
const configuredEffort = modelConfig.effort;
|
|
1534
1534
|
const currentModel = hasModelSwitcher(effortAgent) ? (configuredModel || effortAgent.getModel()) : effortAgent.name;
|
|
1535
1535
|
const efforts = getAvailableEfforts(effortAgent, currentModel);
|
|
1536
1536
|
const currentEffort = configuredEffort ?? effortAgent.getEffort?.() ?? 'auto';
|
|
@@ -2210,7 +2210,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2210
2210
|
}
|
|
2211
2211
|
catch { }
|
|
2212
2212
|
const backendModel = modelConfig.model || newRunner.getModel?.() || newAgent?.model;
|
|
2213
|
-
const backendEffort = modelConfig
|
|
2213
|
+
const backendEffort = modelConfig.effort
|
|
2214
2214
|
?? newRunner.getEffort?.()
|
|
2215
2215
|
?? newAgent?.effort;
|
|
2216
2216
|
const backendBits = [newBaseagent, backendModel, backendEffort].filter(Boolean).join(' · ');
|
|
@@ -3,8 +3,20 @@ function apiEndpoint(baseUrl, resource) {
|
|
|
3
3
|
const configured = baseUrl?.trim();
|
|
4
4
|
if (!configured)
|
|
5
5
|
throw new Error('Direct text inference baseUrl is not configured');
|
|
6
|
-
const
|
|
7
|
-
|
|
6
|
+
const parsed = new URL(configured);
|
|
7
|
+
const pathname = parsed.pathname.replace(/\/+$/, '');
|
|
8
|
+
parsed.pathname = pathname.endsWith('/v1')
|
|
9
|
+
? `${pathname}/${resource}`
|
|
10
|
+
: `${pathname}/v1/${resource}`;
|
|
11
|
+
return parsed.toString();
|
|
12
|
+
}
|
|
13
|
+
function withQueryParams(url, queryParams) {
|
|
14
|
+
if (!queryParams || Object.keys(queryParams).length === 0)
|
|
15
|
+
return url;
|
|
16
|
+
const parsed = new URL(url);
|
|
17
|
+
for (const [name, value] of Object.entries(queryParams))
|
|
18
|
+
parsed.searchParams.set(name, value);
|
|
19
|
+
return parsed.toString();
|
|
8
20
|
}
|
|
9
21
|
async function parseError(response) {
|
|
10
22
|
let raw = '';
|
|
@@ -28,10 +40,10 @@ export class AnthropicTextInferenceProvider {
|
|
|
28
40
|
this.config = config;
|
|
29
41
|
}
|
|
30
42
|
async completeText(request) {
|
|
31
|
-
const response = await fetch(apiEndpoint(this.config.baseUrl, 'messages'), {
|
|
43
|
+
const response = await fetch(withQueryParams(apiEndpoint(this.config.baseUrl, 'messages'), this.config.queryParams), {
|
|
32
44
|
method: 'POST',
|
|
33
45
|
signal: request.signal,
|
|
34
|
-
headers: this.headers(),
|
|
46
|
+
headers: { ...this.headers(), ...this.config.headers },
|
|
35
47
|
body: JSON.stringify({
|
|
36
48
|
model: request.model,
|
|
37
49
|
max_tokens: 256,
|
|
@@ -69,12 +81,13 @@ export class OpenAITextInferenceProvider {
|
|
|
69
81
|
this.config = config;
|
|
70
82
|
}
|
|
71
83
|
async completeText(request) {
|
|
72
|
-
const response = await fetch(apiEndpoint(this.config.baseUrl, 'responses'), {
|
|
84
|
+
const response = await fetch(withQueryParams(apiEndpoint(this.config.baseUrl, 'responses'), this.config.queryParams), {
|
|
73
85
|
method: 'POST',
|
|
74
86
|
signal: request.signal,
|
|
75
87
|
headers: {
|
|
76
88
|
'Content-Type': 'application/json',
|
|
77
89
|
Authorization: `Bearer ${this.config.apiKey}`,
|
|
90
|
+
...this.config.headers,
|
|
78
91
|
},
|
|
79
92
|
body: JSON.stringify({
|
|
80
93
|
model: request.model,
|
|
@@ -627,6 +627,7 @@ export class MessageBridge {
|
|
|
627
627
|
const menuControl = resolvedChannelType === 'aun'
|
|
628
628
|
? parseMenuControl(content)
|
|
629
629
|
: { isMenu: false };
|
|
630
|
+
let menuResponseWarning;
|
|
630
631
|
if (menuControl.isMenu) {
|
|
631
632
|
this.logMenuInbound(channelName, msg, menuControl);
|
|
632
633
|
if (!hasValidMenuId(menuControl)) {
|
|
@@ -649,7 +650,7 @@ export class MessageBridge {
|
|
|
649
650
|
await this.sendMenuResponse(adapter, channelName, msg, menuFailure(header, {
|
|
650
651
|
code: 'MENU_TOKEN_ENCRYPTION_REQUIRED',
|
|
651
652
|
message: 'Menu 请求必须使用 E2EE',
|
|
652
|
-
})
|
|
653
|
+
}));
|
|
653
654
|
return;
|
|
654
655
|
}
|
|
655
656
|
if (!isTokenRequest) {
|
|
@@ -666,6 +667,13 @@ export class MessageBridge {
|
|
|
666
667
|
}));
|
|
667
668
|
return;
|
|
668
669
|
}
|
|
670
|
+
if (!menuTokenRequired && tokenSupplied && !tokenValid) {
|
|
671
|
+
this.logMenuDiagnostic('token-invalid-optional', channelName, msg, menuControl, 'MENU_TOKEN_INVALID');
|
|
672
|
+
menuResponseWarning = {
|
|
673
|
+
code: 'MENU_TOKEN_INVALID',
|
|
674
|
+
message: 'Menu token 无效,请重新申请',
|
|
675
|
+
};
|
|
676
|
+
}
|
|
669
677
|
}
|
|
670
678
|
const validationError = validateMenuRequest(menuControl.request);
|
|
671
679
|
if (validationError) {
|
|
@@ -712,7 +720,7 @@ export class MessageBridge {
|
|
|
712
720
|
});
|
|
713
721
|
const identity = authSubject.identity;
|
|
714
722
|
if (menuControl.isMenu) {
|
|
715
|
-
await this.handleMenuControl(menuControl, channelName, resolvedChannelType, msg, adapter, authSubject);
|
|
723
|
+
await this.handleMenuControl(menuControl, channelName, resolvedChannelType, msg, adapter, authSubject, menuResponseWarning);
|
|
716
724
|
return;
|
|
717
725
|
}
|
|
718
726
|
// 普通消息保留原始日志;控制 payload 使用脱敏元数据日志。
|
|
@@ -1074,7 +1082,7 @@ export class MessageBridge {
|
|
|
1074
1082
|
throw { code: 'NOT_SUPPORTED', message: `Unsupported menu name: ${name}` };
|
|
1075
1083
|
return mapped;
|
|
1076
1084
|
}
|
|
1077
|
-
async handleMenuControl(parsed, channel, channelType, msg, adapter, authSubject) {
|
|
1085
|
+
async handleMenuControl(parsed, channel, channelType, msg, adapter, authSubject, responseWarning) {
|
|
1078
1086
|
if (!hasValidMenuId(parsed))
|
|
1079
1087
|
return;
|
|
1080
1088
|
const header = { id: parsed.id, ...(parsed.name?.trim() ? { name: parsed.name } : {}) };
|
|
@@ -1122,7 +1130,10 @@ export class MessageBridge {
|
|
|
1122
1130
|
}
|
|
1123
1131
|
if (deduped.replayed)
|
|
1124
1132
|
this.logMenuDiagnostic('request-replay', channel, msg, parsed);
|
|
1125
|
-
|
|
1133
|
+
const response = responseWarning && 'data' in deduped.value
|
|
1134
|
+
? { ...deduped.value, warning: responseWarning }
|
|
1135
|
+
: deduped.value;
|
|
1136
|
+
await this.sendMenuResponse(adapter, channel, msg, response);
|
|
1126
1137
|
const deferredEffect = afterResponse;
|
|
1127
1138
|
if (!deduped.replayed && deferredEffect) {
|
|
1128
1139
|
try {
|
|
@@ -1191,7 +1202,7 @@ export class MessageBridge {
|
|
|
1191
1202
|
return menuFailure(header, normalizeMenuError(error));
|
|
1192
1203
|
}
|
|
1193
1204
|
}
|
|
1194
|
-
async sendMenuResponse(adapter, channel, msg, response
|
|
1205
|
+
async sendMenuResponse(adapter, channel, msg, response) {
|
|
1195
1206
|
if (!adapter?.send) {
|
|
1196
1207
|
this.logMenuDiagnostic('transport-unavailable', channel, msg, {
|
|
1197
1208
|
isMenu: true,
|
|
@@ -1208,7 +1219,7 @@ export class MessageBridge {
|
|
|
1208
1219
|
...(msg.replyContext ?? {}),
|
|
1209
1220
|
metadata: {
|
|
1210
1221
|
...(msg.replyContext?.metadata ?? {}),
|
|
1211
|
-
...evolMenuResponseTransportMetadata(
|
|
1222
|
+
...evolMenuResponseTransportMetadata(),
|
|
1212
1223
|
},
|
|
1213
1224
|
};
|
|
1214
1225
|
const envelope = buildEnvelope({
|
|
@@ -890,6 +890,16 @@ export class ResponseEngine {
|
|
|
890
890
|
return;
|
|
891
891
|
renderer.addNotice(text, severity, subtype, true);
|
|
892
892
|
}
|
|
893
|
+
async cancelStaleRunnerStart(agent, sessionId, streamKey, turnLease, taskId) {
|
|
894
|
+
if (this.turnCoordinator.isCurrent(turnLease))
|
|
895
|
+
return false;
|
|
896
|
+
logger.info(`[ResponseEngine] Stale turn detected after agent.runQuery start; cancelling unconsumed stream: session=${sessionId} task=${taskId}`);
|
|
897
|
+
await agent.interrupt(sessionId).catch(interruptError => {
|
|
898
|
+
logger.warn(`[ResponseEngine] Failed to cancel stale runner start: session=${sessionId} task=${taskId} error=${interruptError instanceof Error ? interruptError.message : String(interruptError)}`);
|
|
899
|
+
});
|
|
900
|
+
agent.cleanupStream(streamKey);
|
|
901
|
+
return true;
|
|
902
|
+
}
|
|
893
903
|
async retryAfterContextRecovery(prompt, opts) {
|
|
894
904
|
const { streamKey, renderer, agent, session, absoluteProjectPath, effectiveSystemPrompt, modelOverride, runtimeEnv, resetTimer, shouldSuppress, proactive, turnLease, } = opts;
|
|
895
905
|
if (!session.agentSessionId || !canCompactAgent(agent)) {
|
|
@@ -911,6 +921,9 @@ export class ResponseEngine {
|
|
|
911
921
|
await this.emitOperationalNotice(renderer, '✅ 压缩完成,继续处理...', 'info', 'compact-retry');
|
|
912
922
|
await renderer.flush();
|
|
913
923
|
const retryStream = await agent.runQuery(session.id, prompt, absoluteProjectPath, session.agentSessionId, undefined, effectiveSystemPrompt, this.sessionManager, modelOverride, runtimeEnv);
|
|
924
|
+
if (await this.cancelStaleRunnerStart(agent, session.id, streamKey, turnLease, turnLease.taskId)) {
|
|
925
|
+
throw new Error('RUNNER_START_SUPERSEDED');
|
|
926
|
+
}
|
|
914
927
|
agent.registerStream(streamKey, retryStream);
|
|
915
928
|
return await this.processEventStream(retryStream, session, agent, renderer, resetTimer, shouldSuppress, proactive, undefined, // 重试分支不调插件钩子
|
|
916
929
|
undefined, turnLease);
|
|
@@ -2331,7 +2344,7 @@ export class ResponseEngine {
|
|
|
2331
2344
|
try {
|
|
2332
2345
|
const selector = { self: selfAid || undefined, peerKey };
|
|
2333
2346
|
const modelResolution = resolveEffectiveFieldWithSource(`baseagents.${normalizedBaseagent.canonical}.model`, selector, { cache: true });
|
|
2334
|
-
const effortResolution = resolveEffectiveFieldWithSource(`baseagents.${normalizedBaseagent.canonical}
|
|
2347
|
+
const effortResolution = resolveEffectiveFieldWithSource(`baseagents.${normalizedBaseagent.canonical}.effort`, selector, { cache: true });
|
|
2335
2348
|
const modelDecision = constrainResolvedModelForRole({
|
|
2336
2349
|
role: peerRole,
|
|
2337
2350
|
baseagent: normalizedBaseagent.canonical,
|
|
@@ -2342,7 +2355,7 @@ export class ResponseEngine {
|
|
|
2342
2355
|
selfAid: selfAid || undefined,
|
|
2343
2356
|
});
|
|
2344
2357
|
const model = modelDecision.model;
|
|
2345
|
-
const effortField = `baseagents.${normalizedBaseagent.canonical}
|
|
2358
|
+
const effortField = `baseagents.${normalizedBaseagent.canonical}.effort`;
|
|
2346
2359
|
const effortDecision = resolveRuntimeStringField({
|
|
2347
2360
|
selfAid: selfAid || undefined,
|
|
2348
2361
|
role: peerRole,
|
|
@@ -2389,7 +2402,7 @@ export class ResponseEngine {
|
|
|
2389
2402
|
effectiveModelSource = triggerModelDecision.constrained ? 'role' : 'trigger';
|
|
2390
2403
|
}
|
|
2391
2404
|
if (triggerEffortOverride) {
|
|
2392
|
-
const effortField = `baseagents.${normalizedBaseagent.canonical}
|
|
2405
|
+
const effortField = `baseagents.${normalizedBaseagent.canonical}.effort`;
|
|
2393
2406
|
const triggerEffortDecision = resolveRuntimeStringField({
|
|
2394
2407
|
selfAid: selfAid || undefined,
|
|
2395
2408
|
role: peerRole,
|
|
@@ -2766,6 +2779,12 @@ export class ResponseEngine {
|
|
|
2766
2779
|
try {
|
|
2767
2780
|
logger.info(`[ResponseEngine] agent.runQuery start: agent=${agent.name} session=${session.id} task=${taskId} attempt=${runAttempt} apiRetries=${retryScheduler.apiRetryAttemptsMade} agentSessionId=${session.agentSessionId ?? 'none'}`);
|
|
2768
2781
|
const stream = await agent.runQuery(session.id, effectivePrompt, absoluteProjectPath, session.agentSessionId, renderResult?.images.length ? renderResult.images : message.images, effectiveSystemPrompt, this.sessionManager, modelOverride, runtimeEnv);
|
|
2782
|
+
// The turn may be superseded while the runner is still creating its
|
|
2783
|
+
// backend query. Replay the interrupt after runQuery resolves, when
|
|
2784
|
+
// every runner is required to have an addressable cancellation handle.
|
|
2785
|
+
if (await this.cancelStaleRunnerStart(agent, session.id, streamKey, turnLease, taskId)) {
|
|
2786
|
+
throw new Error('RUNNER_START_SUPERSEDED');
|
|
2787
|
+
}
|
|
2769
2788
|
agent.registerStream(streamKey, stream);
|
|
2770
2789
|
streamRegistered = true;
|
|
2771
2790
|
if (shouldTimeoutRetryAttempt) {
|
|
@@ -82,9 +82,9 @@ export function activeBaseagent(self) {
|
|
|
82
82
|
catch { /* fall through */ }
|
|
83
83
|
return 'claude';
|
|
84
84
|
}
|
|
85
|
-
/**
|
|
86
|
-
function effortField(
|
|
87
|
-
return
|
|
85
|
+
/** 所有 baseagent 统一使用 effort 表达推理强度。 */
|
|
86
|
+
function effortField(_ba) {
|
|
87
|
+
return 'effort';
|
|
88
88
|
}
|
|
89
89
|
// ── 写:单作用域 ──────────────────────────────────────────────────────
|
|
90
90
|
/** 写入指定作用域。patch 中 undefined 不动;显式 null 删除字段。 */
|
|
@@ -169,6 +169,17 @@ function isOwnerOrAdminRole(role) {
|
|
|
169
169
|
function hasNodeProcessTarget(command) {
|
|
170
170
|
return /\bnode(?:js|\.exe)?\b/i.test(command);
|
|
171
171
|
}
|
|
172
|
+
// 包发布命令:npm/pnpm/yarn/bun publish。
|
|
173
|
+
// 排除 --dry-run(不产生实际发布),保留 --provenance 等真实发布参数。
|
|
174
|
+
function isPackagePublishCommand(parsed) {
|
|
175
|
+
const runners = ['npm', 'pnpm', 'yarn', 'bun', 'npx'];
|
|
176
|
+
if (!runners.includes(parsed.executable))
|
|
177
|
+
return false;
|
|
178
|
+
const words = parsed.args.filter(arg => !arg.startsWith('-')).map(arg => arg.toLowerCase());
|
|
179
|
+
if (words[0] !== 'publish')
|
|
180
|
+
return false;
|
|
181
|
+
return !parsed.args.some(arg => arg === '--dry-run' || arg.startsWith('--dry-run='));
|
|
182
|
+
}
|
|
172
183
|
function classifyHostProcessArgv(argv) {
|
|
173
184
|
const executable = commandName(argv[0]);
|
|
174
185
|
if (['ps', 'pgrep', 'pidof'].includes(executable)) {
|
|
@@ -279,6 +290,13 @@ function classifyStructuredCommand(command, depth = 0) {
|
|
|
279
290
|
matches.push({ kind: 'git-push', reason: 'Git push 会修改远端仓库', approvalScope: 'request' });
|
|
280
291
|
}
|
|
281
292
|
}
|
|
293
|
+
if (isPackagePublishCommand(parsed)) {
|
|
294
|
+
matches.push({
|
|
295
|
+
kind: 'package-publish',
|
|
296
|
+
reason: '发布软件包到公共 registry,发布后无法替换同版本',
|
|
297
|
+
approvalScope: 'all',
|
|
298
|
+
});
|
|
299
|
+
}
|
|
282
300
|
if (['kill', 'pkill', 'killall'].includes(parsed.executable) && hasNodeProcessTarget(parsed.raw)) {
|
|
283
301
|
matches.push({ kind: 'process-kill', reason: '终止 Node.js 运行时进程', approvalScope: 'request' });
|
|
284
302
|
}
|
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ import { EvolAgentRegistry } from './core/evolagent-registry.js';
|
|
|
69
69
|
import { buildReloadHooks } from './core/channel-loader.js';
|
|
70
70
|
import { IpcServer } from './ipc.js';
|
|
71
71
|
import { logger, setLogLevel } from './utils/logger.js';
|
|
72
|
-
import { fetchEcwebPairCode } from './utils/ecweb-utils.js';
|
|
72
|
+
import { ecwebVersionRequirementError, fetchEcwebPairCode } from './utils/ecweb-utils.js';
|
|
73
73
|
import { writeMain, removeAll, isMainWinner, scanInstances } from './utils/instance-registry.js';
|
|
74
74
|
import { detectDuplicates } from './core/evolagent-registry.js';
|
|
75
75
|
import { loadKitManifest, cleanEckDebug, invalidateKitCache } from './eck/kit-renderer.js';
|
|
@@ -369,6 +369,7 @@ async function runBindBootstrapDaemon(daemonCfg) {
|
|
|
369
369
|
channelName: 'control',
|
|
370
370
|
pureIdentity: true,
|
|
371
371
|
gatewayUrl: daemonCfg.aun?.gatewayUrl,
|
|
372
|
+
defaultEncrypt: daemonCfg.aun?.defaultEncrypt,
|
|
372
373
|
aunTrace: daemonCfg.debug?.aunTrace,
|
|
373
374
|
aunSdkLog: daemonCfg.debug?.aunSdkLog,
|
|
374
375
|
});
|
|
@@ -951,7 +952,7 @@ async function main() {
|
|
|
951
952
|
messageCache.cleanupExpired();
|
|
952
953
|
}, 60 * 60 * 1000);
|
|
953
954
|
// 渠道插件系统
|
|
954
|
-
const channelLoader = new ChannelLoader(daemonCfg.debug);
|
|
955
|
+
const channelLoader = new ChannelLoader(daemonCfg.debug, daemonCfg.aun?.defaultEncrypt);
|
|
955
956
|
channelLoader.register(new FeishuChannelPlugin());
|
|
956
957
|
channelLoader.register(new WechatChannelPlugin());
|
|
957
958
|
channelLoader.register(new AUNChannelPlugin());
|
|
@@ -1226,7 +1227,7 @@ async function main() {
|
|
|
1226
1227
|
const effortDecision = validateRuntimeStringFieldOverride({
|
|
1227
1228
|
selfAid: definition.agentAid,
|
|
1228
1229
|
role: actor.role,
|
|
1229
|
-
field: `baseagents.${baseagent}
|
|
1230
|
+
field: `baseagents.${baseagent}.effort`,
|
|
1230
1231
|
value: definition.execution.effort,
|
|
1231
1232
|
});
|
|
1232
1233
|
if (!effortDecision.ok)
|
|
@@ -1454,7 +1455,7 @@ async function main() {
|
|
|
1454
1455
|
originSessionId: originSession.id,
|
|
1455
1456
|
originMessageId: input.runId,
|
|
1456
1457
|
payload,
|
|
1457
|
-
encrypt:
|
|
1458
|
+
encrypt: typeof channel.getDefaultEncrypt === 'function' ? channel.getDefaultEncrypt() : true,
|
|
1458
1459
|
thread: target.session === 'thread' ? target.threadId : undefined,
|
|
1459
1460
|
targetChatType,
|
|
1460
1461
|
explicitReturnPolicy: 'none',
|
|
@@ -2016,6 +2017,7 @@ async function main() {
|
|
|
2016
2017
|
channelName: 'control',
|
|
2017
2018
|
pureIdentity: true,
|
|
2018
2019
|
gatewayUrl: daemonCfg.aun?.gatewayUrl,
|
|
2020
|
+
defaultEncrypt: daemonCfg.aun?.defaultEncrypt,
|
|
2019
2021
|
aunTrace: daemonCfg.debug?.aunTrace,
|
|
2020
2022
|
aunSdkLog: daemonCfg.debug?.aunSdkLog,
|
|
2021
2023
|
});
|
|
@@ -2034,26 +2036,38 @@ async function main() {
|
|
|
2034
2036
|
const ecwebPath = path.join(resolvePaths().root, 'ecweb');
|
|
2035
2037
|
const ecwebEntry = path.join(ecwebPath, 'dist', 'index.js');
|
|
2036
2038
|
if (fs.existsSync(ecwebEntry)) {
|
|
2039
|
+
let ecwebVersion;
|
|
2037
2040
|
try {
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2040
|
-
detached: true,
|
|
2041
|
-
stdio: 'ignore',
|
|
2042
|
-
env: { ...process.env, EVOLCORE_HOME: resolvePaths().root }
|
|
2043
|
-
});
|
|
2044
|
-
ecwebProc.unref();
|
|
2045
|
-
logger.info(`✓ ECWeb 已启动 (PID: ${ecwebProc.pid})`);
|
|
2046
|
-
onShutdown(() => {
|
|
2047
|
-
try {
|
|
2048
|
-
if (ecwebProc.pid)
|
|
2049
|
-
platform.killProcess(ecwebProc.pid, true);
|
|
2050
|
-
logger.info(`✓ ECWeb 已停止`);
|
|
2051
|
-
}
|
|
2052
|
-
catch { }
|
|
2053
|
-
});
|
|
2041
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(ecwebPath, 'package.json'), 'utf-8'));
|
|
2042
|
+
ecwebVersion = pkg.version;
|
|
2054
2043
|
}
|
|
2055
|
-
catch
|
|
2056
|
-
|
|
2044
|
+
catch { }
|
|
2045
|
+
const versionError = ecwebVersionRequirementError(ecwebVersion);
|
|
2046
|
+
if (versionError) {
|
|
2047
|
+
logger.error(`ECWeb 未启动: ${versionError}`);
|
|
2048
|
+
}
|
|
2049
|
+
else {
|
|
2050
|
+
try {
|
|
2051
|
+
const ecwebProc = spawn('node', [ecwebEntry], {
|
|
2052
|
+
cwd: ecwebPath,
|
|
2053
|
+
detached: true,
|
|
2054
|
+
stdio: 'ignore',
|
|
2055
|
+
env: { ...process.env, EVOLCORE_HOME: resolvePaths().root }
|
|
2056
|
+
});
|
|
2057
|
+
ecwebProc.unref();
|
|
2058
|
+
logger.info(`✓ ECWeb 已启动 (PID: ${ecwebProc.pid})`);
|
|
2059
|
+
onShutdown(() => {
|
|
2060
|
+
try {
|
|
2061
|
+
if (ecwebProc.pid)
|
|
2062
|
+
platform.killProcess(ecwebProc.pid, true);
|
|
2063
|
+
logger.info(`✓ ECWeb 已停止`);
|
|
2064
|
+
}
|
|
2065
|
+
catch { }
|
|
2066
|
+
});
|
|
2067
|
+
}
|
|
2068
|
+
catch (e) {
|
|
2069
|
+
logger.warn(`ECWeb 启动失败: ${e?.message || e}`);
|
|
2070
|
+
}
|
|
2057
2071
|
}
|
|
2058
2072
|
}
|
|
2059
2073
|
else {
|
|
@@ -2090,7 +2104,7 @@ async function main() {
|
|
|
2090
2104
|
const isRoleMenu = menuControl.isMenu
|
|
2091
2105
|
&& (menuControl.name === 'role' || menuControl.request.cmd === '/role');
|
|
2092
2106
|
const menuResponseContext = () => ({
|
|
2093
|
-
metadata: evolMenuResponseTransportMetadata(
|
|
2107
|
+
metadata: evolMenuResponseTransportMetadata(),
|
|
2094
2108
|
});
|
|
2095
2109
|
if (menuControl.isMenu && !hasValidMenuId(menuControl)) {
|
|
2096
2110
|
logger.warn(`[ControlMenu] dropped malformed request without id type=${menuControl.type}`);
|
|
@@ -2479,6 +2493,9 @@ async function main() {
|
|
|
2479
2493
|
if ((params.scope === 'group') !== targetIsGroup) {
|
|
2480
2494
|
return { ok: false, error: 'AUN target does not match the delegated send scope', code: 'UNSUPPORTED_TARGET' };
|
|
2481
2495
|
}
|
|
2496
|
+
const encrypt = typeof params.encrypt === 'boolean'
|
|
2497
|
+
? params.encrypt
|
|
2498
|
+
: (typeof ch.getDefaultEncrypt === 'function' ? ch.getDefaultEncrypt() : true);
|
|
2482
2499
|
let payload = params.payload;
|
|
2483
2500
|
if (params.file) {
|
|
2484
2501
|
if (isHClassPath(params.file.filePath)) {
|
|
@@ -2520,7 +2537,7 @@ async function main() {
|
|
|
2520
2537
|
originSessionId: params.originSessionId,
|
|
2521
2538
|
originMessageId: params.originMessageId,
|
|
2522
2539
|
payload,
|
|
2523
|
-
encrypt
|
|
2540
|
+
encrypt,
|
|
2524
2541
|
thread: params.thread,
|
|
2525
2542
|
targetChatType: params.scope === 'group' ? 'group' : 'private',
|
|
2526
2543
|
explicitReturnPolicy: params.returnPolicy,
|
|
@@ -2567,7 +2584,7 @@ async function main() {
|
|
|
2567
2584
|
groupId: params.to,
|
|
2568
2585
|
payload,
|
|
2569
2586
|
mentions: params.mentions,
|
|
2570
|
-
encrypt
|
|
2587
|
+
encrypt,
|
|
2571
2588
|
log: params.log ? { ...params.log, sessionId: targetSessionId ?? params.log.sessionId } : undefined,
|
|
2572
2589
|
});
|
|
2573
2590
|
}
|
|
@@ -2577,7 +2594,7 @@ async function main() {
|
|
|
2577
2594
|
return await ch.sendDaemonMsg({
|
|
2578
2595
|
to: params.to,
|
|
2579
2596
|
payload,
|
|
2580
|
-
encrypt
|
|
2597
|
+
encrypt,
|
|
2581
2598
|
causation: runtimeCausation,
|
|
2582
2599
|
log: params.log ? { ...params.log, sessionId: targetSessionId ?? params.log.sessionId } : undefined,
|
|
2583
2600
|
});
|