evolcore 0.0.22 → 0.0.24
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 +74 -14
- package/README.md +4 -0
- package/bin/codex-managed-acl.ps1 +160 -0
- package/bin/codex-managed-hook.mjs +127 -10
- package/bin/ec-safe-output.js +85 -3
- package/bin/install-codex-managed-hooks.mjs +384 -95
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +30 -2
- package/dist/agents/claude-runner.js +179 -240
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +90 -20
- package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
- package/dist/agents/codex/catalog.js +70 -0
- package/dist/agents/codex/diagnostics.js +369 -0
- package/dist/agents/codex-runner.js +839 -192
- package/dist/agents/ecagent-runner.js +27 -34
- package/dist/agents/gemini-runner.js +62 -8
- package/dist/agents/runner-types.js +1 -1
- package/dist/aun/aid/managed-operation.js +28 -6
- package/dist/aun/aid/store.js +43 -0
- package/dist/aun/menu-client.js +272 -0
- package/dist/aun/msg/group.js +65 -4
- package/dist/aun/msg/index.js +1 -1
- package/dist/aun/msg/managed-operation.js +57 -5
- package/dist/aun/outbox.js +56 -18
- package/dist/aun/rpc/client.js +7 -1
- package/dist/channels/aun.js +178 -77
- package/dist/channels/daemon.js +7 -1
- package/dist/channels/dingtalk.js +1 -0
- package/dist/channels/feishu.js +10 -4
- package/dist/channels/wechat.js +81 -10
- package/dist/channels/wecom.js +2 -1
- package/dist/cli/agent-command.js +29 -3
- package/dist/cli/agent-create.js +538 -0
- package/dist/cli/agent.js +26 -675
- package/dist/cli/aun-commands.js +108 -24
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/ctl-command.js +2 -0
- package/dist/cli/daemon-commands.js +289 -61
- package/dist/cli/index.js +22 -2
- package/dist/cli/init.js +2 -10
- package/dist/cli/managed-command-guard.js +3 -0
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/restart-monitor.js +432 -8
- package/dist/cli/stats.js +110 -0
- package/dist/cli/task-context.js +12 -2
- package/dist/cli/trigger-command.js +9 -1
- package/dist/config/builtin-roles.js +2 -0
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +10 -7
- package/dist/core/auth/auth-gateway.js +3 -2
- package/dist/core/auth/authorization-audit.js +75 -18
- package/dist/core/auth/operation-authorizer.js +63 -3
- package/dist/core/auth/operation-catalog.js +14 -2
- package/dist/core/auth/remote-access-store.js +136 -0
- package/dist/core/baseagent-loader.js +4 -4
- package/dist/core/bootstrap-messages.js +39 -18
- package/dist/core/bootstrap-service.js +32 -26
- package/dist/core/capability/capability-manager.js +8 -4
- package/dist/core/capability/providers/codex-capability-provider.js +1 -1
- package/dist/core/command/agent-control.js +7 -2
- package/dist/core/command/command-handler.js +128 -30
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +6 -1
- package/dist/core/command/menu-handler.js +410 -98
- package/dist/core/command/menu-protocol.js +123 -0
- package/dist/core/command/slash-gate.js +4 -6
- package/dist/core/command/slash-handler.js +199 -70
- package/dist/core/data-migration.js +5 -15
- package/dist/core/event-catalog.js +3 -0
- package/dist/core/handoff/runtime.js +3 -1
- package/dist/core/handoff/store.js +7 -1
- package/dist/core/message/im-renderer.js +13 -6
- package/dist/core/message/message-bridge.js +5 -36
- package/dist/core/message/message-queue.js +20 -15
- package/dist/core/message/message-utils.js +6 -3
- package/dist/core/message/response-engine.js +147 -94
- package/dist/core/model/catalog-service.js +310 -0
- package/dist/core/model/model-catalog.js +134 -334
- package/dist/core/model/model-diagnostics.js +4 -5
- package/dist/core/model/model-fallback.js +9 -16
- package/dist/core/model/model-permission.js +5 -2
- package/dist/core/permission/approval-gateway.js +183 -32
- package/dist/core/permission/protected-paths.js +63 -4
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-policy.js +257 -31
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/adapters/codex-session-file-adapter.js +71 -3
- package/dist/core/session/session-manager.js +49 -13
- package/dist/core/session/session-renew.js +1 -0
- package/dist/index.js +214 -57
- package/dist/ipc.js +191 -102
- package/dist/paths.js +23 -1
- package/dist/stats/billing.js +18 -4
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +77 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/utils/atomic-write.js +26 -2
- package/dist/utils/cross-platform.js +436 -1
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +16 -2
- package/dist/utils/model-prices.jsonl +23 -20
- package/dist/utils/npm-ops.js +70 -15
- package/dist/utils/windows-autostart.js +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -0
- package/kits/docs/evolcore/agent-create.md +13 -0
- package/kits/docs/evolcore/group-collaboration.md +7 -2
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
- package/kits/migrations/migrate-role-config-v4.mjs +11 -5
- package/kits/migrations/migrate-role-config-v5.mjs +8 -2
- package/kits/templates/roles/admin.json +2 -0
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +8 -1
- package/package.json +16 -4
- package/dist/utils/codex-cli.js +0 -43
|
@@ -12,11 +12,102 @@ export const MENU_REQUEST_TYPES = new Set([
|
|
|
12
12
|
'menu.update',
|
|
13
13
|
'menu.action',
|
|
14
14
|
]);
|
|
15
|
+
export function buildMenuClientProtectedHeaders(input) {
|
|
16
|
+
const clientName = input.clientName ?? 'evol';
|
|
17
|
+
if (clientName === 'ec-menu-client') {
|
|
18
|
+
const clientVersion = input.clientVersion?.trim();
|
|
19
|
+
if (!parseStableSemver(clientVersion)) {
|
|
20
|
+
throw Object.assign(new Error('ec-menu-client requires a stable X.Y.Z client version'), { code: 'INVALID_CLIENT' });
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
client_name: clientName,
|
|
24
|
+
client_version: clientVersion,
|
|
25
|
+
...(input.remoteAccessToken || input.ecwebToken ? { auth_method: 'remote-access-token', remote_access_token: input.remoteAccessToken ?? input.ecwebToken } : {}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const appClientVersion = input.clientVersion?.trim();
|
|
29
|
+
return {
|
|
30
|
+
...(clientName === 'Evol App' ? { client_name: clientName } : {}),
|
|
31
|
+
...(input.evolVersion ? { evol_version: input.evolVersion } : {}),
|
|
32
|
+
...(clientName === 'Evol App' && appClientVersion ? { client_version: appClientVersion } : {}),
|
|
33
|
+
...(input.remoteAccessToken || input.ecwebToken ? { auth_method: 'remote-access-token', remote_access_token: input.remoteAccessToken ?? input.ecwebToken } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function parseMenuClientProtectedHeaders(value) {
|
|
37
|
+
if (!value)
|
|
38
|
+
return {};
|
|
39
|
+
const normalized = {};
|
|
40
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
41
|
+
if (typeof raw !== 'string')
|
|
42
|
+
continue;
|
|
43
|
+
normalized[key.trim().toLowerCase()] = raw;
|
|
44
|
+
}
|
|
45
|
+
const result = {};
|
|
46
|
+
if (normalized.client_name === 'evol' || normalized.client_name === 'Evol App' || normalized.client_name === 'ec-menu-client')
|
|
47
|
+
result.client_name = normalized.client_name;
|
|
48
|
+
else if (normalized.client_name !== undefined)
|
|
49
|
+
result.client_name = normalized.client_name;
|
|
50
|
+
if (normalized.client_version !== undefined)
|
|
51
|
+
result.client_version = normalized.client_version;
|
|
52
|
+
if (normalized.evol_version !== undefined)
|
|
53
|
+
result.evol_version = normalized.evol_version;
|
|
54
|
+
if (normalized.auth_method === 'daemon-owner' || normalized.auth_method === 'remote-access-token' || normalized.auth_method === 'ecweb-token')
|
|
55
|
+
result.auth_method = normalized.auth_method;
|
|
56
|
+
else if (normalized.auth_method !== undefined)
|
|
57
|
+
result.auth_method = normalized.auth_method;
|
|
58
|
+
if (normalized.remote_access_token !== undefined)
|
|
59
|
+
result.remote_access_token = normalized.remote_access_token;
|
|
60
|
+
if (normalized.ecweb_token !== undefined)
|
|
61
|
+
result.ecweb_token = normalized.ecweb_token;
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
/** Validate client identity separately from authorization. These fields never grant access. */
|
|
65
|
+
export function evaluateMenuClientCompatibility(input) {
|
|
66
|
+
const headers = parseMenuClientProtectedHeaders(input.protectedHeaders);
|
|
67
|
+
const clientName = headers.client_name ?? 'evol';
|
|
68
|
+
if (clientName === 'ec-menu-client') {
|
|
69
|
+
if (!input.encrypted || !parseStableSemver(headers.client_version)) {
|
|
70
|
+
return {
|
|
71
|
+
code: 'INVALID_CLIENT',
|
|
72
|
+
message: 'ec-menu-client requires encrypted protected headers and a stable X.Y.Z client_version',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
if (clientName !== 'evol' && clientName !== 'Evol App') {
|
|
78
|
+
return { code: 'INVALID_CLIENT', message: `Unsupported Menu client: ${String(clientName)}` };
|
|
79
|
+
}
|
|
80
|
+
return evaluateEvolMenuVersionGate(input);
|
|
81
|
+
}
|
|
82
|
+
export function parseMenuResponse(value) {
|
|
83
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
84
|
+
throw Object.assign(new Error('Menu response must be an object'), { code: 'INVALID_RESPONSE' });
|
|
85
|
+
}
|
|
86
|
+
const response = value;
|
|
87
|
+
if (response.type !== 'menu.response' || typeof response.id !== 'string' || !response.id.trim()) {
|
|
88
|
+
throw Object.assign(new Error('Invalid Menu response type or id'), { code: 'INVALID_RESPONSE' });
|
|
89
|
+
}
|
|
90
|
+
const hasData = Object.prototype.hasOwnProperty.call(response, 'data');
|
|
91
|
+
const hasError = Object.prototype.hasOwnProperty.call(response, 'error');
|
|
92
|
+
if (hasData === hasError) {
|
|
93
|
+
throw Object.assign(new Error('Menu response must contain exactly one of data or error'), { code: 'INVALID_RESPONSE' });
|
|
94
|
+
}
|
|
95
|
+
if (hasError) {
|
|
96
|
+
const error = response.error;
|
|
97
|
+
if (!error || typeof error !== 'object' || Array.isArray(error)
|
|
98
|
+
|| typeof error.code !== 'string'
|
|
99
|
+
|| typeof error.message !== 'string') {
|
|
100
|
+
throw Object.assign(new Error('Invalid Menu response error'), { code: 'INVALID_RESPONSE' });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
15
105
|
export const MENU_NAME_COMMANDS = Object.freeze({
|
|
16
106
|
pwd: '/pwd',
|
|
17
107
|
session: '/session',
|
|
18
108
|
topic: '/topic',
|
|
19
109
|
baseagent: '/baseagent',
|
|
110
|
+
'baseagent-models': '/baseagent-models',
|
|
20
111
|
model: '/model',
|
|
21
112
|
effort: '/effort',
|
|
22
113
|
chatmode: '/chatmode',
|
|
@@ -259,6 +350,25 @@ export function menuFailure(header, error) {
|
|
|
259
350
|
},
|
|
260
351
|
};
|
|
261
352
|
}
|
|
353
|
+
export function enforceMenuResponseSize(response, maxBytes = 128 * 1024) {
|
|
354
|
+
let bytes;
|
|
355
|
+
try {
|
|
356
|
+
bytes = Buffer.byteLength(JSON.stringify(response), 'utf8');
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return menuFailure({ id: response.id, ...(response.name ? { name: response.name } : {}) }, {
|
|
360
|
+
code: 'INTERNAL_ERROR',
|
|
361
|
+
message: 'Menu response is not serializable',
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
if (bytes <= maxBytes)
|
|
365
|
+
return response;
|
|
366
|
+
return menuFailure({ id: response.id, ...(response.name ? { name: response.name } : {}) }, {
|
|
367
|
+
code: 'RESPONSE_TOO_LARGE',
|
|
368
|
+
message: `Menu response exceeds the ${maxBytes}-byte limit`,
|
|
369
|
+
data: { bytes, maxBytes },
|
|
370
|
+
});
|
|
371
|
+
}
|
|
262
372
|
const INVALID_ARGUMENT_CODES = new Set([
|
|
263
373
|
'ARGUMENT_MISMATCH', 'FILE_TOO_LARGE', 'INVALID_ARGS', 'INVALID_DELEGATION',
|
|
264
374
|
'INVALID_FIELD', 'INVALID_REVISION', 'INVALID_SCOPE', 'INVALID_TYPE', 'INVALID_VALUE', 'MISSING_AID',
|
|
@@ -273,6 +383,8 @@ const STABLE_CODES = new Set([
|
|
|
273
383
|
'MENU_TOKEN_REQUIRED', 'MENU_TOKEN_REJECTED', 'MENU_TOKEN_ENCRYPTION_REQUIRED',
|
|
274
384
|
'INVALID_CONTEXT', 'SCHEMA_VERSION_UNSUPPORTED', 'DEPENDENCY_UNAVAILABLE',
|
|
275
385
|
'RATE_LIMITED', 'CATALOG_STALE', 'DATA_MIGRATION_REQUIRED',
|
|
386
|
+
'INVALID_CLIENT', 'REMOTE_ACCESS_TOKEN_INVALID', 'ECWEB_TOKEN_INVALID', 'CLIENT_BUSY', 'INVALID_RESPONSE', 'TIMEOUT',
|
|
387
|
+
'RESPONSE_TOO_LARGE',
|
|
276
388
|
]);
|
|
277
389
|
export function normalizeMenuError(error) {
|
|
278
390
|
const source = error && typeof error === 'object' ? error : {};
|
|
@@ -493,6 +605,9 @@ function menuFlowBaseRecord(request, context) {
|
|
|
493
605
|
requestId: menuRequestId(request),
|
|
494
606
|
messageId: context.messageId,
|
|
495
607
|
selfAid: context.selfAid,
|
|
608
|
+
requesterAid: context.requesterAid,
|
|
609
|
+
authMethod: context.authMethod,
|
|
610
|
+
clientName: context.clientName,
|
|
496
611
|
};
|
|
497
612
|
}
|
|
498
613
|
function menuRequestBusinessFields(request) {
|
|
@@ -531,11 +646,19 @@ export function logMenuRequestCompleted(request, response, context, options) {
|
|
|
531
646
|
const processingMs = response && typeof response.processing_ms === 'number'
|
|
532
647
|
? response.processing_ms
|
|
533
648
|
: undefined;
|
|
649
|
+
let responseBytes;
|
|
650
|
+
if (response) {
|
|
651
|
+
try {
|
|
652
|
+
responseBytes = Buffer.byteLength(JSON.stringify(response), 'utf8');
|
|
653
|
+
}
|
|
654
|
+
catch { }
|
|
655
|
+
}
|
|
534
656
|
writeMenuFlowRecord({
|
|
535
657
|
...menuFlowBaseRecord(request, context),
|
|
536
658
|
event: options.delivery === 'failed' ? 'menu.request.failed' : 'menu.request.completed',
|
|
537
659
|
delivery: options.delivery,
|
|
538
660
|
processingMs,
|
|
661
|
+
responseBytes,
|
|
539
662
|
reason: options.reason,
|
|
540
663
|
result: response && 'data' in response ? sanitizeMenuLogValue(response.data) : undefined,
|
|
541
664
|
warning: response && 'warning' in response ? sanitizeMenuLogValue(response.warning) : undefined,
|
|
@@ -43,9 +43,9 @@ export function probeSessionActivity(evidence, probes) {
|
|
|
43
43
|
return evaluateSessionActivity(collected);
|
|
44
44
|
}
|
|
45
45
|
// 支持的命令列表
|
|
46
|
-
const commands = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/stop', '/pause', '/compact', '/renew', '/repair', '/fork', '/del', '/perm', '/file', '/check', '/rewind', '/activity', '/observable', '/chatmode', '/mentionmode', '/ask', '/resume', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade'];
|
|
46
|
+
const commands = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/stop', '/pause', '/compact', '/renew', '/repair', '/fork', '/del', '/perm', '/file', '/check', '/rewind', '/activity', '/observable', '/chatmode', '/mentionmode', '/ask', '/resume', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade', '/pair'];
|
|
47
47
|
const deprecatedCommands = ['/clear'];
|
|
48
|
-
const exactBoundaryCommands = new Set(['/pause', '/resume', '/stop']);
|
|
48
|
+
const exactBoundaryCommands = new Set(['/pause', '/resume', '/stop', '/pair']);
|
|
49
49
|
/** Parse the execution command without treating it as a quick/result command. */
|
|
50
50
|
export function parseFullAccessCommand(content) {
|
|
51
51
|
const match = content.match(/^\s*(\/fa|\/fullaccess)(?=\s|$)([\s\S]*)$/);
|
|
@@ -65,7 +65,7 @@ const aliases = {
|
|
|
65
65
|
'/base': '/baseagent',
|
|
66
66
|
};
|
|
67
67
|
// 命令快速路径前缀(所有命令都不进入消息队列)
|
|
68
|
-
const quickCommandPrefixes = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/repair', '/fork', '/stop', '/pause', '/clear', '/compact', '/renew', '/del', '/perm', '/file', '/check', '/s ', '/name', '/rewind', '/rw', '/rw ', '/activity', '/observable', '/chatmode', '/mentionmode', '/ask', '/resume', '/base ', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade'];
|
|
68
|
+
const quickCommandPrefixes = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/repair', '/fork', '/stop', '/pause', '/clear', '/compact', '/renew', '/del', '/perm', '/file', '/check', '/s ', '/name', '/rewind', '/rw', '/rw ', '/activity', '/observable', '/chatmode', '/mentionmode', '/ask', '/resume', '/base ', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade', '/pair'];
|
|
69
69
|
/**
|
|
70
70
|
* 计算两个字符串的 Levenshtein 距离(编辑距离)
|
|
71
71
|
*/
|
|
@@ -119,10 +119,8 @@ export function guardThreadCommand(content, threadId) {
|
|
|
119
119
|
const threadBlocked = ['/new', '/slist', '/s', '/session', '/fork', '/del', '/repair'];
|
|
120
120
|
const hasCommandArgument = (command) => new RegExp(`^${command.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\s|$)`).test(content);
|
|
121
121
|
const isBlocked = threadBlocked.some(hasCommandArgument);
|
|
122
|
-
const isBaseagentSwitch = /^\/baseagent\s/.test(content);
|
|
123
|
-
const isBaseAliasSwitch = /^\/base\s/.test(content);
|
|
124
122
|
const isRewindMutation = /^\/rewind\s/.test(content);
|
|
125
|
-
if (!isBlocked && !
|
|
123
|
+
if (!isBlocked && !isRewindMutation)
|
|
126
124
|
return undefined;
|
|
127
125
|
return { kind: 'command.error', text: '⚠️ 话题中不支持此命令' };
|
|
128
126
|
}
|