evolcore 0.0.11 → 0.0.13
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 +44 -0
- package/bin/codex-managed-hook.mjs +80 -0
- package/bin/ec-safe-output.js +26 -7
- package/dist/agents/claude-runner.js +86 -7
- package/dist/agents/codex-app-server-client.js +174 -20
- package/dist/agents/codex-runner.js +375 -92
- package/dist/agents/ecagent-runner.js +39 -4
- package/dist/agents/gemini-runner.js +1 -0
- package/dist/aun/aid/client.js +11 -21
- package/dist/aun/aid/control-aid.js +36 -13
- package/dist/aun/aid/managed-operation.js +107 -0
- package/dist/aun/aid/store.js +13 -7
- package/dist/aun/group-fs-download.js +56 -0
- package/dist/aun/group-identity.js +1 -2
- package/dist/aun/msg/group.js +91 -44
- package/dist/aun/msg/index.js +1 -2
- package/dist/aun/msg/managed-operation.js +865 -0
- package/dist/aun/msg/mention-schema.js +20 -0
- package/dist/aun/msg/p2p.js +7 -0
- package/dist/aun/msg/upload.js +16 -1
- package/dist/aun/outbox.js +31 -2
- package/dist/aun/rpc/client.js +66 -0
- package/dist/aun/rpc/index.js +1 -2
- package/dist/aun/storage/{upload.js → client.js} +11 -2
- package/dist/aun/storage/index.js +1 -2
- package/dist/channels/aun.js +655 -240
- package/dist/channels/daemon.js +13 -0
- package/dist/cli/agent-command.js +56 -8
- package/dist/cli/agent.js +108 -31
- package/dist/cli/aun-commands.js +270 -69
- package/dist/cli/bench.js +12 -3
- package/dist/cli/cli-argv.js +10 -0
- package/dist/cli/config.js +9 -17
- package/dist/cli/ctl-command.js +1 -1
- package/dist/cli/daemon-commands.js +70 -55
- package/dist/cli/fs-command.js +79 -10
- package/dist/cli/handoff-command.js +3 -0
- package/dist/cli/index.js +30 -2
- package/dist/cli/init.js +77 -8
- package/dist/cli/managed-command-guard.js +41 -0
- package/dist/cli/model.js +11 -4
- package/dist/cli/queue-command.js +53 -1
- package/dist/cli/response.js +71 -0
- package/dist/cli/restart-monitor.js +7 -32
- package/dist/cli/trigger-command.js +11 -0
- package/dist/config/access-policy.js +1 -2
- package/dist/config/builtin-roles.js +9 -0
- package/dist/config/config-manager.js +21 -1
- package/dist/config/contact-book-store.js +11 -3
- package/dist/config/contact-request-service.js +161 -15
- package/dist/config/mention-mode.js +8 -24
- package/dist/config/peer-role-resolver.js +6 -2
- package/dist/config/role-migration-startup.js +53 -0
- package/dist/config/role-store.js +1 -1
- package/dist/core/auth/agent-delegation.js +1 -2
- package/dist/core/auth/auth-gateway.js +29 -1
- package/dist/core/auth/authorization-audit.js +15 -0
- package/dist/core/auth/operation-authorizer.js +31 -7
- package/dist/core/auth/operation-catalog.js +196 -25
- package/dist/core/bootstrap-messages.js +25 -0
- package/dist/core/bootstrap-service.js +64 -4
- package/dist/core/capability/providers/claude-capability-provider.js +9 -31
- package/dist/core/capability/providers/codex-capability-provider.js +4 -15
- package/dist/core/capability/skill-discovery.js +55 -0
- package/dist/core/channel-loader.js +1 -1
- package/dist/core/command/cli-intent-parser.js +9 -0
- package/dist/core/command/command-handler.js +650 -42
- package/dist/core/command/connect-menu.js +15 -0
- package/dist/core/command/group-menu.js +4 -4
- package/dist/core/command/menu-catalog.js +370 -0
- package/dist/core/command/menu-handler.js +230 -51
- package/dist/core/command/menu-protocol.js +94 -2
- package/dist/core/command/slash-gate.js +5 -2
- package/dist/core/command/slash-handler.js +99 -31
- package/dist/core/daemon-file-cache.js +2 -1
- package/dist/core/data-migration.js +9 -2
- package/dist/core/event-catalog.js +6 -0
- package/dist/core/evolagent.js +4 -2
- package/dist/core/handoff/dispatcher.js +5 -2
- package/dist/core/handoff/runtime.js +157 -22
- package/dist/core/handoff/store.js +29 -1
- package/dist/core/handoff/types.js +1 -0
- package/dist/core/interaction-router.js +10 -0
- package/dist/core/message/im-renderer.js +19 -0
- package/dist/core/message/logical-queue-bridge.js +1 -0
- package/dist/core/message/mention-schema.js +126 -0
- package/dist/core/message/message-bridge.js +298 -88
- package/dist/core/message/message-log.js +3 -0
- package/dist/core/message/message-queue.js +268 -39
- package/dist/core/message/message-utils.js +81 -4
- package/dist/core/message/response-engine.js +161 -77
- package/dist/core/message/stream-debouncer.js +10 -2
- package/dist/core/permission/approval-gateway.js +1 -0
- package/dist/core/permission/ec-command-parser.js +243 -18
- package/dist/core/permission/index.js +1 -1
- package/dist/core/permission/mode.js +15 -0
- package/dist/core/permission/readonly-shell-query.js +148 -8
- package/dist/core/permission/sandbox-runtime.js +43 -1
- package/dist/core/permission/tool-policy.js +322 -57
- package/dist/core/protected-paths.js +114 -4
- package/dist/core/session/session-manager.js +42 -4
- package/dist/core/session/session-mapper.js +20 -1
- package/dist/eck/detect.js +18 -1
- package/dist/eck/group-rules-sync.js +15 -44
- package/dist/eck/manifest-engine.js +39 -13
- package/dist/index.js +541 -180
- package/dist/ipc.js +232 -10
- package/dist/paths.js +3 -0
- package/dist/response-system/coordinator.js +6 -4
- package/dist/response-system/engines/v1/proactive-flow.js +26 -8
- package/dist/response-system/modes/single-session/index.js +14 -1
- package/dist/response-system/selector.js +6 -5
- package/dist/trigger/anomaly-store.js +4 -0
- package/dist/trigger/feedback.js +64 -11
- package/dist/trigger/manager.js +21 -1
- package/dist/trigger/parser.js +14 -2
- package/dist/trigger/scheduler.js +1 -0
- package/dist/trigger/script-executor.js +1 -0
- package/dist/trigger/validation.js +67 -6
- package/dist/utils/codex-app-server-registry.js +90 -0
- package/dist/utils/codex-cli.js +5 -1
- package/dist/utils/cross-platform.js +15 -0
- package/dist/utils/ecweb-supervisor.js +332 -0
- package/dist/utils/error-utils.js +10 -0
- package/dist/utils/npm-ops.js +5 -12
- package/dist/utils/tool-summary.js +11 -0
- package/kits/docs/channels/aun.md +1 -1
- package/kits/docs/context-assembly.md +2 -2
- package/kits/docs/evolcore/agent.md +11 -6
- package/kits/docs/evolcore/aid.md +14 -0
- package/kits/docs/evolcore/trigger.md +17 -1
- package/kits/docs/prompt-loading-architecture.md +1 -2
- package/kits/docs/venues/group.md +1 -1
- package/kits/eck_manifest.json +0 -12
- package/kits/migrations/migrate-contact-book-v2.mjs +1 -2
- package/kits/rules/04-relation.md +1 -1
- package/kits/rules/05-venue.md +2 -2
- package/kits/schemas/role-config.schema.1.json +1 -0
- package/kits/schemas/single-session.schema.1.json +3 -3
- package/kits/schemas/single-session.schema.2.json +3 -3
- package/kits/templates/roles/admin.json +27 -0
- package/kits/templates/roles/member.json +34 -1
- package/kits/templates/roles/visitor.json +35 -3
- package/kits/templates/system-fragments/bootstrap.md +1 -1
- package/kits/templates/system-fragments/channel.md +1 -1
- package/kits/templates/system-fragments/session.md +1 -1
- package/package.json +2 -2
- package/dist/aun/msg/payload-type.js +0 -27
- package/dist/aun/rpc/caller.js +0 -42
- package/dist/aun/rpc/connection.js +0 -25
- package/dist/aun/storage/manage.js +0 -10
- package/dist/config/access-policy-domain.js +0 -18
- package/dist/config/config-batch-get.js +0 -11
- package/dist/config/owner-policy.js +0 -4
- package/dist/config/role-config-v4-startup.js +0 -32
- package/dist/config/role-config-v5-startup.js +0 -27
- package/dist/core/auth/trigger-authorization.js +0 -15
- package/dist/core/command/evol-menu-version-gate.js +0 -39
- package/dist/core/interaction-registration.js +0 -10
- package/dist/core/permission/execution-sandbox.js +0 -16
- package/dist/core/relation/peer-key.js +0 -1
- package/dist/core/session/session-key.js +0 -24
- package/dist/eck/baseagent-caps.js +0 -18
- package/dist/eck/rules-loader.js +0 -28
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
2
|
import { ipcQuery } from '../ipc.js';
|
|
3
|
+
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
3
4
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
4
5
|
export async function cmdQueue(args) {
|
|
5
6
|
if (args.length === 0 || isHelpFlag(args[0]) || wantsHelp(args)) {
|
|
@@ -9,10 +10,18 @@ export async function cmdQueue(args) {
|
|
|
9
10
|
|
|
10
11
|
查询:
|
|
11
12
|
--agent <aid> 必填,目标 agent(如 mybot.agentid.pub)
|
|
13
|
+
--after <time> 只显示 adapter 接收时间晚于该值的消息(epoch ms 或 ISO)
|
|
14
|
+
--before <time> 只显示 adapter 接收时间早于该值的消息(epoch ms 或 ISO)
|
|
12
15
|
--showid 显示 messageId
|
|
13
16
|
--full 显示完整消息内容(不截断)
|
|
14
17
|
--format json 以 JSON 格式输出
|
|
15
18
|
|
|
19
|
+
JSON 时间字段:
|
|
20
|
+
receivedAt adapter 收到消息时间(epoch ms)
|
|
21
|
+
enqueuedAt 实际进入队列时间(epoch ms)
|
|
22
|
+
queueWaitMs 排队等待时长(ms)
|
|
23
|
+
processingStartedAt 开始处理时间(epoch ms,active)
|
|
24
|
+
|
|
16
25
|
操作:
|
|
17
26
|
--clear 清空该 agent 的所有待处理消息
|
|
18
27
|
--cancel <messageId> 取消指定消息
|
|
@@ -20,6 +29,7 @@ export async function cmdQueue(args) {
|
|
|
20
29
|
|
|
21
30
|
示例:
|
|
22
31
|
ec queue --agent mybot.agentid.pub
|
|
32
|
+
ec queue --agent mybot.agentid.pub --after 2026-08-19T12:00:00+08:00
|
|
23
33
|
ec queue --agent mybot.agentid.pub --showid
|
|
24
34
|
ec queue --agent mybot.agentid.pub --clear
|
|
25
35
|
ec queue --agent mybot.agentid.pub --cancel msg_d4e5f6
|
|
@@ -45,6 +55,12 @@ export async function cmdQueue(args) {
|
|
|
45
55
|
process.exit(1);
|
|
46
56
|
}
|
|
47
57
|
const formatJson = formatValue === 'json';
|
|
58
|
+
const after = parseQueueTime(getArgValue(args, '--after'), '--after');
|
|
59
|
+
const before = parseQueueTime(getArgValue(args, '--before'), '--before');
|
|
60
|
+
if (after !== undefined && before !== undefined && after >= before) {
|
|
61
|
+
console.error('❌ --after 必须早于 --before');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
48
64
|
const clear = args.includes('--clear');
|
|
49
65
|
const cancelIdx = args.indexOf('--cancel');
|
|
50
66
|
const cancelCandidate = cancelIdx >= 0 && cancelIdx + 1 < args.length ? args[cancelIdx + 1] : undefined;
|
|
@@ -72,12 +88,25 @@ export async function cmdQueue(args) {
|
|
|
72
88
|
: interrupt ? 'interrupt'
|
|
73
89
|
: undefined;
|
|
74
90
|
const socketPath = resolvePaths().socket;
|
|
75
|
-
const
|
|
91
|
+
const managed = process.env.EVOLCORE_SESSION_ID;
|
|
92
|
+
const result = await ipcQuery(socketPath, managed ? {
|
|
93
|
+
type: 'queue.op',
|
|
94
|
+
agent,
|
|
95
|
+
action,
|
|
96
|
+
messageId: cancelMsgId,
|
|
97
|
+
sessionKey,
|
|
98
|
+
after,
|
|
99
|
+
before,
|
|
100
|
+
sessionId: managed,
|
|
101
|
+
delegationToken: process.env[AGENT_DELEGATION_TOKEN_ENV],
|
|
102
|
+
} : {
|
|
76
103
|
type: 'queue-snapshot',
|
|
77
104
|
agent,
|
|
78
105
|
action,
|
|
79
106
|
messageId: cancelMsgId,
|
|
80
107
|
sessionKey,
|
|
108
|
+
after,
|
|
109
|
+
before,
|
|
81
110
|
});
|
|
82
111
|
if (!result) {
|
|
83
112
|
console.error('错误: 无法连接 evolcore 服务');
|
|
@@ -108,6 +137,16 @@ export async function cmdQueue(args) {
|
|
|
108
137
|
}
|
|
109
138
|
console.log(renderQueueItemsCli(items, showId, full, agent));
|
|
110
139
|
}
|
|
140
|
+
function parseQueueTime(value, flag) {
|
|
141
|
+
if (value === undefined)
|
|
142
|
+
return undefined;
|
|
143
|
+
const parsed = /^\d+$/.test(value) ? Number(value) : Date.parse(value);
|
|
144
|
+
if (!Number.isFinite(parsed)) {
|
|
145
|
+
console.error(`❌ ${flag} 必须是 epoch 毫秒或 ISO 时间: ${value}`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
return parsed;
|
|
149
|
+
}
|
|
111
150
|
function renderQueueItemsCli(items, showId, full, aid) {
|
|
112
151
|
const lines = [`${aid} — 队列 (${items.length} 条)`, ''];
|
|
113
152
|
if (items.length === 0) {
|
|
@@ -141,6 +180,12 @@ function renderQueueItemsCli(items, showId, full, aid) {
|
|
|
141
180
|
elapsed = sec >= 60 ? `${Math.floor(sec / 60)}m${sec % 60}s` : `${sec}s`;
|
|
142
181
|
}
|
|
143
182
|
parts.push(` ${elapsed.padEnd(elapsedColWidth)} `);
|
|
183
|
+
const wait = item.queueWaitMs == null ? '—' : formatDuration(item.queueWaitMs);
|
|
184
|
+
parts.push(` wait:${wait.padEnd(6)} `);
|
|
185
|
+
if (item.receivedAt != null)
|
|
186
|
+
parts.push(` recv:${formatQueueTime(item.receivedAt)} `);
|
|
187
|
+
if (item.enqueuedAt != null)
|
|
188
|
+
parts.push(` enq:${formatQueueTime(item.enqueuedAt)} `);
|
|
144
189
|
// 内容列
|
|
145
190
|
const content = full ? item.preview.replace(/\.\.\.$/, '') : item.preview;
|
|
146
191
|
parts.push(`"${content}"`);
|
|
@@ -148,3 +193,10 @@ function renderQueueItemsCli(items, showId, full, aid) {
|
|
|
148
193
|
}
|
|
149
194
|
return lines.join('\n');
|
|
150
195
|
}
|
|
196
|
+
function formatDuration(ms) {
|
|
197
|
+
const sec = Math.max(0, Math.round(ms / 1000));
|
|
198
|
+
return sec >= 60 ? `${Math.floor(sec / 60)}m${sec % 60}s` : `${sec}s`;
|
|
199
|
+
}
|
|
200
|
+
function formatQueueTime(timestamp) {
|
|
201
|
+
return new Date(timestamp).toISOString();
|
|
202
|
+
}
|
package/dist/cli/response.js
CHANGED
|
@@ -15,6 +15,9 @@ import { readField, writeField, determineFieldScope, normalizePeer, ModelScopeEr
|
|
|
15
15
|
import { readFieldWithSource, resolveAgentConfig, ConfigTarget } from '../config/config-manager.js';
|
|
16
16
|
import { ResponseModeRegistry } from '../response-system/registry.js';
|
|
17
17
|
import { registerBuiltinModes } from '../response-system/modes/index.js';
|
|
18
|
+
import { ipcQuery } from '../ipc.js';
|
|
19
|
+
import { resolvePaths } from '../paths.js';
|
|
20
|
+
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
18
21
|
const RESPONSE_MODE_FIELD = 'responseMode';
|
|
19
22
|
const RESPONSE_MODE_PARAMS_FIELD = 'responseModeParams';
|
|
20
23
|
/**
|
|
@@ -54,6 +57,71 @@ function fail(formatJson, code, message) {
|
|
|
54
57
|
}
|
|
55
58
|
process.exit(1);
|
|
56
59
|
}
|
|
60
|
+
async function managedConfig(fieldArgs, formatJson) {
|
|
61
|
+
const sessionId = process.env.EVOLCORE_SESSION_ID;
|
|
62
|
+
const delegationToken = process.env[AGENT_DELEGATION_TOKEN_ENV];
|
|
63
|
+
if (!sessionId)
|
|
64
|
+
fail(formatJson, 'NO_SESSION', 'EVOLCORE_SESSION_ID is not set');
|
|
65
|
+
if (!delegationToken)
|
|
66
|
+
fail(formatJson, 'DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} is not set`);
|
|
67
|
+
const response = await ipcQuery(resolvePaths().socket, {
|
|
68
|
+
type: 'config.op',
|
|
69
|
+
argv: ['config', ...fieldArgs],
|
|
70
|
+
sessionId,
|
|
71
|
+
delegationToken,
|
|
72
|
+
}, 10_000);
|
|
73
|
+
if (!response)
|
|
74
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
75
|
+
if (!response.ok || !response.result?.ok) {
|
|
76
|
+
fail(formatJson, response.code || 'CONFIG_AUTH_FAILED', response.error || 'response config operation failed');
|
|
77
|
+
}
|
|
78
|
+
return response.result;
|
|
79
|
+
}
|
|
80
|
+
async function runManagedResponse(args, formatJson) {
|
|
81
|
+
if (getArgValue(args, '--self') || getArgValue(args, '--peer')) {
|
|
82
|
+
fail(formatJson, 'NOT_ALLOWED', 'Managed response commands always use the authenticated current relation');
|
|
83
|
+
}
|
|
84
|
+
const sub = args[0];
|
|
85
|
+
if (sub === 'set') {
|
|
86
|
+
const id = args[1];
|
|
87
|
+
if (!id)
|
|
88
|
+
fail(formatJson, 'MISSING_ID', 'set requires a mode id');
|
|
89
|
+
if (!buildRegistry().has(id))
|
|
90
|
+
fail(formatJson, 'UNKNOWN_MODE', `Unknown mode: ${id}`);
|
|
91
|
+
await managedConfig(['set', RESPONSE_MODE_FIELD, id], formatJson);
|
|
92
|
+
return emit(formatJson, { ok: true, scope: 'relation', mode: id }, () => `✓ 已设置响应模式为 ${id}(作用域: relation)`);
|
|
93
|
+
}
|
|
94
|
+
if (sub === 'reset') {
|
|
95
|
+
await managedConfig(['unset', RESPONSE_MODE_FIELD], formatJson);
|
|
96
|
+
return emit(formatJson, { ok: true, scope: 'relation' }, () => '✓ 已清除当前关系的响应模式设置');
|
|
97
|
+
}
|
|
98
|
+
if (sub === 'current') {
|
|
99
|
+
const modeResult = await managedConfig(['get', RESPONSE_MODE_FIELD], formatJson);
|
|
100
|
+
const paramsResult = await managedConfig(['get', RESPONSE_MODE_PARAMS_FIELD], formatJson);
|
|
101
|
+
const configuredMode = typeof modeResult.value === 'string' ? modeResult.value : undefined;
|
|
102
|
+
const mode = configuredMode ?? buildRegistry().getPreferredId();
|
|
103
|
+
return emit(formatJson, {
|
|
104
|
+
ok: true,
|
|
105
|
+
scope: 'relation',
|
|
106
|
+
responseMode: mode ?? null,
|
|
107
|
+
source: configuredMode ? 'config' : 'preferred',
|
|
108
|
+
sourceTarget: modeResult.source?.target ?? null,
|
|
109
|
+
responseModeParams: paramsResult.value ?? null,
|
|
110
|
+
}, () => `当前响应模式: ${mode ?? '(无)'}`);
|
|
111
|
+
}
|
|
112
|
+
if (sub === 'config') {
|
|
113
|
+
if (args[1] === 'set') {
|
|
114
|
+
fail(formatJson, 'NOT_ALLOWED', 'responseModeParams cannot be modified as an opaque object from a managed task');
|
|
115
|
+
}
|
|
116
|
+
const result = await managedConfig(['get', RESPONSE_MODE_PARAMS_FIELD], formatJson);
|
|
117
|
+
const params = result.value ?? {};
|
|
118
|
+
const modeId = args[1] && !args[1].startsWith('--') ? args[1] : undefined;
|
|
119
|
+
if (modeId)
|
|
120
|
+
return emit(formatJson, { ok: true, mode: modeId, config: params[modeId] ?? {} }, () => `${modeId} 配置: ${JSON.stringify(params[modeId] ?? {}, null, 2)}`);
|
|
121
|
+
return emit(formatJson, { ok: true, responseModeParams: params }, () => `所有模式配置: ${JSON.stringify(params, null, 2)}`);
|
|
122
|
+
}
|
|
123
|
+
fail(formatJson, 'NOT_ALLOWED', `response ${sub} is not available in a managed task`);
|
|
124
|
+
}
|
|
57
125
|
/** 解析 --self / --peer 为作用域选择器 */
|
|
58
126
|
function parseSelector(args, formatJson) {
|
|
59
127
|
const self = getArgValue(args, '--self');
|
|
@@ -331,6 +399,9 @@ export async function cmdResponse(args) {
|
|
|
331
399
|
console.log(HELP);
|
|
332
400
|
return;
|
|
333
401
|
}
|
|
402
|
+
if (process.env.EVOLCORE_SESSION_ID && sub !== 'list' && sub !== 'info') {
|
|
403
|
+
return runManagedResponse(args, formatJson);
|
|
404
|
+
}
|
|
334
405
|
switch (sub) {
|
|
335
406
|
case 'list': return cmdList(args, formatJson);
|
|
336
407
|
case 'current': return cmdCurrent(args, formatJson);
|
|
@@ -6,8 +6,7 @@ import { resolvePaths, getPackageRoot, daemonControlDir } from '../paths.js';
|
|
|
6
6
|
import { loadDaemonConfig } from '../config-store.js';
|
|
7
7
|
import * as platform from '../utils/cross-platform.js';
|
|
8
8
|
import { EventBus } from '../core/event-bus.js';
|
|
9
|
-
import { tryUpgrade,
|
|
10
|
-
import { resolveAunCoreSdkPkg, AUN_CORE_SDK_PKG } from '../aun/aid/client.js';
|
|
9
|
+
import { tryUpgrade, tryUpgradeGlobalPkg, resolveGlobalPkg } from '../utils/npm-ops.js';
|
|
11
10
|
import { isValidAid } from '../aun/aid/index.js';
|
|
12
11
|
import { msgSend } from '../aun/msg/index.js';
|
|
13
12
|
import { scanInstances, cleanupInstances, writeRestartMonitor, removeRestartMonitor, isRestartMonitorWinner, findOrphanProcesses, killOrphans } from '../utils/instance-registry.js';
|
|
@@ -15,7 +14,6 @@ import { WEB_PACKAGE_NAME } from '../product.js';
|
|
|
15
14
|
import { shouldSuppressRealRestart } from '../utils/restart-safety.js';
|
|
16
15
|
import { rotateStdoutLog } from '../utils/log-writer.js';
|
|
17
16
|
import { inspectDataMigrationRequirement } from '../core/data-migration.js';
|
|
18
|
-
import { serviceProxyNeedsEcweb, startEcwebIfEnabled } from './daemon-commands.js';
|
|
19
17
|
const execFileAsync = promisify(execFile);
|
|
20
18
|
// 清理 Claude Code 环境变量,防止 SDK 认为是嵌套会话
|
|
21
19
|
function cleanEnv() {
|
|
@@ -181,21 +179,7 @@ export async function cmdRestartMonitor() {
|
|
|
181
179
|
await notifyDaemonOwners(p, `⚠️ evolcore 升级失败,使用当前版本继续\n${upgrade.error ?? ''}`.trim(), log);
|
|
182
180
|
break;
|
|
183
181
|
}
|
|
184
|
-
//
|
|
185
|
-
const aunUpgrade = await tryUpgradeAunSdk(resolveAunCoreSdkPkg, AUN_CORE_SDK_PKG);
|
|
186
|
-
switch (aunUpgrade.status) {
|
|
187
|
-
case 'upgraded':
|
|
188
|
-
log(`✅ AUN SDK upgraded: ${aunUpgrade.from} → ${aunUpgrade.to}`);
|
|
189
|
-
await notifyDaemonOwners(p, `📦 AUN SDK 已升级 ${aunUpgrade.from} → ${aunUpgrade.to}`, log);
|
|
190
|
-
break;
|
|
191
|
-
case 'no-update':
|
|
192
|
-
break;
|
|
193
|
-
case 'failed':
|
|
194
|
-
log(`⚠ AUN SDK upgrade failed (${aunUpgrade.from} → ${aunUpgrade.to}): ${aunUpgrade.error}`);
|
|
195
|
-
await notifyDaemonOwners(p, `⚠️ AUN SDK 升级失败,使用当前版本继续\n${aunUpgrade.error ?? ''}`.trim(), log);
|
|
196
|
-
break;
|
|
197
|
-
}
|
|
198
|
-
// EC Web 版本检查与升级(已安装才检查)
|
|
182
|
+
// EC Web 是独立全局包,已安装时单独检查升级。
|
|
199
183
|
const ecwebUpgrade = await tryUpgradeGlobalPkg(() => resolveGlobalPkg(WEB_PACKAGE_NAME), WEB_PACKAGE_NAME);
|
|
200
184
|
switch (ecwebUpgrade.status) {
|
|
201
185
|
case 'upgraded':
|
|
@@ -209,22 +193,12 @@ export async function cmdRestartMonitor() {
|
|
|
209
193
|
await notifyDaemonOwners(p, `⚠️ ${WEB_PACKAGE_NAME} 升级失败,使用当前版本继续\n${ecwebUpgrade.error ?? ''}`.trim(), log);
|
|
210
194
|
break;
|
|
211
195
|
}
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
const ecwebStartedBeforeDaemon = serviceProxyNeedsEcweb(loadDaemonConfig())
|
|
216
|
-
? await startEcwebIfEnabled(p)
|
|
217
|
-
: false;
|
|
218
|
-
if (ecwebStartedBeforeDaemon)
|
|
219
|
-
log('ECWeb started before daemon');
|
|
196
|
+
// ECWeb is owned by the daemon. Starting it here used to race with the
|
|
197
|
+
// daemon's own launcher and ECWeb's stale-instance cleanup, which could
|
|
198
|
+
// leave ServiceProxy pointed at a dead PID.
|
|
220
199
|
// 启动并检测 ready signal
|
|
221
200
|
let started = await spawnAndWaitReady(p, log, READY_TIMEOUT);
|
|
222
201
|
if (started) {
|
|
223
|
-
// 没有 Service Proxy 时可以等 daemon ready 后再启动;有代理时已在上方启动,
|
|
224
|
-
// 避免重新拉起造成实例记录和反向隧道短暂失配。
|
|
225
|
-
if (!ecwebStartedBeforeDaemon && await startEcwebIfEnabled(p)) {
|
|
226
|
-
log('ECWeb started after daemon');
|
|
227
|
-
}
|
|
228
202
|
log('✓ Service restarted successfully');
|
|
229
203
|
archiveSelfHealLog(p, log);
|
|
230
204
|
// 发起会话内的“重启成功”通知由新进程自行发送,此处只负责失败/自愈告警。
|
|
@@ -392,7 +366,7 @@ async function spawnAndWaitReady(p, log, timeout) {
|
|
|
392
366
|
const out = fs.openSync(stdoutLog, 'a');
|
|
393
367
|
const err = fs.openSync(stdoutLog, 'a');
|
|
394
368
|
const appMain = path.join(getPackageRoot(), 'dist', 'index.js');
|
|
395
|
-
const child = spawn(
|
|
369
|
+
const child = spawn(process.execPath, ['--no-warnings=ExperimentalWarning', appMain], {
|
|
396
370
|
detached: true,
|
|
397
371
|
stdio: ['ignore', out, err],
|
|
398
372
|
windowsHide: true,
|
|
@@ -489,6 +463,7 @@ async function invokeClaude(claudePath, p, attempt, maxAttempts, timeout, log) {
|
|
|
489
463
|
timeout,
|
|
490
464
|
// Windows npm CLIs are .cmd shims; execFile needs a shell to run them.
|
|
491
465
|
shell: platform.isWindows,
|
|
466
|
+
windowsHide: platform.isWindows,
|
|
492
467
|
env: { ...process.env, CLAUDE_CODE_ENTRYPOINT: 'cli' },
|
|
493
468
|
maxBuffer: 10 * 1024 * 1024,
|
|
494
469
|
});
|
|
@@ -31,6 +31,10 @@ export async function cmdTrigger(args) {
|
|
|
31
31
|
}
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
+
if (process.env.EVOLCORE_SESSION_ID
|
|
35
|
+
&& (hasOption(rest, '--file') || hasOption(rest, '--prompt-file') || hasOption(rest, '--script-path'))) {
|
|
36
|
+
throw new Error('Managed tasks cannot read trigger definitions, prompts, or scripts from local files; use inline prompt content');
|
|
37
|
+
}
|
|
34
38
|
try {
|
|
35
39
|
switch (sub) {
|
|
36
40
|
case 'list':
|
|
@@ -109,6 +113,7 @@ Create 参数模式支持:
|
|
|
109
113
|
--permission <readonly|auto|request|bypass>(省略则继承当前身份配置)
|
|
110
114
|
--tz <时区> (仅 cron)
|
|
111
115
|
--target-channel <channelKey> --target-channel-id <ID> (AUN 可简写为 aun)
|
|
116
|
+
--target-chat-type <private|group> (AUN 目标必填;channelId 同时作为群聊 ID)
|
|
112
117
|
--target-session <main|thread> [--target-thread-id <threadId>]
|
|
113
118
|
--trigger-thread <by-run|by-trigger> (兼容旧值 per-run)
|
|
114
119
|
--name <名称>
|
|
@@ -259,6 +264,11 @@ async function createTrigger(args, json) {
|
|
|
259
264
|
if (!parsed.targetChannel || !parsed.targetChannelId) {
|
|
260
265
|
throw new Error('CLI flag 模式需要显式指定 --target-channel <channelKey> --target-channel-id <id>');
|
|
261
266
|
}
|
|
267
|
+
const targetIsAun = parsed.targetChannel === 'aun' || parsed.targetChannel.startsWith('aun#');
|
|
268
|
+
if (targetIsAun && !parsed.targetChatType) {
|
|
269
|
+
throw new Error('AUN 目标必须显式指定 --target-chat-type private 或 group');
|
|
270
|
+
}
|
|
271
|
+
const targetChatType = parsed.targetChatType;
|
|
262
272
|
const now = Date.now();
|
|
263
273
|
if (parsed.targetSession === 'thread' && !parsed.targetThreadId) {
|
|
264
274
|
throw new Error('--target-session thread 需要 --target-thread-id');
|
|
@@ -296,6 +306,7 @@ async function createTrigger(args, json) {
|
|
|
296
306
|
channelKey: parsed.targetChannel,
|
|
297
307
|
channelId: parsed.targetChannelId,
|
|
298
308
|
session: parsed.targetSession,
|
|
309
|
+
...(targetChatType ? { chatType: targetChatType } : {}),
|
|
299
310
|
...(parsed.targetSession === 'thread' ? { threadId: parsed.targetThreadId } : {}),
|
|
300
311
|
},
|
|
301
312
|
},
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
|
-
import { ConfigError, ConfigTarget, mutateConfig, read, validateConfig, } from './config-manager.js';
|
|
3
|
-
import { validAgentOwnerIds, validateAccessPolicyDomain, } from './access-policy-domain.js';
|
|
2
|
+
import { ConfigError, ConfigTarget, mutateConfig, read, validateConfig, validAgentOwnerIds, validateAccessPolicyDomain, } from './config-manager.js';
|
|
4
3
|
export class AccessPolicyError extends Error {
|
|
5
4
|
code;
|
|
6
5
|
data;
|
|
@@ -35,11 +35,20 @@ export function getManagementCommandPermissions(role) {
|
|
|
35
35
|
'role.revoke': { allow: true, scopes: ['agent'] },
|
|
36
36
|
'role.policy.read': { allow: true, scopes: ['agent'] },
|
|
37
37
|
'role.relation.read': { allow: true, scopes: ['agent'] },
|
|
38
|
+
'agent.baseagent.update': { allow: true, scopes: ['agent'], constraints: { requireAgentOwner: true, targetCurrentAgentOnly: true } },
|
|
38
39
|
'observable.current': { allow: true, scopes: ['agent'], constraints: { requireAgentOwner: true } },
|
|
40
|
+
'observable.update': { allow: true, scopes: ['agent'], constraints: { requireAgentOwner: true, targetCurrentAgentOnly: true } },
|
|
39
41
|
'config.get': { allow: true, scopes: ['agent', 'relation'] },
|
|
40
42
|
'config.set': { allow: true, scopes: ['agent', 'relation'] },
|
|
41
43
|
'config.unset': { allow: true, scopes: ['agent', 'relation'] },
|
|
42
44
|
'role.policy.write': { allow: true, dangerous: true, scopes: ['agent'], constraints: { requireAgentAdmin: true } },
|
|
45
|
+
'ec.aid.show': { allow: true, dangerous: true, scopes: ['agent'], constraints: { targetCurrentAgentOnly: true, requireAgentAdmin: true } },
|
|
46
|
+
'ec.aid.agentmd.put': { allow: true, dangerous: true, scopes: ['agent'], constraints: { targetCurrentAgentOnly: true, requireAgentAdmin: true } },
|
|
47
|
+
'ec.fs.mkdir': { allow: true, permissionMode: 'auto', scopes: ['relation'], constraints: { groupOnly: true, currentRelationOnly: true, targetCurrentAgentOnly: true } },
|
|
48
|
+
'ec.fs.upload': { allow: true, permissionMode: 'auto', scopes: ['relation'], constraints: { groupOnly: true, currentRelationOnly: true, targetCurrentAgentOnly: true } },
|
|
49
|
+
'ec.fs.copy': { allow: true, permissionMode: 'auto', scopes: ['relation'], constraints: { groupOnly: true, currentRelationOnly: true, targetCurrentAgentOnly: true } },
|
|
50
|
+
'ec.fs.move': { allow: true, permissionMode: 'auto', scopes: ['relation'], constraints: { groupOnly: true, currentRelationOnly: true, targetCurrentAgentOnly: true } },
|
|
51
|
+
'ec.fs.remove': { allow: true, permissionMode: 'auto', scopes: ['relation'], constraints: { groupOnly: true, currentRelationOnly: true, targetCurrentAgentOnly: true } },
|
|
43
52
|
'*': { allow: true },
|
|
44
53
|
// Reload is valid from an Agent's own channel and the daemon control plane.
|
|
45
54
|
// The control-channel gate still requires a daemon owner for cross-Agent reloads.
|
|
@@ -28,7 +28,27 @@ import { clearRoleStoreCache, isRoleName } from './role-store.js';
|
|
|
28
28
|
import { writeRoleDefinition, writeRoleRegistry } from './role-service.js';
|
|
29
29
|
import { mutateContactBookTransactionSync } from './contact-book-store.js';
|
|
30
30
|
import { DAEMON_SCHEMA_NAME } from '../product.js';
|
|
31
|
-
|
|
31
|
+
export function shouldFailFastForMissingOwners(env = process.env) {
|
|
32
|
+
const value = (env.EVOLCORE_REQUIRE_OWNERS || '').trim().toLowerCase();
|
|
33
|
+
return value === '1' || value === 'true' || value === 'yes';
|
|
34
|
+
}
|
|
35
|
+
export function validAgentOwnerIds(agent) {
|
|
36
|
+
return [...new Set((agent?.owners ?? [])
|
|
37
|
+
.map(value => String(value || '').trim())
|
|
38
|
+
.filter(isValidAid))];
|
|
39
|
+
}
|
|
40
|
+
export function validateAccessPolicyDomain(selfAid, agent) {
|
|
41
|
+
const access = agent.access;
|
|
42
|
+
if (!access)
|
|
43
|
+
return undefined;
|
|
44
|
+
if (access.policyMode !== 'open' && validAgentOwnerIds(agent).length === 0) {
|
|
45
|
+
return {
|
|
46
|
+
code: 'restricted_mode_without_owner',
|
|
47
|
+
message: `Agent ${selfAid} cannot use ${access.policyMode} without an Owner`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
32
52
|
export var ConfigTarget;
|
|
33
53
|
(function (ConfigTarget) {
|
|
34
54
|
ConfigTarget["Process"] = "process";
|
|
@@ -184,17 +184,25 @@ function mutateContactBookPreparedSyncInternal(selfAid, prepare) {
|
|
|
184
184
|
value: prepared.value,
|
|
185
185
|
};
|
|
186
186
|
}
|
|
187
|
-
prepared.beforeCommit?.({
|
|
187
|
+
const preparedChanges = prepared.beforeCommit?.({
|
|
188
188
|
contact: next,
|
|
189
189
|
previousContactRevision: previousRevision,
|
|
190
190
|
contactRevision: nextRevision,
|
|
191
191
|
});
|
|
192
192
|
const before = readTextOrNull(file);
|
|
193
193
|
const after = `${JSON.stringify(next, null, 2)}\n`;
|
|
194
|
-
const
|
|
194
|
+
const additionalChanges = preparedChanges === undefined
|
|
195
|
+
? []
|
|
196
|
+
: Array.isArray(preparedChanges) ? preparedChanges : [preparedChanges];
|
|
197
|
+
const changes = [
|
|
198
|
+
{ file, before, after },
|
|
199
|
+
...additionalChanges,
|
|
200
|
+
];
|
|
201
|
+
validateTransactionChanges(selfAid, changes);
|
|
195
202
|
writeJournal(selfAid, { schemaVersion: 1, state: 'prepared', selfAid, changes });
|
|
196
203
|
try {
|
|
197
|
-
|
|
204
|
+
for (const change of changes)
|
|
205
|
+
applyTransactionChange(change);
|
|
198
206
|
writeJournal(selfAid, { schemaVersion: 1, state: 'committed', selfAid, changes });
|
|
199
207
|
removeJournal(selfAid);
|
|
200
208
|
}
|