evolcore 0.0.28 → 0.0.29
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 +12 -0
- package/bin/ec-safe-output.js +270 -54
- package/dist/agents/baseagent-availability.js +37 -1
- package/dist/agents/baseagent.js +19 -9
- package/dist/agents/claude-runner.js +171 -13
- package/dist/agents/codex/app-server-client.js +6 -2
- package/dist/agents/codex/diagnostics.js +4 -3
- package/dist/agents/codex-runner.js +396 -95
- 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/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 +249 -89
- 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 +40 -10
- package/dist/cli/data-command.js +4 -4
- 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/restart-monitor.js +62 -6
- 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 +51 -23
- 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 +315 -60
- package/dist/core/command/menu-protocol.js +42 -4
- package/dist/core/command/slash-gate.js +10 -10
- package/dist/core/command/slash-handler.js +206 -64
- 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 +69 -16
- package/dist/core/message/message-bridge.js +287 -21
- 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 +567 -80
- package/dist/core/permission/ec-command-parser.js +1029 -80
- 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 +276 -23
- 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 +478 -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 +708 -18
- package/dist/ipc.js +564 -2
- package/dist/paths.js +30 -9
- 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/avatar-upload.js +59 -18
- 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/welcome.js +37 -8
- 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/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
|
@@ -19,6 +19,7 @@ export class MessageQueue {
|
|
|
19
19
|
activeStates = new Map(); // queueKey → active task state
|
|
20
20
|
interruptCallback;
|
|
21
21
|
interruptBarriers = new Map();
|
|
22
|
+
interruptFailures = new Map();
|
|
22
23
|
activeTerminalReasons = new Map();
|
|
23
24
|
eventBus;
|
|
24
25
|
recentMessageIds = new Set();
|
|
@@ -53,7 +54,7 @@ export class MessageQueue {
|
|
|
53
54
|
setInterruptCallback(callback) {
|
|
54
55
|
this.interruptCallback = callback;
|
|
55
56
|
}
|
|
56
|
-
triggerInterrupt(queueKey, sessionKey, baseagent, evolagentName, reason, timeout) {
|
|
57
|
+
triggerInterrupt(queueKey, sessionKey, baseagent, evolagentName, reason, timeout, strict) {
|
|
57
58
|
const existing = this.interruptBarriers.get(queueKey);
|
|
58
59
|
if (existing)
|
|
59
60
|
return existing;
|
|
@@ -62,15 +63,20 @@ export class MessageQueue {
|
|
|
62
63
|
this.activeTerminalReasons.set(queueKey, reason);
|
|
63
64
|
let interruption;
|
|
64
65
|
try {
|
|
65
|
-
interruption = Promise.resolve(
|
|
66
|
-
? this.interruptCallback(sessionKey, baseagent, evolagentName, reason, timeout)
|
|
67
|
-
:
|
|
66
|
+
interruption = Promise.resolve(strict
|
|
67
|
+
? this.interruptCallback(sessionKey, baseagent, evolagentName, reason, timeout, true)
|
|
68
|
+
: timeout
|
|
69
|
+
? this.interruptCallback(sessionKey, baseagent, evolagentName, reason, timeout)
|
|
70
|
+
: this.interruptCallback(sessionKey, baseagent, evolagentName, reason));
|
|
68
71
|
}
|
|
69
72
|
catch (error) {
|
|
70
73
|
interruption = Promise.reject(error);
|
|
71
74
|
}
|
|
72
75
|
const barrier = interruption
|
|
73
76
|
.catch(error => {
|
|
77
|
+
this.interruptFailures.set(queueKey, error instanceof Error ? error : new Error(String(error)));
|
|
78
|
+
const cleanup = setTimeout(() => this.interruptFailures.delete(queueKey), 60_000);
|
|
79
|
+
cleanup.unref?.();
|
|
74
80
|
logger.warn(`[Queue] Interrupt barrier failed for ${queueKey}: ${error instanceof Error ? error.message : String(error)}`);
|
|
75
81
|
})
|
|
76
82
|
.finally(() => {
|
|
@@ -379,25 +385,35 @@ export class MessageQueue {
|
|
|
379
385
|
}
|
|
380
386
|
messageIdsFor(item) {
|
|
381
387
|
return this.partsOf(item)
|
|
382
|
-
.
|
|
388
|
+
.flatMap(part => [...(part.message.sourceMessageIds ?? []), part.message.messageId])
|
|
383
389
|
.filter((id) => !!id);
|
|
384
390
|
}
|
|
385
391
|
partMatchesMessage(part, messageId, selfAID, queueKey) {
|
|
386
|
-
if (part.message.messageId !== messageId)
|
|
392
|
+
if (part.message.messageId !== messageId && !part.message.sourceMessageIds?.includes(messageId))
|
|
387
393
|
return false;
|
|
388
394
|
if (selfAID === undefined)
|
|
389
395
|
return true;
|
|
390
396
|
const messageScope = part.message.selfAID ?? (queueKey ? this.selfAIDFromQueueKey(queueKey) : undefined);
|
|
391
397
|
return messageScope === selfAID;
|
|
392
398
|
}
|
|
399
|
+
partMatchesScope(part, scope) {
|
|
400
|
+
if (!scope)
|
|
401
|
+
return true;
|
|
402
|
+
const message = part.message;
|
|
403
|
+
if (scope.channelId !== undefined && message.channelId !== scope.channelId)
|
|
404
|
+
return false;
|
|
405
|
+
if (scope.groupId !== undefined && message.groupId !== scope.groupId)
|
|
406
|
+
return false;
|
|
407
|
+
if (scope.threadId !== undefined && (message.threadId || '') !== (scope.threadId || ''))
|
|
408
|
+
return false;
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
393
411
|
peerIdsFor(item) {
|
|
394
412
|
return this.partsOf(item).map(part => part.message.peerId);
|
|
395
413
|
}
|
|
396
414
|
serializePart(part, fallbackEnqueuedAt) {
|
|
397
415
|
const enqueuedAt = part.enqueuedAt ?? part.message.enqueuedAt ?? fallbackEnqueuedAt ?? Date.now();
|
|
398
|
-
const message = part.message
|
|
399
|
-
? part.message
|
|
400
|
-
: { ...part.message, enqueuedAt };
|
|
416
|
+
const message = { ...part.message, enqueuedAt };
|
|
401
417
|
return {
|
|
402
418
|
message,
|
|
403
419
|
projectPath: part.projectPath,
|
|
@@ -408,9 +424,7 @@ export class MessageQueue {
|
|
|
408
424
|
}
|
|
409
425
|
serializeItem(item, fallbackEnqueuedAt) {
|
|
410
426
|
const enqueuedAt = item.enqueuedAt ?? item.message.enqueuedAt ?? fallbackEnqueuedAt ?? Date.now();
|
|
411
|
-
const message = item.message
|
|
412
|
-
? item.message
|
|
413
|
-
: { ...item.message, enqueuedAt };
|
|
427
|
+
const message = { ...item.message, enqueuedAt };
|
|
414
428
|
return {
|
|
415
429
|
message,
|
|
416
430
|
projectPath: item.projectPath,
|
|
@@ -580,6 +594,8 @@ export class MessageQueue {
|
|
|
580
594
|
canDequeueGroupTimeline(first, next) {
|
|
581
595
|
if (first.role === undefined || next.role === undefined)
|
|
582
596
|
return false;
|
|
597
|
+
if (first.message.attentionPolicy !== next.message.attentionPolicy)
|
|
598
|
+
return false;
|
|
583
599
|
if ((first.agentName || DEFAULT_AGENT_NAME) !== (next.agentName || DEFAULT_AGENT_NAME))
|
|
584
600
|
return false;
|
|
585
601
|
if (path.resolve(first.projectPath) !== path.resolve(next.projectPath))
|
|
@@ -678,14 +694,17 @@ export class MessageQueue {
|
|
|
678
694
|
const buckets = [];
|
|
679
695
|
const activeBuckets = [];
|
|
680
696
|
for (const [queueKey, queue] of this.queues.entries()) {
|
|
681
|
-
|
|
697
|
+
const durable = queue.filter(item => item.message.source !== 'owner-inject');
|
|
698
|
+
if (durable.length === 0)
|
|
682
699
|
continue;
|
|
683
700
|
buckets.push({
|
|
684
701
|
queueKey,
|
|
685
|
-
items:
|
|
702
|
+
items: durable.map(item => this.serializeItem(item)),
|
|
686
703
|
});
|
|
687
704
|
}
|
|
688
705
|
for (const [queueKey, item] of this.activeBatches.entries()) {
|
|
706
|
+
if (item.message.source === 'owner-inject')
|
|
707
|
+
continue;
|
|
689
708
|
activeBuckets.push({
|
|
690
709
|
queueKey,
|
|
691
710
|
items: [this.serializeItem(item)],
|
|
@@ -872,6 +891,8 @@ export class MessageQueue {
|
|
|
872
891
|
return sessionIds;
|
|
873
892
|
}
|
|
874
893
|
shouldRestoreMessage(message, sessionId) {
|
|
894
|
+
if (message.source === 'owner-inject')
|
|
895
|
+
return false;
|
|
875
896
|
// The Trigger scheduler records open runs as daemon_restart. Replaying their
|
|
876
897
|
// queued work afterwards would execute side effects for an already-failed run.
|
|
877
898
|
if (message.executionPermissionOverride)
|
|
@@ -896,7 +917,7 @@ export class MessageQueue {
|
|
|
896
917
|
message = { ...message, selfAID: options.selfAID };
|
|
897
918
|
}
|
|
898
919
|
// 消息去重检查
|
|
899
|
-
if (!this.shouldProcess(sessionKey, message, options?.selfAID)) {
|
|
920
|
+
if (message.source !== 'owner-inject' && !this.shouldProcess(sessionKey, message, options?.selfAID)) {
|
|
900
921
|
options?.onPersisted?.();
|
|
901
922
|
return Promise.resolve();
|
|
902
923
|
}
|
|
@@ -920,6 +941,19 @@ export class MessageQueue {
|
|
|
920
941
|
const isProcessing = this.processing.has(queueKey);
|
|
921
942
|
const currentQueue = this.queues.get(queueKey);
|
|
922
943
|
logger.info(`[Queue] enqueue: key=${queueKey} processing=${isProcessing} queueLen=${currentQueue?.length ?? 0} pending=${currentQueue?.length ?? 0} rawPending=${currentQueue ? this.queueRawMessageCount(currentQueue) : 0} agent=${agentName} role=${options?.role ?? '<none>'} peer=${message.peerId ?? '<none>'} msg=${message.messageId ?? '<none>'}`);
|
|
944
|
+
// Do not await diagnostic logging before the queue entry is admitted. The
|
|
945
|
+
// enqueue API must expose the message to concurrent session barriers in the
|
|
946
|
+
// same turn; yielding here creates a window where recovery can observe an
|
|
947
|
+
// empty queue and enqueue a duplicate task.
|
|
948
|
+
void import('../../utils/msg-diag.js').then(({ diagLog }) => {
|
|
949
|
+
diagLog('queue_enqueue', {
|
|
950
|
+
aid: message.selfAID ?? agentName,
|
|
951
|
+
from: message.peerId ?? '',
|
|
952
|
+
to: message.selfAID ?? agentName,
|
|
953
|
+
msgId: message.messageId ?? '',
|
|
954
|
+
text: message.content ?? '',
|
|
955
|
+
});
|
|
956
|
+
}).catch(() => { });
|
|
923
957
|
return new Promise((resolve, reject) => {
|
|
924
958
|
let settled = false;
|
|
925
959
|
let aborting = false;
|
|
@@ -967,8 +1001,14 @@ export class MessageQueue {
|
|
|
967
1001
|
timestamp: message.receivedAt ?? message.timestamp ?? enqueuedAt,
|
|
968
1002
|
};
|
|
969
1003
|
const queuedItem = { message, projectPath, agentName, role: options?.role, resolve: queuedResolve, reject: queuedReject, enqueuedAt };
|
|
970
|
-
|
|
971
|
-
|
|
1004
|
+
if (options?.priority) {
|
|
1005
|
+
const firstOrdinary = queue.findIndex(item => item.message.source !== 'owner-inject');
|
|
1006
|
+
queue.splice(firstOrdinary < 0 ? queue.length : firstOrdinary, 0, queuedItem);
|
|
1007
|
+
}
|
|
1008
|
+
else
|
|
1009
|
+
queue.push(queuedItem);
|
|
1010
|
+
if (message.source !== 'owner-inject' && message.attentionPolicy !== 'interrupt')
|
|
1011
|
+
this.logicalQueue.enqueue(queueKey, message);
|
|
972
1012
|
abortHandler = () => {
|
|
973
1013
|
if (settled || aborting)
|
|
974
1014
|
return;
|
|
@@ -1009,7 +1049,8 @@ export class MessageQueue {
|
|
|
1009
1049
|
// A duplicate must not re-enter a runner after the queue entry has
|
|
1010
1050
|
// survived its write-ahead snapshot. Keep this separate from the queue
|
|
1011
1051
|
// snapshot because the latter is removed as soon as the task completes.
|
|
1012
|
-
|
|
1052
|
+
if (message.source !== 'owner-inject')
|
|
1053
|
+
this.rememberDurably(sessionKey, message, options?.selfAID);
|
|
1013
1054
|
try {
|
|
1014
1055
|
options?.onPersisted?.();
|
|
1015
1056
|
}
|
|
@@ -1030,9 +1071,12 @@ export class MessageQueue {
|
|
|
1030
1071
|
// - 单聊(interruptible !== false):始终打断
|
|
1031
1072
|
// - 群聊(interruptible === false)+ interruptSamePeer:仅当「同一发送者连发」
|
|
1032
1073
|
// 且队列里没有其他人的消息时打断,避免抢占群里他人的排队消息
|
|
1033
|
-
const interruptSingle = options?.
|
|
1074
|
+
const interruptSingle = options?.attentionPolicy === 'interrupt'
|
|
1075
|
+
|| (options?.attentionPolicy !== 'defer' && options?.interruptible !== false);
|
|
1034
1076
|
const activeState = this.activeStates.get(queueKey);
|
|
1035
|
-
const interruptGroupSamePeer = options?.
|
|
1077
|
+
const interruptGroupSamePeer = options?.attentionPolicy !== 'interrupt' &&
|
|
1078
|
+
options?.attentionPolicy !== 'defer' &&
|
|
1079
|
+
options?.interruptible === false &&
|
|
1036
1080
|
options?.interruptSamePeer === true &&
|
|
1037
1081
|
!!message.peerId &&
|
|
1038
1082
|
activeState?.peerId === message.peerId &&
|
|
@@ -1125,7 +1169,8 @@ export class MessageQueue {
|
|
|
1125
1169
|
return;
|
|
1126
1170
|
}
|
|
1127
1171
|
// 逻辑队列重排:让响应模式的出队策略决定队首(默认 FIFO,不改变顺序)
|
|
1128
|
-
|
|
1172
|
+
if (queue[0]?.message.source !== 'owner-inject' && queue[0]?.message.attentionPolicy !== 'interrupt')
|
|
1173
|
+
this.logicalQueue.reorderPhysical(queueKey, queue);
|
|
1129
1174
|
// 贪心合并:群聊按完整时间线,旧路径/私聊按 peerId
|
|
1130
1175
|
const items = this.dequeueGreedy(queue);
|
|
1131
1176
|
// 同步逻辑队列:移除所有被合并处理的消息
|
|
@@ -1158,8 +1203,8 @@ export class MessageQueue {
|
|
|
1158
1203
|
// 记录正在执行的 messageId(用于撤回中断)
|
|
1159
1204
|
const activeMessageIds = new Set();
|
|
1160
1205
|
for (const item of rawItems) {
|
|
1161
|
-
|
|
1162
|
-
activeMessageIds.add(
|
|
1206
|
+
for (const messageId of this.messageIdsFor(item))
|
|
1207
|
+
activeMessageIds.add(messageId);
|
|
1163
1208
|
}
|
|
1164
1209
|
const activeState = {
|
|
1165
1210
|
baseagent: merged.message.baseagent,
|
|
@@ -1266,7 +1311,8 @@ export class MessageQueue {
|
|
|
1266
1311
|
return result;
|
|
1267
1312
|
}
|
|
1268
1313
|
isMergeBarrier(message) {
|
|
1269
|
-
return
|
|
1314
|
+
return message.source === 'owner-inject'
|
|
1315
|
+
|| !!message.taskRecovery
|
|
1270
1316
|
|| !!message.asyncQuestionAnswer
|
|
1271
1317
|
|| !!message.executionPermissionOverride
|
|
1272
1318
|
|| !!message.handoffDelivery
|
|
@@ -1424,6 +1470,12 @@ export class MessageQueue {
|
|
|
1424
1470
|
const earliestEnqueuedAt = this.earliestEnqueuedAt(items);
|
|
1425
1471
|
const merged = {
|
|
1426
1472
|
...last.message,
|
|
1473
|
+
autoMentionBatch: items.some(item => item.message.autoMentionBatch),
|
|
1474
|
+
attentionPolicy: items.some(item => item.message.attentionPolicy === 'interrupt')
|
|
1475
|
+
? 'interrupt'
|
|
1476
|
+
: items.some(item => item.message.attentionPolicy === 'defer')
|
|
1477
|
+
? 'defer'
|
|
1478
|
+
: last.message.attentionPolicy,
|
|
1427
1479
|
content: contents.join('\n'),
|
|
1428
1480
|
items: subMessages,
|
|
1429
1481
|
images: allImages.length > 0 ? allImages : undefined,
|
|
@@ -1558,9 +1610,7 @@ export class MessageQueue {
|
|
|
1558
1610
|
}
|
|
1559
1611
|
else {
|
|
1560
1612
|
this.activeBatches.set(queueKey, this.buildCoalescedItem(remaining));
|
|
1561
|
-
activeState.messageIds = new Set(remaining
|
|
1562
|
-
.map(part => part.message.messageId)
|
|
1563
|
-
.filter((id) => !!id));
|
|
1613
|
+
activeState.messageIds = new Set(remaining.flatMap(part => this.messageIdsFor(this.itemFromPart(part))));
|
|
1564
1614
|
}
|
|
1565
1615
|
this.persistQueuesImmediate();
|
|
1566
1616
|
}
|
|
@@ -1651,6 +1701,22 @@ export class MessageQueue {
|
|
|
1651
1701
|
}
|
|
1652
1702
|
return { state: 'missing' };
|
|
1653
1703
|
}
|
|
1704
|
+
/** Resolve a stable inbound message ID when the caller has not yet resolved a thread session. */
|
|
1705
|
+
getMessageStateByMessageId(messageId, selfAid, scope) {
|
|
1706
|
+
for (const [key, queue] of this.queues) {
|
|
1707
|
+
if (queue.some(item => this.partsOf(item)
|
|
1708
|
+
.some(part => this.partMatchesMessage(part, messageId, selfAid, key)
|
|
1709
|
+
&& this.partMatchesScope(part, scope))))
|
|
1710
|
+
return { state: 'queued' };
|
|
1711
|
+
}
|
|
1712
|
+
for (const [key, item] of this.activeBatches) {
|
|
1713
|
+
if (this.partsOf(item)
|
|
1714
|
+
.some(part => this.partMatchesMessage(part, messageId, selfAid, key)
|
|
1715
|
+
&& this.partMatchesScope(part, scope)))
|
|
1716
|
+
return { state: 'active' };
|
|
1717
|
+
}
|
|
1718
|
+
return { state: 'missing' };
|
|
1719
|
+
}
|
|
1654
1720
|
/** Live admission state, including work that arrived after an older gate. */
|
|
1655
1721
|
getSessionSnapshot(sessionKey) {
|
|
1656
1722
|
let queued = 0;
|
|
@@ -2129,6 +2195,27 @@ export class MessageQueue {
|
|
|
2129
2195
|
}
|
|
2130
2196
|
return true;
|
|
2131
2197
|
}
|
|
2198
|
+
async interruptForPriority(sessionId) {
|
|
2199
|
+
for (const [queueKey, active] of this.activeBatches) {
|
|
2200
|
+
if (!this.matchesSession(queueKey, sessionId))
|
|
2201
|
+
continue;
|
|
2202
|
+
if (!this.interruptCallback)
|
|
2203
|
+
throw new Error('Interrupt callback is unavailable');
|
|
2204
|
+
this.interruptFailures.delete(queueKey);
|
|
2205
|
+
this.eventBus?.publish({
|
|
2206
|
+
type: 'task:interrupted', sessionId, reason: 'new_message',
|
|
2207
|
+
agentName: this.processingAgent.get(queueKey),
|
|
2208
|
+
taskId: this.activeStates.get(queueKey)?.taskId,
|
|
2209
|
+
generation: this.activeStates.get(queueKey)?.generation,
|
|
2210
|
+
causation: active.message.causation,
|
|
2211
|
+
});
|
|
2212
|
+
await this.triggerInterrupt(queueKey, sessionId, this.activeStates.get(queueKey)?.baseagent, this.processingAgent.get(queueKey), 'new_message', undefined, true);
|
|
2213
|
+
const failure = this.interruptFailures.get(queueKey);
|
|
2214
|
+
this.interruptFailures.delete(queueKey);
|
|
2215
|
+
if (failure)
|
|
2216
|
+
throw failure;
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2132
2219
|
}
|
|
2133
2220
|
function abortError(reason) {
|
|
2134
2221
|
if (reason instanceof Error)
|