evolcore 0.0.27 → 0.0.29-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -15
- package/bin/ec-safe-output.js +270 -54
- package/dist/agents/baseagent-availability.js +37 -1
- package/dist/agents/baseagent.js +29 -14
- package/dist/agents/claude-runner.js +171 -13
- package/dist/agents/codex/app-server-client.js +13 -2
- package/dist/agents/codex/catalog.js +7 -1
- package/dist/agents/codex/diagnostics.js +4 -3
- package/dist/agents/codex-runner.js +444 -106
- package/dist/agents/gemini-runner.js +35 -17
- package/dist/aun/group/history.js +130 -90
- package/dist/aun/group/operations.js +1 -3
- package/dist/aun/menu/client.js +1 -0
- package/dist/aun/menu/transport.js +5 -3
- package/dist/aun/msg/managed-operation.js +70 -0
- package/dist/aun/msg/p2p.js +1 -3
- package/dist/aun/msg/upload.js +2 -2
- package/dist/aun/outbox.js +1 -37
- package/dist/channels/aun.js +262 -86
- package/dist/channels/daemon.js +18 -1
- package/dist/channels/feishu.js +1 -2
- package/dist/cli/agent-command.js +23 -3
- package/dist/cli/agent-create.js +68 -2
- package/dist/cli/agent.js +12 -2
- package/dist/cli/aun-commands.js +87 -13
- package/dist/cli/cli-argv.js +26 -0
- package/dist/cli/daemon-commands.js +116 -149
- package/dist/cli/data-command.js +4 -4
- package/dist/cli/diag.js +1 -1
- package/dist/cli/handoff-command.js +2 -0
- package/dist/cli/index.js +18 -1
- package/dist/cli/managed-command-guard.js +10 -0
- package/dist/cli/memory-command.js +441 -0
- package/dist/cli/menu-client.js +4 -0
- package/dist/cli/restart-monitor.js +127 -23
- package/dist/cli/skill-command.js +41 -0
- package/dist/cli/task-context.js +2 -23
- package/dist/cli/trigger-command.js +9 -1
- package/dist/cli/watch-msg-diag.js +209 -0
- package/dist/config/config-field-policy.js +52 -3
- package/dist/config/config-manager.js +17 -4
- package/dist/config/contact-book-store.js +2 -2
- package/dist/config/mention-mode.js +7 -2
- package/dist/config/merge.js +28 -9
- package/dist/config/resolved-config-op.js +1 -1
- package/dist/config/runtime-env.js +137 -0
- package/dist/config/schema-registry.js +11 -1
- package/dist/config-store.js +10 -10
- package/dist/core/audit/event-key.js +3 -1
- package/dist/core/audit/log-integrity.js +4 -0
- package/dist/core/auth/agent-delegation.js +2 -1
- package/dist/core/auth/auth-gateway.js +13 -6
- package/dist/core/auth/authorization-audit.js +54 -19
- package/dist/core/auth/operation-authorizer.js +17 -0
- package/dist/core/auth/operation-catalog.js +9 -0
- package/dist/core/causation/context.js +5 -1
- package/dist/core/command/agent-control.js +1 -2
- package/dist/core/command/command-handler.js +80 -24
- package/dist/core/command/diag-service.js +292 -27
- package/dist/core/command/memory-slash.js +270 -0
- package/dist/core/command/menu-catalog.js +1 -0
- package/dist/core/command/menu-handler.js +331 -79
- package/dist/core/command/menu-protocol.js +45 -4
- package/dist/core/command/slash-gate.js +10 -10
- package/dist/core/command/slash-handler.js +230 -79
- package/dist/core/data-migration.js +282 -505
- package/dist/core/event-catalog.js +26 -0
- package/dist/core/evolagent-registry.js +6 -0
- package/dist/core/evolagent.js +0 -10
- package/dist/core/handoff/store.js +1 -20
- package/dist/core/inference/text-inference.js +57 -1
- package/dist/core/memory/consolidation-context.js +505 -0
- package/dist/core/memory/consolidation-ops-records.js +124 -0
- package/dist/core/memory/consolidation-trigger.js +394 -0
- package/dist/core/memory/index-manager.js +308 -0
- package/dist/core/memory/launch-consolidation.js +395 -0
- package/dist/core/memory/memory-admin.js +234 -0
- package/dist/core/memory/memory-document.js +100 -0
- package/dist/core/memory/memory-session-policy.js +41 -0
- package/dist/core/memory/memory-signature.js +257 -0
- package/dist/core/memory/memory-writer.js +432 -0
- package/dist/core/memory/staleness.js +117 -0
- package/dist/core/message/auto-mention-gate.js +454 -0
- package/dist/core/message/im-renderer.js +90 -20
- package/dist/core/message/message-bridge.js +333 -23
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +114 -27
- package/dist/core/message/pending-hints.js +329 -161
- package/dist/core/message/response-engine.js +596 -90
- package/dist/core/permission/ec-command-parser.js +1044 -87
- package/dist/core/permission/protected-paths.js +376 -126
- package/dist/core/permission/sandbox-runtime.js +40 -12
- package/dist/core/permission/tool-error-code.js +96 -13
- package/dist/core/permission/tool-policy.js +277 -24
- package/dist/core/role/runtime-policy.js +3 -7
- package/dist/core/session/{runner-task-history.js → runner-event-summary.js} +1 -1
- package/dist/core/session/session-fs-store.js +0 -76
- package/dist/core/session/session-idle-monitor.js +355 -0
- package/dist/core/session/session-manager.js +482 -17
- package/dist/core/session/session-mapper.js +33 -16
- package/dist/core/session/session-renew.js +217 -155
- package/dist/core/session/{session-turns.js → session-transcript.js} +35 -6
- package/dist/core/skill/global-watcher.js +282 -0
- package/dist/core/skill/index-generator.js +84 -0
- package/dist/core/skill/startup.js +73 -0
- package/dist/core/skill/switch-resolver.js +115 -0
- package/dist/core/task/task-activity-store.js +219 -0
- package/dist/eck/kit-renderer.js +30 -3
- package/dist/eck/manifest-engine.js +26 -4
- package/dist/index.js +722 -171
- package/dist/ipc.js +564 -2
- package/dist/paths.js +30 -9
- package/dist/product.js +1 -0
- package/dist/response-system/engines/v1/proactive-flow.js +116 -15
- package/dist/response-system/modes/single-session/index.js +3 -0
- package/dist/trigger/feedback.js +1 -0
- package/dist/trigger/manager.js +0 -10
- package/dist/trigger/scheduler.js +11 -0
- package/dist/trigger/validation.js +22 -0
- package/dist/utils/atomic-write.js +98 -0
- package/dist/utils/avatar-upload.js +59 -18
- package/dist/utils/cross-platform.js +87 -16
- package/dist/utils/error-dict.json +6 -3
- package/dist/utils/error-utils.js +27 -0
- package/dist/utils/logger.js +32 -10
- package/dist/utils/media-cache.js +84 -0
- package/dist/utils/msg-diag.js +97 -0
- package/dist/utils/npm-ops.js +119 -4
- package/dist/utils/package-version-info.js +244 -0
- package/dist/utils/welcome.js +37 -8
- package/dist/utils/windows-shell-trust.js +37 -0
- package/kits/docs/AUTHORING.md +314 -0
- package/kits/docs/GUIDE.md +2 -0
- package/kits/docs/INDEX.md +2 -0
- package/kits/docs/aun/CHEATSHEET.md +4 -0
- package/kits/docs/aun/SDK.md +60 -0
- package/kits/docs/channels/aun.md +8 -0
- package/kits/docs/context-assembly.md +10 -6
- package/kits/docs/evolcore/INDEX.md +17 -3
- package/kits/docs/evolcore/agent-create.md +24 -0
- package/kits/docs/evolcore/agent.md +5 -2
- package/kits/docs/evolcore/config.md +1 -1
- package/kits/docs/evolcore/ec-capabilities.md +364 -0
- package/kits/docs/evolcore/group.md +34 -18
- package/kits/docs/evolcore/memory-architecture.md +78 -0
- package/kits/docs/evolcore/memory-consolidation-batches.md +133 -0
- package/kits/docs/evolcore/memory-consolidation.md +263 -0
- package/kits/docs/evolcore/memory-tags.md +63 -0
- package/kits/docs/evolcore/memory.md +110 -0
- package/kits/docs/evolcore/menu-client.md +27 -11
- package/kits/{schemas → docs/evolcore}/menu-exec-schema-commands.md +12 -6
- package/kits/docs/evolcore/menu-protocol.md +213 -0
- package/kits/docs/evolcore/msg.md +2 -0
- package/kits/docs/evolcore/trigger.md +7 -5
- package/kits/docs/path-registry.md +6 -8
- package/kits/docs/prompt-loading-architecture.md +5 -3
- package/kits/docs/venues/group.md +5 -4
- package/kits/eck_manifest.json +294 -88
- package/kits/eck_manifest.memory.json +257 -0
- package/kits/rules/03-identity.md +8 -8
- package/kits/rules/05-venue.md +4 -2
- package/kits/rules/06-channel.md +1 -1
- package/kits/schemas/_meta.json +276 -47
- package/kits/schemas/agent-config.schema.12.json +38 -2
- package/kits/schemas/agent-config.schema.13.json +591 -0
- package/kits/schemas/daemon.schema.6.json +9 -9
- package/kits/schemas/defaults.schema.5.json +29 -0
- package/kits/schemas/relation-config.schema.8.json +14 -1
- package/kits/schemas/relation-config.schema.9.json +129 -0
- package/kits/schemas/role-config.schema.1.json +3 -3
- package/kits/skills/.switches.json +3 -0
- package/kits/skills/ec-skill/SKILL.md +217 -0
- package/kits/skills/ec-skill/scripts/cli.mjs +128 -0
- package/kits/skills/ec-skill/scripts/deps.mjs +107 -0
- package/kits/skills/ec-skill/scripts/frontmatter.mjs +104 -0
- package/kits/skills/ec-skill/scripts/skill.mjs +629 -0
- package/kits/skills/ec-skill/scripts/template/SKILL.md.tmpl +30 -0
- package/kits/templates/decision/auto-mention.md +25 -0
- package/kits/templates/decision/session-renew.md +22 -0
- package/kits/templates/memory-consolidation/forget.md +104 -0
- package/kits/templates/memory-consolidation/generalize.md +76 -0
- package/kits/templates/memory-consolidation/notes.md +133 -0
- package/kits/templates/memory-consolidation/profile.md +58 -0
- package/kits/templates/memory-consolidation/promote.md +72 -0
- package/kits/templates/memory-consolidation/workflow.md +75 -0
- package/kits/templates/system-fragments/bootstrap.md +14 -5
- package/kits/templates/system-fragments/commands.md +1 -0
- package/kits/templates/system-fragments/group-history.md +6 -0
- package/kits/templates/system-fragments/identity.md +0 -3
- package/kits/templates/system-fragments/memory.md +79 -0
- package/kits/templates/system-fragments/reply.md +1 -0
- package/kits/templates/system-fragments/venue.md +1 -1
- package/package.json +4 -6
- package/dist/trigger/legacy-session-history.js +0 -19
- package/kits/templates/system-fragments/group-unread-history.md +0 -7
|
@@ -2,6 +2,8 @@ const BEHAVIOR_TOP_FIELDS = new Set([
|
|
|
2
2
|
'active_baseagent',
|
|
3
3
|
'chatmode',
|
|
4
4
|
'mentionMode',
|
|
5
|
+
'autoMentionQuietWindowMs',
|
|
6
|
+
'sessionIdleSec',
|
|
5
7
|
'groupSlashRequireMentions',
|
|
6
8
|
'responseMode',
|
|
7
9
|
'responseModeParams',
|
|
@@ -14,6 +16,7 @@ const BEHAVIOR_TOP_FIELDS = new Set([
|
|
|
14
16
|
'render',
|
|
15
17
|
'sessionManifests',
|
|
16
18
|
'enable_rich_content',
|
|
19
|
+
'memory',
|
|
17
20
|
]);
|
|
18
21
|
const BASEAGENT_BEHAVIOR_FIELDS = new Set([
|
|
19
22
|
'model',
|
|
@@ -59,6 +62,7 @@ const SENSITIVE_TOP_FIELDS = new Set([
|
|
|
59
62
|
'roles',
|
|
60
63
|
'role',
|
|
61
64
|
'extra_backup',
|
|
65
|
+
'decision_model',
|
|
62
66
|
]);
|
|
63
67
|
const CRITICAL_AGENT_FIELDS = new Set(['owners', 'admins', 'roles', 'access']);
|
|
64
68
|
const EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
|
|
@@ -75,7 +79,7 @@ export function isBehaviorConfigFieldPath(fieldPath) {
|
|
|
75
79
|
}
|
|
76
80
|
return BEHAVIOR_TOP_FIELDS.has(parts[0]);
|
|
77
81
|
}
|
|
78
|
-
export function resolveConfigFieldRule(fieldPath) {
|
|
82
|
+
export function resolveConfigFieldRule(fieldPath, scope) {
|
|
79
83
|
const field = fieldPath.trim();
|
|
80
84
|
if (!field)
|
|
81
85
|
return { class: 'unknown' };
|
|
@@ -122,6 +126,10 @@ export function resolveConfigFieldRule(fieldPath) {
|
|
|
122
126
|
return scalar(field, 'nonnegative-number');
|
|
123
127
|
if (field === 'mentionMode')
|
|
124
128
|
return scalar(field, 'mention-mode');
|
|
129
|
+
if (field === 'autoMentionQuietWindowMs')
|
|
130
|
+
return scalar(field, 'nonnegative-number');
|
|
131
|
+
if (field === 'sessionIdleSec')
|
|
132
|
+
return scalar(field, 'finite-number');
|
|
125
133
|
if (field === 'groupSlashRequireMentions')
|
|
126
134
|
return scalar(field, 'boolean');
|
|
127
135
|
if (field === 'show_activities')
|
|
@@ -132,6 +140,8 @@ export function resolveConfigFieldRule(fieldPath) {
|
|
|
132
140
|
return scalar(field, 'string');
|
|
133
141
|
if (field === 'configSnapshots')
|
|
134
142
|
return scalar('configSnapshots', 'boolean');
|
|
143
|
+
if (field === 'restartRecovery.enabled')
|
|
144
|
+
return scalar('restartRecovery.enabled', 'boolean');
|
|
135
145
|
if (top === 'chatmode') {
|
|
136
146
|
if (parts.length === 1)
|
|
137
147
|
return readonlyObject('chatmode');
|
|
@@ -158,6 +168,8 @@ export function resolveConfigFieldRule(fieldPath) {
|
|
|
158
168
|
return scalar('session_renew', 'boolean');
|
|
159
169
|
if (parts[1] === 'after_hours')
|
|
160
170
|
return scalar('session_renew', 'positive-number');
|
|
171
|
+
if (parts[1] === 'new_probability_threshold')
|
|
172
|
+
return scalar('session_renew', 'probability');
|
|
161
173
|
if (parts[1] === 'fallback_action')
|
|
162
174
|
return scalar('session_renew', 'session-renew-action');
|
|
163
175
|
return { class: 'unknown' };
|
|
@@ -188,6 +200,31 @@ export function resolveConfigFieldRule(fieldPath) {
|
|
|
188
200
|
return parts.length === 1
|
|
189
201
|
? readonlyObject('group_venue_sync')
|
|
190
202
|
: { class: 'unknown' };
|
|
203
|
+
if (top === 'memory') {
|
|
204
|
+
if (parts.length === 1)
|
|
205
|
+
return readonlyObject('memory');
|
|
206
|
+
if (field === 'memory.enableAgent')
|
|
207
|
+
return scalar('memory', 'boolean', 'owner-only');
|
|
208
|
+
if (field === 'memory.enableOwner')
|
|
209
|
+
return scalar('memory', 'boolean', 'owner-only');
|
|
210
|
+
if (field === 'memory.enableRelation') {
|
|
211
|
+
// relation scope:对端自主控制自己这条关系的记忆开关,role-overridable
|
|
212
|
+
// agent scope:owner 级管控,owner-only
|
|
213
|
+
return scope === 'relation'
|
|
214
|
+
? scalar('memory', 'boolean')
|
|
215
|
+
: scalar('memory', 'boolean', 'owner-only');
|
|
216
|
+
}
|
|
217
|
+
// 数值参数:整理节奏与容量上限,均 owner-only
|
|
218
|
+
if (field === 'memory.idleHours'
|
|
219
|
+
|| field === 'memory.checkIntervalHours'
|
|
220
|
+
|| field === 'memory.backlogHours'
|
|
221
|
+
|| field === 'memory.indexMaxBytes'
|
|
222
|
+
|| field === 'memory.forgetAfterDays'
|
|
223
|
+
|| field === 'memory.profileRegenDays') {
|
|
224
|
+
return scalar('memory', 'positive-number', 'owner-only');
|
|
225
|
+
}
|
|
226
|
+
return { class: 'unknown' };
|
|
227
|
+
}
|
|
191
228
|
return { class: 'unknown' };
|
|
192
229
|
}
|
|
193
230
|
export function isSafeBehaviorConfigField(fieldPath) {
|
|
@@ -262,6 +299,18 @@ export function parseConfigFieldValue(fieldPath, rawValue) {
|
|
|
262
299
|
? { ok: true, value }
|
|
263
300
|
: { ok: false, reason: `Config field ${fieldPath} must be a positive number` };
|
|
264
301
|
}
|
|
302
|
+
case 'finite-number': {
|
|
303
|
+
const value = Number(raw);
|
|
304
|
+
return Number.isFinite(value)
|
|
305
|
+
? { ok: true, value }
|
|
306
|
+
: { ok: false, reason: `Config field ${fieldPath} must be a finite number` };
|
|
307
|
+
}
|
|
308
|
+
case 'probability': {
|
|
309
|
+
const value = Number(raw);
|
|
310
|
+
return raw && Number.isFinite(value) && value >= 0 && value <= 1
|
|
311
|
+
? { ok: true, value }
|
|
312
|
+
: { ok: false, reason: `Config field ${fieldPath} must be a number between 0 and 1` };
|
|
313
|
+
}
|
|
265
314
|
case 'effort':
|
|
266
315
|
return EFFORTS.has(raw)
|
|
267
316
|
? { ok: true, value: raw }
|
|
@@ -271,9 +320,9 @@ export function parseConfigFieldValue(fieldPath, rawValue) {
|
|
|
271
320
|
? { ok: true, value: raw }
|
|
272
321
|
: { ok: false, reason: `Config field ${fieldPath} must be interactive or proactive` };
|
|
273
322
|
case 'mention-mode':
|
|
274
|
-
return raw === 'disabled' || raw === 'mention-only'
|
|
323
|
+
return raw === 'disabled' || raw === 'mention-only' || raw === 'auto'
|
|
275
324
|
? { ok: true, value: raw }
|
|
276
|
-
: { ok: false, reason: `Config field ${fieldPath} must be disabled
|
|
325
|
+
: { ok: false, reason: `Config field ${fieldPath} must be disabled, mention-only, or auto` };
|
|
277
326
|
case 'show-activities':
|
|
278
327
|
return raw === 'all' || raw === 'text' || raw === 'none'
|
|
279
328
|
? { ok: true, value: raw }
|
|
@@ -747,6 +747,10 @@ export function normalizeProcessConfigCompat(value) {
|
|
|
747
747
|
const debug = value.debug;
|
|
748
748
|
let changed = false;
|
|
749
749
|
let normalized = value;
|
|
750
|
+
if (Object.prototype.hasOwnProperty.call(normalized, 'fullaccess')) {
|
|
751
|
+
normalized = { ...normalized };
|
|
752
|
+
delete normalized.fullaccess;
|
|
753
|
+
}
|
|
750
754
|
if (idleMonitor && typeof idleMonitor === 'object' && !Array.isArray(idleMonitor)) {
|
|
751
755
|
const nextIdleMonitor = { ...idleMonitor };
|
|
752
756
|
if (nextIdleMonitor.apiRetryTimeout === undefined && nextIdleMonitor.retryAttemptTimeout !== undefined) {
|
|
@@ -1337,7 +1341,7 @@ export function normalizeDefaultsBehaviorCompat(defaults) {
|
|
|
1337
1341
|
if (!normalized.chatmode && (chatMode === 'interactive' || chatMode === 'proactive')) {
|
|
1338
1342
|
normalized.chatmode = { private: chatMode, group: chatMode, nothuman: chatMode };
|
|
1339
1343
|
}
|
|
1340
|
-
if (normalized.mentionMode === undefined && (config.mentionMode === 'disabled' || config.mentionMode === 'mention-only')) {
|
|
1344
|
+
if (normalized.mentionMode === undefined && (config.mentionMode === 'disabled' || config.mentionMode === 'mention-only' || config.mentionMode === 'auto')) {
|
|
1341
1345
|
normalized.mentionMode = config.mentionMode;
|
|
1342
1346
|
}
|
|
1343
1347
|
if (normalized.show_activities === undefined && ['all', 'text', 'none'].includes(config.show_activities)) {
|
|
@@ -1362,9 +1366,10 @@ function stripStaticOwnerField(config) {
|
|
|
1362
1366
|
}
|
|
1363
1367
|
function stripRelationRoleData(config) {
|
|
1364
1368
|
if (!config || (!Object.prototype.hasOwnProperty.call(config, 'role')
|
|
1365
|
-
&& !Object.prototype.hasOwnProperty.call(config, 'roles')
|
|
1369
|
+
&& !Object.prototype.hasOwnProperty.call(config, 'roles')
|
|
1370
|
+
&& !Object.prototype.hasOwnProperty.call(config, 'decision_model')))
|
|
1366
1371
|
return config;
|
|
1367
|
-
const { role: _role, roles: _legacyRoles, ...rest } = config;
|
|
1372
|
+
const { role: _role, roles: _legacyRoles, decision_model: _decisionModel, ...rest } = config;
|
|
1368
1373
|
return rest;
|
|
1369
1374
|
}
|
|
1370
1375
|
// ── effective(合并视图)─────────────────────────────────────────────────
|
|
@@ -1374,6 +1379,7 @@ function stripRelationRoleData(config) {
|
|
|
1374
1379
|
export function resolveEffective(sel, opts = {}) {
|
|
1375
1380
|
const config = resolveAgentConfig(sel, opts);
|
|
1376
1381
|
const observableDefault = loadSchema('agent-config').fields.get('observable')?.default;
|
|
1382
|
+
const autoMentionQuietWindowMsDefault = loadSchema('agent-config').fields.get('autoMentionQuietWindowMs')?.default;
|
|
1377
1383
|
const effective = {
|
|
1378
1384
|
$schema_version: config.$schema_version ?? currentVersion('agent-config'),
|
|
1379
1385
|
aid: config.aid ?? sel.self ?? '',
|
|
@@ -1384,6 +1390,7 @@ export function resolveEffective(sel, opts = {}) {
|
|
|
1384
1390
|
owners: config.owners,
|
|
1385
1391
|
fullaccess: config.fullaccess,
|
|
1386
1392
|
aun: config.aun,
|
|
1393
|
+
decision_model: config.decision_model,
|
|
1387
1394
|
channels: config.channels ?? [],
|
|
1388
1395
|
models: config.models,
|
|
1389
1396
|
projects: config.projects,
|
|
@@ -1398,6 +1405,8 @@ export function resolveEffective(sel, opts = {}) {
|
|
|
1398
1405
|
baseagents: config.baseagents,
|
|
1399
1406
|
chatmode: config.chatmode,
|
|
1400
1407
|
mentionMode: config.mentionMode,
|
|
1408
|
+
autoMentionQuietWindowMs: config.autoMentionQuietWindowMs
|
|
1409
|
+
?? (typeof autoMentionQuietWindowMsDefault === 'number' ? autoMentionQuietWindowMsDefault : 3000),
|
|
1401
1410
|
groupSlashRequireMentions: config.groupSlashRequireMentions ?? true,
|
|
1402
1411
|
model: config.model,
|
|
1403
1412
|
responseMode: config.responseMode,
|
|
@@ -1410,6 +1419,7 @@ export function resolveEffective(sel, opts = {}) {
|
|
|
1410
1419
|
render: config.render,
|
|
1411
1420
|
sessionManifests: config.sessionManifests,
|
|
1412
1421
|
enable_rich_content: config.enable_rich_content,
|
|
1422
|
+
memory: config.memory,
|
|
1413
1423
|
};
|
|
1414
1424
|
return normalizeEffectiveCompatibility(effective);
|
|
1415
1425
|
}
|
|
@@ -1430,6 +1440,7 @@ const EFFECTIVE_BEHAVIOR_FIELDS = [
|
|
|
1430
1440
|
'baseagents',
|
|
1431
1441
|
'chatmode',
|
|
1432
1442
|
'mentionMode',
|
|
1443
|
+
'autoMentionQuietWindowMs',
|
|
1433
1444
|
'groupSlashRequireMentions',
|
|
1434
1445
|
'flush_delay',
|
|
1435
1446
|
'debounce',
|
|
@@ -1456,7 +1467,9 @@ export function routeFieldPath(fieldPath, scope) {
|
|
|
1456
1467
|
if (scope === 'process')
|
|
1457
1468
|
return routeIn(DAEMON_SCHEMA_NAME, ConfigTarget.Process, topField);
|
|
1458
1469
|
if (scope === 'defaults') {
|
|
1459
|
-
if (isBehaviorConfigFieldPath(fieldPath)
|
|
1470
|
+
if (isBehaviorConfigFieldPath(fieldPath)
|
|
1471
|
+
&& topField !== 'session_renew'
|
|
1472
|
+
&& topField !== 'autoMentionQuietWindowMs') {
|
|
1460
1473
|
throw new ConfigError('DEFAULT_BEHAVIOR_REJECT', `--default 不支持行为字段: ${fieldPath}`);
|
|
1461
1474
|
}
|
|
1462
1475
|
return routeIn('defaults', ConfigTarget.Defaults, topField);
|
|
@@ -3,7 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { isValidAid } from '../aun/aid/validation.js';
|
|
5
5
|
import { isExplicitGroupId } from '../aun/group/index.js';
|
|
6
|
-
import { agentConfig, agentContactConfig, agentDir, resolvePaths } from '../paths.js';
|
|
6
|
+
import { agentConfig, agentContactAuditPath, agentContactConfig, agentDir, resolvePaths } from '../paths.js';
|
|
7
7
|
import { atomicReadJson, atomicWrite, atomicWriteJson } from '../utils/atomic-write.js';
|
|
8
8
|
import { fileCache } from '../core/daemon-file-cache.js';
|
|
9
9
|
import { ensureManagedLockParent, resolveManagedLockPath } from '../core/runtime-lock.js';
|
|
@@ -601,7 +601,7 @@ function journalFile(selfAid) {
|
|
|
601
601
|
return path.join(agentDir(selfAid), JOURNAL_NAME);
|
|
602
602
|
}
|
|
603
603
|
function appendAudit(selfAid, request, previousContactRevision, contactRevisionValue) {
|
|
604
|
-
const file =
|
|
604
|
+
const file = agentContactAuditPath(selfAid);
|
|
605
605
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
606
606
|
fs.appendFileSync(file, `${JSON.stringify({
|
|
607
607
|
timestamp: new Date().toISOString(),
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export function normalizeMentionMode(mode) {
|
|
1
|
+
export function normalizeAunMentionMode(mode) {
|
|
3
2
|
if (typeof mode !== 'string')
|
|
4
3
|
return undefined;
|
|
5
4
|
const normalized = mode.trim().toLowerCase();
|
|
@@ -9,3 +8,9 @@ export function normalizeMentionMode(mode) {
|
|
|
9
8
|
return 'mention-only';
|
|
10
9
|
return undefined;
|
|
11
10
|
}
|
|
11
|
+
export function normalizeMentionMode(mode) {
|
|
12
|
+
const normalized = typeof mode === 'string' ? mode.trim().toLowerCase() : '';
|
|
13
|
+
if (normalized === 'auto')
|
|
14
|
+
return 'auto';
|
|
15
|
+
return normalizeAunMentionMode(mode);
|
|
16
|
+
}
|
package/dist/config/merge.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* merge —— 类型驱动的覆盖链合并(design §三,全项目唯一实现点)+ ${VAR} 展开。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 合并规则(按字段的 x-merge 语义):
|
|
5
5
|
* - scalar:高优先级整体覆盖
|
|
6
6
|
* - list: 并集追加去重(只能加,不能减)
|
|
7
|
-
* - dict: 键并集;同键 →
|
|
7
|
+
* - dict: 键并集;同键 → 高优先级值直接覆盖(合并粒度=第一层键)
|
|
8
|
+
* 若字段在 schema 中声明了 x-merge-logic: AND 的子字段,
|
|
9
|
+
* 则该子字段做 AND 合并而非覆盖(任意层为 false 结果为 false)
|
|
8
10
|
*
|
|
9
|
-
*
|
|
11
|
+
* 合并代码永远只有这几条规则;所有"覆盖 vs 追加 vs AND"通过 schema 的 x-merge / x-merge-logic 选择表达,不为字段写特判。
|
|
10
12
|
*/
|
|
11
13
|
import fs from 'fs';
|
|
12
14
|
import path from 'path';
|
|
@@ -24,11 +26,20 @@ function unionList(base, overlay) {
|
|
|
24
26
|
}
|
|
25
27
|
return out;
|
|
26
28
|
}
|
|
27
|
-
/** dict
|
|
28
|
-
|
|
29
|
+
/** dict 第一层键合并:键并集,同键按子字段 FieldSpec 决定合并语义。
|
|
30
|
+
* 若子字段声明了 mergeLogic: AND 且两值均为 boolean,做 AND;否则高优先级覆盖。 */
|
|
31
|
+
function mergeDictWithSchema(base, overlay, children) {
|
|
29
32
|
const out = { ...base };
|
|
30
|
-
for (const [k, v] of Object.entries(overlay))
|
|
31
|
-
|
|
33
|
+
for (const [k, v] of Object.entries(overlay)) {
|
|
34
|
+
const childSpec = children?.get(k);
|
|
35
|
+
const prev = out[k];
|
|
36
|
+
if (prev !== undefined && childSpec?.mergeLogic === 'AND' && typeof prev === 'boolean' && typeof v === 'boolean') {
|
|
37
|
+
out[k] = prev && v;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
out[k] = v;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
32
43
|
return out;
|
|
33
44
|
}
|
|
34
45
|
function isPlainObject(v) {
|
|
@@ -38,6 +49,9 @@ function isPlainObject(v) {
|
|
|
38
49
|
* 按 schema 字段表,对覆盖链上"存在的每一级"做类型驱动合并。
|
|
39
50
|
* layers 从低优先级到高优先级;低优先级独有字段保留,冲突点高优先级胜。
|
|
40
51
|
* 字段未在 schema 中(理论上 ajv 已拦)按 scalar 处理。
|
|
52
|
+
*
|
|
53
|
+
* x-merge-logic: AND 语义:所有层的布尔值做 AND 合并,任意层为 false 则结果为 false。
|
|
54
|
+
* 仅对 boolean 类型的 scalar 字段有意义;值缺失的层不参与 AND(按 true 处理)。
|
|
41
55
|
*/
|
|
42
56
|
export function mergeLayers(layers, fields) {
|
|
43
57
|
const out = {};
|
|
@@ -54,11 +68,16 @@ export function mergeLayers(layers, fields) {
|
|
|
54
68
|
out[k] = v;
|
|
55
69
|
continue;
|
|
56
70
|
}
|
|
57
|
-
|
|
71
|
+
// x-merge-logic: AND — 任意层为 false 则结果为 false
|
|
72
|
+
if (spec?.mergeLogic === 'AND' && typeof v === 'boolean' && typeof prev === 'boolean') {
|
|
73
|
+
out[k] = prev && v;
|
|
74
|
+
}
|
|
75
|
+
else if (kind === 'list' && Array.isArray(prev) && Array.isArray(v)) {
|
|
58
76
|
out[k] = unionList(prev, v);
|
|
59
77
|
}
|
|
60
78
|
else if (kind === 'dict' && isPlainObject(prev) && isPlainObject(v)) {
|
|
61
|
-
|
|
79
|
+
// 传入 children,让 dict 子字段能感知 x-merge-logic: AND
|
|
80
|
+
out[k] = mergeDictWithSchema(prev, v, spec?.children);
|
|
62
81
|
}
|
|
63
82
|
else {
|
|
64
83
|
out[k] = v; // scalar 覆盖(或类型不一致时高优先级胜)
|
|
@@ -125,7 +125,7 @@ function resolveFieldCommand(argv, subcommand, options = {}) {
|
|
|
125
125
|
reason: 'fallbackModels is configured only by editing agents/defaults.json',
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
-
const fieldRule = resolveConfigFieldRule(field);
|
|
128
|
+
const fieldRule = resolveConfigFieldRule(field, selector.scope);
|
|
129
129
|
if (subcommand !== 'get' && fieldRule.class === 'safe-readonly-object') {
|
|
130
130
|
return {
|
|
131
131
|
ok: false,
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execFileSync } from 'child_process';
|
|
4
|
+
import { agentDir, resolvePaths } from '../paths.js';
|
|
5
|
+
export const RUNTIME_ENVIRONMENT_NAMES = [
|
|
6
|
+
'ANTHROPIC_BASE_URL',
|
|
7
|
+
'ANTHROPIC_AUTH_TOKEN',
|
|
8
|
+
'ANTHROPIC_API_KEY',
|
|
9
|
+
];
|
|
10
|
+
const cache = new Map();
|
|
11
|
+
const overrides = new Map();
|
|
12
|
+
const startupValues = new Map();
|
|
13
|
+
function captureStartupValues() {
|
|
14
|
+
startupValues.clear();
|
|
15
|
+
for (const name of RUNTIME_ENVIRONMENT_NAMES)
|
|
16
|
+
startupValues.set(name, process.env[name]);
|
|
17
|
+
}
|
|
18
|
+
captureStartupValues();
|
|
19
|
+
function isSafeAid(aid) {
|
|
20
|
+
const labels = aid.split('.');
|
|
21
|
+
return aid.length > 0 && aid.length <= 256 && path.basename(aid) === aid
|
|
22
|
+
&& labels.length >= 3
|
|
23
|
+
&& labels.every(label => /^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$/u.test(label));
|
|
24
|
+
}
|
|
25
|
+
function normalizeScope(aid) {
|
|
26
|
+
if (!aid || aid === '*')
|
|
27
|
+
return '*';
|
|
28
|
+
if (!isSafeAid(aid))
|
|
29
|
+
throw new Error('Invalid agent aid');
|
|
30
|
+
return aid;
|
|
31
|
+
}
|
|
32
|
+
function envFileValue(file, name) {
|
|
33
|
+
try {
|
|
34
|
+
for (const line of fs.readFileSync(file, 'utf8').split(/\r?\n/u)) {
|
|
35
|
+
const match = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/u);
|
|
36
|
+
if (!match || match[1] !== name)
|
|
37
|
+
continue;
|
|
38
|
+
const value = match[2].trim();
|
|
39
|
+
return value.length > 1 && ((value[0] === '"' && value.at(-1) === '"')
|
|
40
|
+
|| (value[0] === "'" && value.at(-1) === "'")) ? value.slice(1, -1) : value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch { }
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
function windowsValue(hive, name) {
|
|
47
|
+
if (process.platform !== 'win32')
|
|
48
|
+
return undefined;
|
|
49
|
+
const registryPath = hive === 'user' ? 'HKCU\\Environment'
|
|
50
|
+
: 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment';
|
|
51
|
+
try {
|
|
52
|
+
const output = execFileSync(path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'reg.exe'), ['query', registryPath, '/v', name], {
|
|
53
|
+
encoding: 'utf8', windowsHide: true, timeout: 1500, stdio: ['ignore', 'pipe', 'ignore'],
|
|
54
|
+
});
|
|
55
|
+
const line = output.split(/\r?\n/u).find(entry => entry.trimStart().startsWith(`${name} `));
|
|
56
|
+
return line?.match(/\sREG_[A-Z0-9_]+\s+(.+?)\s*$/u)?.[1];
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function readOverride(name, aid) {
|
|
63
|
+
return overrides.get(normalizeScope(aid))?.get(name) ?? overrides.get('*')?.get(name);
|
|
64
|
+
}
|
|
65
|
+
export function readRuntimeEnvironmentVariable(name, aid, projectPath) {
|
|
66
|
+
if (!RUNTIME_ENVIRONMENT_NAMES.includes(name)) {
|
|
67
|
+
throw new Error('Unsupported gateway environment variable');
|
|
68
|
+
}
|
|
69
|
+
const typedName = name;
|
|
70
|
+
const scope = normalizeScope(aid);
|
|
71
|
+
const cacheKey = `${scope}:${projectPath || ''}:${typedName}`;
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
const hit = cache.get(cacheKey);
|
|
74
|
+
if (hit && hit.expires > now)
|
|
75
|
+
return hit.result;
|
|
76
|
+
const agentValue = aid && isSafeAid(aid)
|
|
77
|
+
? envFileValue(path.join(agentDir(aid), '.env'), typedName)
|
|
78
|
+
: undefined;
|
|
79
|
+
const projectValue = projectPath
|
|
80
|
+
? envFileValue(path.join(projectPath, '.env'), typedName)
|
|
81
|
+
: undefined;
|
|
82
|
+
const rootValue = envFileValue(path.join(resolvePaths().root, '.env'), typedName);
|
|
83
|
+
const localSelections = [
|
|
84
|
+
[readOverride(typedName, aid), 'ipc-process'],
|
|
85
|
+
[agentValue, 'agent-env'],
|
|
86
|
+
[projectValue, 'project-env'],
|
|
87
|
+
[rootValue, 'root-env'],
|
|
88
|
+
];
|
|
89
|
+
const local = localSelections.find(([value]) => value !== undefined && value !== '');
|
|
90
|
+
if (local) {
|
|
91
|
+
const result = { name: typedName, value: local[0], source: local[1], checkedAt: now };
|
|
92
|
+
cache.set(cacheKey, { result, expires: now + 3000 });
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
const startup = startupValues.get(typedName);
|
|
96
|
+
const user = windowsValue('user', typedName);
|
|
97
|
+
const machine = windowsValue('machine', typedName);
|
|
98
|
+
const selections = [
|
|
99
|
+
[user && user !== startup ? user : undefined, 'windows-user'],
|
|
100
|
+
[machine && machine !== startup ? machine : undefined, 'windows-machine'],
|
|
101
|
+
[startup, 'process-startup'],
|
|
102
|
+
[user, 'windows-user'],
|
|
103
|
+
[machine, 'windows-machine'],
|
|
104
|
+
];
|
|
105
|
+
const selected = selections.find(([value]) => value !== undefined && value !== '');
|
|
106
|
+
const result = {
|
|
107
|
+
name: typedName,
|
|
108
|
+
value: selected?.[0],
|
|
109
|
+
source: selected?.[1] ?? 'unset',
|
|
110
|
+
checkedAt: now,
|
|
111
|
+
};
|
|
112
|
+
cache.set(cacheKey, { result, expires: now + 3000 });
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
export function setRuntimeEnvironmentOverride(aid, values) {
|
|
116
|
+
const scope = normalizeScope(aid);
|
|
117
|
+
const next = new Map(overrides.get(scope));
|
|
118
|
+
for (const name of RUNTIME_ENVIRONMENT_NAMES) {
|
|
119
|
+
if (!Object.prototype.hasOwnProperty.call(values, name))
|
|
120
|
+
continue;
|
|
121
|
+
const value = values[name]?.trim();
|
|
122
|
+
if (value)
|
|
123
|
+
next.set(name, value);
|
|
124
|
+
else
|
|
125
|
+
next.delete(name);
|
|
126
|
+
}
|
|
127
|
+
if (next.size)
|
|
128
|
+
overrides.set(scope, next);
|
|
129
|
+
else
|
|
130
|
+
overrides.delete(scope);
|
|
131
|
+
cache.clear();
|
|
132
|
+
}
|
|
133
|
+
export function resetRuntimeEnvironmentForTests() {
|
|
134
|
+
overrides.clear();
|
|
135
|
+
cache.clear();
|
|
136
|
+
captureStartupValues();
|
|
137
|
+
}
|
|
@@ -99,12 +99,20 @@ function schemaFilePath(name, version) {
|
|
|
99
99
|
return path.join(kitsSchemasDir(), `${name}.schema.${version}.json`);
|
|
100
100
|
}
|
|
101
101
|
function extractFields(raw) {
|
|
102
|
+
return extractFieldsFromProps(raw.properties || {});
|
|
103
|
+
}
|
|
104
|
+
function extractFieldsFromProps(props) {
|
|
102
105
|
const fields = new Map();
|
|
103
|
-
const props = raw.properties || {};
|
|
104
106
|
for (const [name, spec] of Object.entries(props)) {
|
|
105
107
|
if (name === '$schema_version')
|
|
106
108
|
continue;
|
|
107
109
|
const merge = spec['x-merge'] || inferMerge(spec);
|
|
110
|
+
const mergeLogic = spec['x-merge-logic'] === 'AND' ? 'AND' : undefined;
|
|
111
|
+
// 递归提取嵌套 object 字段的子字段,用于 mergeLayers 感知嵌套字段的 x-merge-logic
|
|
112
|
+
const childProps = spec.properties;
|
|
113
|
+
const children = (childProps && typeof childProps === 'object')
|
|
114
|
+
? extractFieldsFromProps(childProps)
|
|
115
|
+
: undefined;
|
|
108
116
|
fields.set(name, {
|
|
109
117
|
name,
|
|
110
118
|
type: spec.type,
|
|
@@ -112,6 +120,8 @@ function extractFields(raw) {
|
|
|
112
120
|
enum: spec.enum,
|
|
113
121
|
default: spec.default,
|
|
114
122
|
description: spec.description,
|
|
123
|
+
...(mergeLogic ? { mergeLogic } : {}),
|
|
124
|
+
...(children && children.size > 0 ? { children } : {}),
|
|
115
125
|
});
|
|
116
126
|
}
|
|
117
127
|
return fields;
|
package/dist/config-store.js
CHANGED
|
@@ -57,8 +57,8 @@ export function loadDaemonConfig() {
|
|
|
57
57
|
const sanitized = stripLegacyAunGatewayConfig(raw ?? {}, resolvePaths().daemonConfig, message => logger.warn(message));
|
|
58
58
|
return validateDaemonConfig(normalizeProcessConfigCompat(normalizeDaemonServices(sanitized)), false);
|
|
59
59
|
}
|
|
60
|
-
export function
|
|
61
|
-
return config.
|
|
60
|
+
export function isRestartRecoveryEnabled(config = loadDaemonConfig()) {
|
|
61
|
+
return config.restartRecovery?.enabled === true;
|
|
62
62
|
}
|
|
63
63
|
let eckSnapshotsConfigCache;
|
|
64
64
|
/** Parse the process-level snapshot gate once for the current daemon lifecycle. */
|
|
@@ -91,16 +91,16 @@ export function saveDaemonConfig(value) {
|
|
|
91
91
|
atomicWriteJson(configPath, validateDaemonConfig({ ...normalized, $schema_version: currentVersion('daemon') }, validateAidDomain));
|
|
92
92
|
}
|
|
93
93
|
function validateDaemonConfig(value, validateAidDomain) {
|
|
94
|
-
if (value.
|
|
95
|
-
if (!value.
|
|
96
|
-
throw new Error('daemon.json.
|
|
94
|
+
if (value.restartRecovery !== undefined) {
|
|
95
|
+
if (!value.restartRecovery || typeof value.restartRecovery !== 'object' || Array.isArray(value.restartRecovery)) {
|
|
96
|
+
throw new Error('daemon.json.restartRecovery must be an object');
|
|
97
97
|
}
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
100
|
-
throw new Error(
|
|
98
|
+
const unknownRestartRecoveryFields = Object.keys(value.restartRecovery).filter(key => key !== 'enabled');
|
|
99
|
+
if (unknownRestartRecoveryFields.length > 0) {
|
|
100
|
+
throw new Error('daemon.json.restartRecovery contains unsupported fields: ' + unknownRestartRecoveryFields.join(', '));
|
|
101
101
|
}
|
|
102
|
-
if (value.
|
|
103
|
-
throw new Error('daemon.json.
|
|
102
|
+
if (value.restartRecovery.enabled !== undefined && typeof value.restartRecovery.enabled !== 'boolean') {
|
|
103
|
+
throw new Error('daemon.json.restartRecovery.enabled must be a boolean');
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
const minEvolVersion = value.aun?.minEvolVersion;
|
|
@@ -40,5 +40,7 @@ export function buildAuthorizationEventKey(input) {
|
|
|
40
40
|
requestId: input.requestId,
|
|
41
41
|
})}:authorization:${stableDigest([input.operation])}`;
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// Anonymous authorizations cannot be joined safely. Keep them as distinct
|
|
44
|
+
// records so daily analysis never merges unrelated calls by session/operation.
|
|
45
|
+
return `authorization:unlinked:${crypto.randomUUID()}`;
|
|
44
46
|
}
|
|
@@ -137,6 +137,10 @@ function stableHash(value) {
|
|
|
137
137
|
permissionMode: firstDefined(value, nested, ['permissionMode', 'permission_mode']),
|
|
138
138
|
isError: firstDefined(value, nested, ['isError', 'is_error']) ?? (value.ok === false || nested?.ok === false ? true : undefined),
|
|
139
139
|
errorCode: firstDefined(value, nested, ['errorCode', 'error_code']),
|
|
140
|
+
errorDetailCode: firstDefined(value, nested, ['errorDetailCode', 'detail_code', 'detailCode']),
|
|
141
|
+
classificationMissing: firstDefined(value, nested, ['classificationMissing', 'classification_missing']),
|
|
142
|
+
classificationConflict: firstDefined(value, nested, ['classificationConflict', 'classification_conflict']),
|
|
143
|
+
exitCode: firstDefined(value, nested, ['exitCode', 'exit_code']),
|
|
140
144
|
decision: firstDefined(value, nested, ['decision']),
|
|
141
145
|
decisionSource: firstDefined(value, nested, ['decisionSource', 'decision_source']),
|
|
142
146
|
policyCode: firstDefined(value, nested, ['policyCode', 'policy_code']),
|
|
@@ -3,6 +3,7 @@ import crypto from 'crypto';
|
|
|
3
3
|
import { authorizeOperation, buildAuthSubject } from './auth-gateway.js';
|
|
4
4
|
import { formatPeerKey, parsePeerKey } from '../relation/peer-identity.js';
|
|
5
5
|
import { logger } from '../../utils/logger.js';
|
|
6
|
+
import { canonicalizeEvolcoreCommandArgv } from '../permission/ec-command-parser.js';
|
|
6
7
|
export const AGENT_DELEGATION_TOKEN_ENV = 'EVOLCORE_DELEGATION_TOKEN';
|
|
7
8
|
export const CODEX_SESSION_TOKEN_ENV = 'EVOLCORE_CODEX_SESSION_TOKEN';
|
|
8
9
|
export const AGENT_DELEGATION_COMMAND_TTL_MS = 5 * 60_000;
|
|
@@ -279,5 +280,5 @@ export function hashDelegatedCommandArgv(argv) {
|
|
|
279
280
|
export function hashCurrentDelegatedCommand(processArgv = process.argv) {
|
|
280
281
|
if (processArgv.length < 3)
|
|
281
282
|
return undefined;
|
|
282
|
-
return hashDelegatedCommandArgv(['ec', ...processArgv.slice(2)]);
|
|
283
|
+
return hashDelegatedCommandArgv(canonicalizeEvolcoreCommandArgv(['ec', ...processArgv.slice(2)]));
|
|
283
284
|
}
|
|
@@ -76,6 +76,7 @@ export function buildAuthSubject(input) {
|
|
|
76
76
|
: roleDetail.allowAccess && checkRoleAccess(role, input.selfAid)),
|
|
77
77
|
canApprovePersistentFullAccess: input.canApprovePersistentFullAccess
|
|
78
78
|
?? (isDaemonOwner && !isDaemonService),
|
|
79
|
+
auditMetadata: input.auditMetadata,
|
|
79
80
|
permissionMode: isFullAccessRun
|
|
80
81
|
? 'fullaccess'
|
|
81
82
|
: input.permissionMode
|
|
@@ -184,9 +185,12 @@ function resolveRoleDetail(input) {
|
|
|
184
185
|
});
|
|
185
186
|
}
|
|
186
187
|
function auditDecision(params, decision) {
|
|
188
|
+
const roleDenial = !decision.allow && decision.code === 'ROLE_ACCESS_DENIED';
|
|
187
189
|
auditCommandAuthorization({
|
|
188
190
|
ts: Date.now(),
|
|
189
191
|
...params.auditMetadata,
|
|
192
|
+
...params.subject.auditMetadata,
|
|
193
|
+
eventPhase: params.auditMetadata?.eventPhase ?? 'final',
|
|
190
194
|
correlationId: params.auditMetadata?.correlationId ?? params.auditMetadata?.requestId ?? params.subject.requestId,
|
|
191
195
|
requestId: params.auditMetadata?.requestId ?? params.subject.requestId,
|
|
192
196
|
sessionId: params.auditMetadata?.sessionId ?? params.subject.sessionId,
|
|
@@ -198,13 +202,16 @@ function auditDecision(params, decision) {
|
|
|
198
202
|
errorCode: params.auditMetadata?.errorCode
|
|
199
203
|
?? (decision.allow
|
|
200
204
|
? undefined
|
|
201
|
-
:
|
|
202
|
-
? '
|
|
203
|
-
: params.auditMetadata?.decisionSource === '
|
|
204
|
-
? '
|
|
205
|
-
: '
|
|
205
|
+
: roleDenial
|
|
206
|
+
? 'ROLE_DENIED'
|
|
207
|
+
: params.auditMetadata?.decisionSource === 'approval'
|
|
208
|
+
? 'USER_DENIED'
|
|
209
|
+
: params.auditMetadata?.decisionSource === 'infrastructure'
|
|
210
|
+
? 'EXECUTION_FAILED'
|
|
211
|
+
: 'POLICY_DENIED'),
|
|
206
212
|
policyCode: params.auditMetadata?.policyCode ?? (decision.allow ? undefined : decision.code),
|
|
207
|
-
decisionSource: params.auditMetadata?.decisionSource
|
|
213
|
+
decisionSource: params.auditMetadata?.decisionSource
|
|
214
|
+
?? (decision.allow ? 'command' : roleDenial ? 'role' : 'policy'),
|
|
208
215
|
source: params.source,
|
|
209
216
|
operation: params.intent.operation,
|
|
210
217
|
scope: params.intent.scope,
|