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
|
@@ -4,6 +4,7 @@ import { resolvePaths } from '../../paths.js';
|
|
|
4
4
|
import crypto from 'node:crypto';
|
|
5
5
|
import { buildAuthorizationEventKey, buildToolLifecycleEventKey, normalizeToolCorrelation } from '../audit/event-key.js';
|
|
6
6
|
import { normalizeExecutionPermissionMode } from '../permission/mode.js';
|
|
7
|
+
import { normalizeToolErrorClassification } from '../permission/tool-error-code.js';
|
|
7
8
|
export function auditCommandAuthorization(event) {
|
|
8
9
|
const shouldAudit = event.source === 'menu.cli' ||
|
|
9
10
|
event.decision === 'deny' ||
|
|
@@ -101,6 +102,13 @@ export function auditFullAccessEvent(input) {
|
|
|
101
102
|
* denials otherwise only reach `logger.warn` and `TriggerExecutionAnomaly`.
|
|
102
103
|
*/
|
|
103
104
|
export function auditToolPreflightDenial(input) {
|
|
105
|
+
const classification = normalizeToolErrorClassification({
|
|
106
|
+
errorCode: 'POLICY_DENIED',
|
|
107
|
+
decisionSource: 'policy',
|
|
108
|
+
policyCode: input.policyCode,
|
|
109
|
+
executed: false,
|
|
110
|
+
executionState: 'blocked',
|
|
111
|
+
});
|
|
104
112
|
auditCommandAuthorization({
|
|
105
113
|
ts: Date.now(),
|
|
106
114
|
eventKey: buildToolLifecycleEventKey(input),
|
|
@@ -114,7 +122,8 @@ export function auditToolPreflightDenial(input) {
|
|
|
114
122
|
executed: false,
|
|
115
123
|
executionState: 'blocked',
|
|
116
124
|
decisionSource: 'policy',
|
|
117
|
-
errorCode:
|
|
125
|
+
errorCode: classification.errorCode,
|
|
126
|
+
...(classification.errorDetailCode ? { errorDetailCode: classification.errorDetailCode } : {}),
|
|
118
127
|
toolName: input.toolName,
|
|
119
128
|
policyCode: input.policyCode,
|
|
120
129
|
protectionClass: input.protectionClass ?? protectionClassForPolicy(input.policyCode),
|
|
@@ -158,6 +167,7 @@ export function auditCodexApprovalDecision(input) {
|
|
|
158
167
|
errorCode: input.decision === 'deny'
|
|
159
168
|
? input.decisionSource === 'approval' ? 'USER_DENIED' : input.decisionSource === 'policy' ? 'POLICY_DENIED' : infrastructureErrorCode(input.policyCode)
|
|
160
169
|
: undefined,
|
|
170
|
+
...(input.errorDetailCode ? { errorDetailCode: input.errorDetailCode } : {}),
|
|
161
171
|
sessionId: input.sessionId ?? 'unknown',
|
|
162
172
|
agentAid: input.agentAid ?? 'unknown',
|
|
163
173
|
agentName: input.agentName,
|
|
@@ -313,14 +323,25 @@ function infrastructureErrorCode(policyCode) {
|
|
|
313
323
|
}
|
|
314
324
|
function buildAuditRecord(event) {
|
|
315
325
|
const executed = event.executed ?? false;
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
326
|
+
const roleDenial = event.decision === 'deny'
|
|
327
|
+
&& (event.errorCode === 'ROLE_DENIED'
|
|
328
|
+
|| event.code === 'ROLE_ACCESS_DENIED'
|
|
329
|
+
|| event.policyCode === 'ROLE_ACCESS_DENIED');
|
|
330
|
+
const decisionSource = event.decisionSource
|
|
331
|
+
?? (roleDenial
|
|
332
|
+
? 'role'
|
|
333
|
+
: event.decision === 'deny' ? 'policy' : event.decision === 'pending' ? 'approval' : 'command');
|
|
334
|
+
const executionFailed = executed
|
|
335
|
+
&& (event.executionState === 'failed' || (event.exitCode !== undefined && event.exitCode !== 0));
|
|
336
|
+
const rawErrorCode = event.errorCode ?? (event.decision === 'deny'
|
|
337
|
+
? decisionSource === 'role'
|
|
338
|
+
? 'ROLE_DENIED'
|
|
339
|
+
: decisionSource === 'approval'
|
|
340
|
+
? 'USER_DENIED'
|
|
341
|
+
: decisionSource === 'policy'
|
|
342
|
+
? 'POLICY_DENIED'
|
|
343
|
+
: 'EXECUTION_FAILED'
|
|
344
|
+
: executionFailed ? 'EXECUTION_FAILED' : undefined);
|
|
324
345
|
const executionState = event.executionState
|
|
325
346
|
?? (event.decision === 'deny'
|
|
326
347
|
? 'blocked'
|
|
@@ -329,25 +350,35 @@ function buildAuditRecord(event) {
|
|
|
329
350
|
: executed
|
|
330
351
|
? (event.exitCode === undefined || event.exitCode === 0 ? 'completed' : 'failed')
|
|
331
352
|
: 'authorized');
|
|
353
|
+
const classification = rawErrorCode !== undefined
|
|
354
|
+
? normalizeToolErrorClassification({
|
|
355
|
+
errorCode: rawErrorCode,
|
|
356
|
+
errorDetailCode: event.errorDetailCode,
|
|
357
|
+
decisionSource,
|
|
358
|
+
executed,
|
|
359
|
+
executionState,
|
|
360
|
+
exitCode: event.exitCode,
|
|
361
|
+
policyCode: event.policyCode,
|
|
362
|
+
})
|
|
363
|
+
: undefined;
|
|
364
|
+
const errorCode = classification?.errorCode;
|
|
332
365
|
const ecwebRequestId = event.source === 'ecweb' ? event.ecwebRequestId : undefined;
|
|
333
366
|
const requestId = event.requestId ?? ecwebRequestId;
|
|
334
367
|
const correlationId = event.correlationId ?? event.callId ?? requestId;
|
|
335
|
-
const lifecycleId = event.callId ?? correlationId ?? requestId;
|
|
336
368
|
return {
|
|
369
|
+
type: 'authorization:audit',
|
|
337
370
|
ts: event.ts,
|
|
338
371
|
eventKey: event.eventKey ?? (ecwebRequestId
|
|
339
372
|
? `ecweb:${crypto.createHash('sha256').update(JSON.stringify([
|
|
340
373
|
ecwebRequestId, event.targetAgentAid ?? event.selfAid, event.operation,
|
|
341
374
|
])).digest('hex').slice(0, 20)}`
|
|
342
|
-
:
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
})
|
|
350
|
-
: undefined),
|
|
375
|
+
: buildAuthorizationEventKey({
|
|
376
|
+
sessionId: event.sessionId,
|
|
377
|
+
callId: event.callId,
|
|
378
|
+
correlationId,
|
|
379
|
+
requestId,
|
|
380
|
+
operation: event.operation,
|
|
381
|
+
})),
|
|
351
382
|
eventPhase: event.eventPhase,
|
|
352
383
|
callId: event.callId,
|
|
353
384
|
correlationId,
|
|
@@ -360,6 +391,9 @@ function buildAuditRecord(event) {
|
|
|
360
391
|
toolName: event.toolName,
|
|
361
392
|
approvalMethod: event.approvalMethod,
|
|
362
393
|
errorCode,
|
|
394
|
+
errorDetailCode: classification?.errorDetailCode,
|
|
395
|
+
classificationMissing: classification?.classificationMissing || event.classificationMissing,
|
|
396
|
+
classificationConflict: classification?.classificationConflict || event.classificationConflict,
|
|
363
397
|
policyCode: event.policyCode ?? event.code,
|
|
364
398
|
protectionClass: event.protectionClass,
|
|
365
399
|
matchedPath: event.matchedPath,
|
|
@@ -459,6 +493,7 @@ function logAuditEvent(record) {
|
|
|
459
493
|
record.correlationId ? `correlation=${record.correlationId}` : null,
|
|
460
494
|
record.eventKey ? `eventKey=${record.eventKey}` : null,
|
|
461
495
|
record.eventPhase ? `eventPhase=${record.eventPhase}` : null,
|
|
496
|
+
record.sessionScope ? `sessionScope=${record.sessionScope}` : null,
|
|
462
497
|
record.sessionId ? `session=${record.sessionId}` : null,
|
|
463
498
|
record.agentName ? `agentName=${JSON.stringify(record.agentName)}` : null,
|
|
464
499
|
record.agentAid ? `agent=${record.agentAid}` : null,
|
|
@@ -41,6 +41,10 @@ const DAEMON_SERVICE_OPERATIONS = new Set([
|
|
|
41
41
|
'system.restart',
|
|
42
42
|
'system.upgrade',
|
|
43
43
|
]);
|
|
44
|
+
const DAEMON_OWNER_MODEL_OPTION_READ_OPERATIONS = new Set([
|
|
45
|
+
'model.list',
|
|
46
|
+
'model.effort.current',
|
|
47
|
+
]);
|
|
44
48
|
export function authorizeCommand(ctx) {
|
|
45
49
|
return authorizeCommandInternal(ctx);
|
|
46
50
|
}
|
|
@@ -186,6 +190,19 @@ function authorizeCommandInternal(ctx, resolvedConfigCommand) {
|
|
|
186
190
|
matchedRule: 'daemon-service',
|
|
187
191
|
};
|
|
188
192
|
}
|
|
193
|
+
if (ctx.processRole === 'daemon-owner'
|
|
194
|
+
&& ctx.fromControlChannel
|
|
195
|
+
&& (intent.scope === 'relation' || intent.scope === 'agent')
|
|
196
|
+
&& DAEMON_OWNER_MODEL_OPTION_READ_OPERATIONS.has(operation)) {
|
|
197
|
+
return {
|
|
198
|
+
allow: true,
|
|
199
|
+
operation,
|
|
200
|
+
scope: intent.scope,
|
|
201
|
+
role: 'daemon-owner',
|
|
202
|
+
dangerous: opMeta.dangerous,
|
|
203
|
+
matchedRule: 'daemon-owner-model-options-read',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
189
206
|
if (requiresDaemonOwner(ctx, resolvedConfigCommand)) {
|
|
190
207
|
if (!hasDaemonOwnerRole(ctx)) {
|
|
191
208
|
const reasonCode = daemonOwnerDenialReasonCode(ctx);
|
|
@@ -53,6 +53,7 @@ const GROUP_MANAGEMENT_OPERATIONS = [
|
|
|
53
53
|
['ec.group.blocklist', 'read', ['agent'], 'Read the group block list'],
|
|
54
54
|
['ec.group.report-status', 'write-own', ['relation', 'agent'], 'Report the current Agent group status'],
|
|
55
55
|
['ec.group.member-statuses', 'read', ['relation', 'agent'], 'Read reported group member statuses'],
|
|
56
|
+
['ec.group.mention', 'write-own', ['relation', 'agent'], 'Read or update the group mention mode'],
|
|
56
57
|
['ec.group.rules.set', 'write-agent', ['agent'], 'Upload and publish group rules content'],
|
|
57
58
|
['ec.group.rules.publish', 'write-agent', ['agent'], 'Publish the current group rules file'],
|
|
58
59
|
['ec.group.rules.update', 'write-agent', ['agent'], 'Update group join rules'],
|
|
@@ -799,6 +800,14 @@ const OPERATIONS = [
|
|
|
799
800
|
description: '查看当前中间活动显示策略',
|
|
800
801
|
sources: ['menu'],
|
|
801
802
|
},
|
|
803
|
+
{
|
|
804
|
+
id: 'task.activity.read',
|
|
805
|
+
category: 'read',
|
|
806
|
+
dangerous: false,
|
|
807
|
+
defaultScopes: ['relation'],
|
|
808
|
+
description: '读取当前关系内任务的 Activity 列表和详情',
|
|
809
|
+
sources: ['menu'],
|
|
810
|
+
},
|
|
802
811
|
{
|
|
803
812
|
id: 'activity.update',
|
|
804
813
|
category: 'write-agent',
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
2
|
import { CAUSATION_VERSION, MAX_TRIGGER_CAUSATION_DEPTH, } from './types.js';
|
|
3
|
-
|
|
3
|
+
// Trigger identifiers may be daemon-owned and conventionally begin with
|
|
4
|
+
// underscores (for example, `__session-idle-check`). Internal trace/span IDs
|
|
5
|
+
// are still generated with alphabetic prefixes, so accepting `_` here only
|
|
6
|
+
// broadens validation for persisted/propagated trigger and run IDs.
|
|
7
|
+
const ID_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9._:-]{0,127}$/;
|
|
4
8
|
function newId(prefix) {
|
|
5
9
|
return `${prefix}_${crypto.randomUUID().replace(/-/g, '')}`;
|
|
6
10
|
}
|
|
@@ -750,8 +750,7 @@ export async function execAgentQuery(args, service, subject) {
|
|
|
750
750
|
canConfigure: subject?.ecwebManagement === true
|
|
751
751
|
&& subject?.isDaemonOwner === true
|
|
752
752
|
&& subject.canApprovePersistentFullAccess !== false
|
|
753
|
-
&& subject.chatType !== 'group'
|
|
754
|
-
&& fullaccessStatus.hostEnabled,
|
|
753
|
+
&& subject.chatType !== 'group',
|
|
755
754
|
},
|
|
756
755
|
};
|
|
757
756
|
// 叠加构建进度(create 受理后、ready 前可见;ready 后文件仍在,可反映软失败 warn)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { BaseagentRunnerUnavailableError } from '../../agents/runner-types.js';
|
|
2
2
|
import { loadedBaseagentIds } from '../../agents/baseagent-availability.js';
|
|
3
|
+
import { closeDiagnosticSession, diagnosticTokenHash, isDiagnosticSessionActive } from './diag-service.js';
|
|
3
4
|
import { parseMenuClientArgs } from '../../cli/menu-client.js';
|
|
4
5
|
import { ensureSessionRuntimeDir } from '../../cli/task-context.js';
|
|
5
6
|
import { renderCommandCardAsText } from '../interaction-router.js';
|
|
6
7
|
import { buildEnvelope, deliveryTargetFromSession, isInteractionSendAccepted, replyContextFromSession, sendInteractionPayload } from '../message/message-utils.js';
|
|
7
8
|
import { resolvePaths, getPackageRoot } from '../../paths.js';
|
|
8
|
-
import {
|
|
9
|
+
import { loadDaemonConfig } from '../../config-store.js';
|
|
9
10
|
import { logger } from '../../utils/logger.js';
|
|
10
11
|
import { resolvePeerRoleDetail, roleToSessionIdentity } from '../../config/peer-role-resolver.js';
|
|
11
12
|
import { isManagementRole } from '../../config/builtin-roles.js';
|
|
@@ -19,7 +20,7 @@ import { applyTriggerPatch, replaceEditableTriggerDefinition } from '../../trigg
|
|
|
19
20
|
import { definitionRevision } from '../../trigger/validation.js';
|
|
20
21
|
import { tryParseChannelKey } from '../channel-loader.js';
|
|
21
22
|
import { displaySessionTitle } from '../session/session-title.js';
|
|
22
|
-
import {
|
|
23
|
+
import { buildTranscriptTurns } from '../session/session-transcript.js';
|
|
23
24
|
import { resolveConfigCommand } from '../../config/resolved-config-op.js';
|
|
24
25
|
import { AUTHENTICATED_CONFIG_ROLE_ENV, executeResolvedConfigCommandAsync } from '../../config/config-operation-service.js';
|
|
25
26
|
import { splitConfigBatchGetArgv } from '../../cli/cli-argv.js';
|
|
@@ -27,6 +28,7 @@ import { auditCommandAuthorization, auditFullAccessEvent, hashArgv } from '../au
|
|
|
27
28
|
import { executeResolvedContactCommand, resolveContactCommand } from '../../config/contact-operation-service.js';
|
|
28
29
|
import { hasTrustedFullAccessDelegation, trustedExecutionIdentityInput } from '../auth/agent-delegation.js';
|
|
29
30
|
import { executeManagedAidOperation, ManagedAidOperationError, managedAidShowViewForRole, resolveManagedAidOperation, } from '../../aun/aid/managed-operation.js';
|
|
31
|
+
import { MAX_AVATAR_SOURCE_BYTES } from '../../utils/avatar-upload.js';
|
|
30
32
|
import { executeManagedGroupOperation, isManagedGroupRelationRead, isManagedGroupRelationWrite, ManagedGroupOperationError, resolveManagedGroupOperation, executeManagedMsgOperation, ManagedMsgOperationError, resolveManagedMsgOperation, executeManagedFsOperation, ManagedFsOperationError, resolveManagedFsOperation, } from '../../aun/msg/managed-operation.js';
|
|
31
33
|
import { authorizeOperation, buildAuthSubject } from '../auth/auth-gateway.js';
|
|
32
34
|
import { isHClassPath, isLClassPath, isSameOrDescendant } from '../permission/protected-paths.js';
|
|
@@ -37,7 +39,7 @@ import { parsePeerKey } from '../relation/peer-identity.js';
|
|
|
37
39
|
import { isQuickCommand } from './slash-gate.js';
|
|
38
40
|
import { handleSlashCommand } from './slash-handler.js';
|
|
39
41
|
import { resolveChatMode } from '../message/peer-mode.js';
|
|
40
|
-
import { execMenuAction as menuExecMenuAction, execMenuForEcweb as menuExecMenuForEcweb, execMenuForControl as menuExecMenuForControl, execMenuQuery as menuExecMenuQuery, execMenuUpdate as menuExecMenuUpdate, getMenuItems as menuGetMenuItems, getSubMenuItems as menuGetSubMenuItems, } from './menu-handler.js';
|
|
42
|
+
import { execMenuAction as menuExecMenuAction, execMenuForEcweb as menuExecMenuForEcweb, execMenuForControl as menuExecMenuForControl, execMenuQuery as menuExecMenuQuery, execMenuUpdate as menuExecMenuUpdate, getMenuItems as menuGetMenuItems, getSubMenuItems as menuGetSubMenuItems, buildTopicForkSourcePayload, } from './menu-handler.js';
|
|
41
43
|
import { getMenuCatalog, execMenuValueBatch, validateMenuValueBatchArgs } from './menu-catalog.js';
|
|
42
44
|
export { isProcessLevelOwner } from './menu-handler.js';
|
|
43
45
|
const CLI_EXEC_TIMEOUT_MS = 15_000;
|
|
@@ -123,6 +125,7 @@ export class CommandHandler {
|
|
|
123
125
|
legacySingleRunnerMode;
|
|
124
126
|
primaryRunnerKey;
|
|
125
127
|
agentRegistry;
|
|
128
|
+
memoryConsolidationLauncher;
|
|
126
129
|
agentApplicationService;
|
|
127
130
|
triggerSchedulerResolver;
|
|
128
131
|
triggerSchedulerFallback;
|
|
@@ -166,7 +169,34 @@ export class CommandHandler {
|
|
|
166
169
|
throw new Error('Menu request file must be a regular file of at most 128 KiB');
|
|
167
170
|
return fs.readFileSync(target, 'utf8');
|
|
168
171
|
});
|
|
169
|
-
|
|
172
|
+
const binding = session.metadata?.diagnostic;
|
|
173
|
+
if (binding || session.metadata?.diagnosticStatus === 'cancelled') {
|
|
174
|
+
if (!isDiagnosticSessionActive(session, this.sessionManager.getChatDir(session))) {
|
|
175
|
+
return { ok: false, code: 'DIAG_CLOSED', error: '诊断授权已结束,禁止旧会话继续访问' };
|
|
176
|
+
}
|
|
177
|
+
if (binding && (options.targetAid !== binding.controlAid
|
|
178
|
+
|| diagnosticTokenHash(options.remoteAccessToken ?? options.ecwebToken ?? '') !== binding.tokenHash)) {
|
|
179
|
+
return { ok: false, code: 'DIAG_SCOPE_MISMATCH', error: '诊断请求必须使用本会话绑定的主机和 Token' };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const guardedOptions = binding
|
|
183
|
+
? {
|
|
184
|
+
...options,
|
|
185
|
+
beforeSend: () => {
|
|
186
|
+
if (!isDiagnosticSessionActive(session, this.sessionManager.getChatDir(session))) {
|
|
187
|
+
const error = new Error('诊断授权已结束,禁止旧会话继续访问');
|
|
188
|
+
error.code = 'DIAG_CLOSED';
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
: options;
|
|
194
|
+
const response = await send(guardedOptions);
|
|
195
|
+
if (binding && response?.error?.code === 'REMOTE_ACCESS_TOKEN_INVALID') {
|
|
196
|
+
closeDiagnosticSession(session, this.sessionManager.getChatDir(session));
|
|
197
|
+
this.messageQueue?.clearBySession(session.id);
|
|
198
|
+
}
|
|
199
|
+
return { ok: true, response };
|
|
170
200
|
}
|
|
171
201
|
catch (error) {
|
|
172
202
|
return { ok: false, code: error.code ?? 'MENU_REQUEST_FAILED', error: error.message };
|
|
@@ -482,8 +512,6 @@ export class CommandHandler {
|
|
|
482
512
|
if (!mode)
|
|
483
513
|
return undefined;
|
|
484
514
|
if (mode === 'fullaccess') {
|
|
485
|
-
if (!isFullAccessEnabled())
|
|
486
|
-
return 'fullaccess 功能未启用';
|
|
487
515
|
return canApprovePersistentFullAccess ? undefined : '无权限:只有 daemon-owner 可以配置 fullaccess Trigger';
|
|
488
516
|
}
|
|
489
517
|
if (!role) {
|
|
@@ -901,6 +929,10 @@ export class CommandHandler {
|
|
|
901
929
|
setStatsCollector(collector) {
|
|
902
930
|
this.statsCollector = collector;
|
|
903
931
|
}
|
|
932
|
+
/** 注入记忆整理入口(daemon 的统一整理队列),供 /memory consolidate 使用。返回 null 表示已入队。 */
|
|
933
|
+
setMemoryConsolidationLauncher(launcher) {
|
|
934
|
+
this.memoryConsolidationLauncher = launcher;
|
|
935
|
+
}
|
|
904
936
|
registerAdapter(adapter) {
|
|
905
937
|
this.adapters.set(adapter.channelName, adapter);
|
|
906
938
|
}
|
|
@@ -1017,8 +1049,12 @@ export class CommandHandler {
|
|
|
1017
1049
|
const item = {
|
|
1018
1050
|
value: s.threadId,
|
|
1019
1051
|
label: displayName,
|
|
1020
|
-
|
|
1052
|
+
topicLabel: s.label || null,
|
|
1053
|
+
topicStatus: s.topicStatus ?? 'pending',
|
|
1021
1054
|
};
|
|
1055
|
+
const forkSource = buildTopicForkSourcePayload(s);
|
|
1056
|
+
if (forkSource)
|
|
1057
|
+
item.forkSource = forkSource;
|
|
1022
1058
|
if (s.agentSessionId) {
|
|
1023
1059
|
item.agentSessionId = s.agentSessionId;
|
|
1024
1060
|
const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
|
|
@@ -1332,8 +1368,8 @@ export class CommandHandler {
|
|
|
1332
1368
|
}
|
|
1333
1369
|
if (sub.startsWith('enable ')) {
|
|
1334
1370
|
const { definition } = extractAndFindTrigger(sub, 'enable ', 'enable');
|
|
1335
|
-
if (definition.execution.permissionMode === 'fullaccess' &&
|
|
1336
|
-
return '❌ 只有 daemon-owner 可以启用 fullaccess Trigger
|
|
1371
|
+
if (definition.execution.permissionMode === 'fullaccess' && !isDaemonOwner) {
|
|
1372
|
+
return '❌ 只有 daemon-owner 可以启用 fullaccess Trigger';
|
|
1337
1373
|
}
|
|
1338
1374
|
if (definition.execution.permissionMode === 'fullaccess' && !canApprovePersistentFullAccess) {
|
|
1339
1375
|
return '❌ 当前认证通道不能批准持久 fullaccess Trigger';
|
|
@@ -1543,9 +1579,7 @@ export class CommandHandler {
|
|
|
1543
1579
|
return {
|
|
1544
1580
|
ok: false,
|
|
1545
1581
|
error: permissionError,
|
|
1546
|
-
code:
|
|
1547
|
-
: /无权限|只有 daemon-owner/.test(permissionError) ? 'FORBIDDEN'
|
|
1548
|
-
: undefined,
|
|
1582
|
+
code: /无权限|只有 daemon-owner/.test(permissionError) ? 'FORBIDDEN' : undefined,
|
|
1549
1583
|
};
|
|
1550
1584
|
}
|
|
1551
1585
|
const runtimeFieldError = this.validateTriggerRuntimeFields(updated, triggerRole.role, triggerRole.baseagent);
|
|
@@ -1631,7 +1665,7 @@ export class CommandHandler {
|
|
|
1631
1665
|
async handleRewindList(session, agent) {
|
|
1632
1666
|
try {
|
|
1633
1667
|
const messages = await agent.getSessionMessages(session.agentSessionId, session.projectPath);
|
|
1634
|
-
const turns =
|
|
1668
|
+
const turns = buildTranscriptTurns(messages);
|
|
1635
1669
|
if (turns.length === 0) {
|
|
1636
1670
|
return '📋 当前会话暂无对话记录';
|
|
1637
1671
|
}
|
|
@@ -1651,8 +1685,11 @@ export class CommandHandler {
|
|
|
1651
1685
|
}
|
|
1652
1686
|
async handleRewind(session, agent, turnNum, mode) {
|
|
1653
1687
|
try {
|
|
1688
|
+
if (session.threadId && turnNum === 1) {
|
|
1689
|
+
return '❌ 话题会话暂不支持 /rewind 1,仅开放 N>1';
|
|
1690
|
+
}
|
|
1654
1691
|
const messages = await agent.getSessionMessages(session.agentSessionId, session.projectPath);
|
|
1655
|
-
const turns =
|
|
1692
|
+
const turns = buildTranscriptTurns(messages);
|
|
1656
1693
|
if (turnNum < 1 || turnNum > turns.length) {
|
|
1657
1694
|
return `❌ 轮次超出范围,当前共 ${turns.length} 轮`;
|
|
1658
1695
|
}
|
|
@@ -1688,19 +1725,38 @@ export class CommandHandler {
|
|
|
1688
1725
|
if (mode === 'chat' || mode === 'all') {
|
|
1689
1726
|
const discarded = turns.length - turnNum + 1;
|
|
1690
1727
|
if (agent.rollbackSessionTurns) {
|
|
1691
|
-
const ok = await agent.rollbackSessionTurns(session.agentSessionId, session.projectPath, discarded);
|
|
1728
|
+
const ok = await agent.rollbackSessionTurns(session.agentSessionId, session.projectPath, discarded, rewindTarget.assistantUuid);
|
|
1692
1729
|
if (!ok)
|
|
1693
1730
|
return '❌ 对话回退失败';
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1731
|
+
if (session.threadId) {
|
|
1732
|
+
await this.sessionManager.clearTopicResumeAt({
|
|
1733
|
+
sessionId: session.id,
|
|
1734
|
+
expectedThreadId: session.threadId,
|
|
1735
|
+
expectedAgentSessionId: session.agentSessionId,
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
else {
|
|
1739
|
+
const meta = { ...(session.metadata || {}) };
|
|
1740
|
+
delete meta.resumeAt;
|
|
1741
|
+
await this.sessionManager.updateSession(session.id, { metadata: meta });
|
|
1742
|
+
}
|
|
1697
1743
|
}
|
|
1698
1744
|
else if (keepTarget) {
|
|
1699
|
-
|
|
1700
|
-
|
|
1745
|
+
if (session.threadId) {
|
|
1746
|
+
await this.sessionManager.setTopicResumeAt({
|
|
1747
|
+
sessionId: session.id,
|
|
1748
|
+
expectedThreadId: session.threadId,
|
|
1749
|
+
expectedAgentSessionId: session.agentSessionId,
|
|
1750
|
+
resumeAt: keepTarget.assistantUuid,
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
else {
|
|
1754
|
+
const meta = { ...(session.metadata || {}), resumeAt: keepTarget.assistantUuid };
|
|
1755
|
+
await this.sessionManager.updateSession(session.id, { metadata: meta });
|
|
1756
|
+
}
|
|
1701
1757
|
}
|
|
1702
1758
|
else {
|
|
1703
|
-
// N=1
|
|
1759
|
+
// N=1:撤销全部对话,清空主会话 session 从头开始
|
|
1704
1760
|
const meta = { ...(session.metadata || {}) };
|
|
1705
1761
|
delete meta.resumeAt;
|
|
1706
1762
|
await this.sessionManager.updateSession(session.id, {
|
|
@@ -2102,15 +2158,15 @@ export class CommandHandler {
|
|
|
2102
2158
|
if (realManagedTempPath && isSameOrDescendant(realPath, realManagedTempPath) && stat.nlink > 1) {
|
|
2103
2159
|
return { ok: false, code: 'INVALID_AVATAR_PATH', error: 'Avatar source cannot be a hard link inside managed TMPDIR' };
|
|
2104
2160
|
}
|
|
2105
|
-
if (stat.size < 1 || stat.size >
|
|
2106
|
-
return { ok: false, code: 'INVALID_AVATAR_FILE', error: 'Avatar source must be between 1 byte and
|
|
2161
|
+
if (stat.size < 1 || stat.size > MAX_AVATAR_SOURCE_BYTES) {
|
|
2162
|
+
return { ok: false, code: 'INVALID_AVATAR_FILE', error: 'Avatar source must be between 1 byte and 10 MiB' };
|
|
2107
2163
|
}
|
|
2108
2164
|
// Open the user-supplied node with no-follow semantics after checking
|
|
2109
2165
|
// its canonical ancestors; the bytes passed to the uploader come from
|
|
2110
2166
|
// this descriptor rather than from a second path lookup.
|
|
2111
2167
|
fd = fs.openSync(resolvedPath, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
|
|
2112
2168
|
const finalStat = fs.fstatSync(fd);
|
|
2113
|
-
if (!finalStat.isFile() || finalStat.size < 1 || finalStat.size >
|
|
2169
|
+
if (!finalStat.isFile() || finalStat.size < 1 || finalStat.size > MAX_AVATAR_SOURCE_BYTES || finalStat.nlink !== stat.nlink) {
|
|
2114
2170
|
return { ok: false, code: 'INVALID_AVATAR_FILE', error: 'Avatar source changed during validation' };
|
|
2115
2171
|
}
|
|
2116
2172
|
avatarBuffer = fs.readFileSync(fd);
|