evolcore 0.0.35 → 0.0.37
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 +42 -0
- package/README.md +6 -0
- package/bin/install-codex-managed-hooks.mjs +20 -3
- package/dist/agents/baseagent-availability.js +1 -1
- package/dist/agents/baseagent.js +88 -0
- package/dist/agents/claude-runner.js +59 -12
- package/dist/agents/codex/app-server-client.js +18 -1
- package/dist/agents/codex-runner.js +262 -21
- package/dist/agents/ecagent-runner.js +47 -11
- package/dist/agents/gemini-runner.js +36 -12
- package/dist/aun/aid/client.js +4 -3
- package/dist/aun/aid/control-aid.js +270 -8
- package/dist/aun/aid/identity.js +6 -3
- package/dist/aun/aid/ownership-operation.js +58 -0
- package/dist/aun/aid/store.js +1 -0
- package/dist/aun/group/fs-download.js +67 -2
- package/dist/aun/group/history.js +20 -5
- package/dist/aun/group/operations.js +8 -2
- package/dist/aun/menu/client.js +39 -2
- package/dist/aun/menu/transport.js +1 -1
- package/dist/aun/msg/history.js +43 -4
- package/dist/aun/msg/managed-operation.js +30 -53
- package/dist/aun/msg/p2p.js +51 -15
- package/dist/aun/outbox.js +4 -0
- package/dist/channels/aun.js +260 -73
- package/dist/channels/daemon.js +6 -4
- package/dist/channels/feishu.js +3 -0
- package/dist/cli/agent-command.js +161 -223
- package/dist/cli/agent-create.js +190 -223
- package/dist/cli/agent.js +3 -1
- package/dist/cli/aid-bind-command.js +53 -0
- package/dist/cli/aun-commands.js +384 -91
- package/dist/cli/bench.js +1 -1
- package/dist/cli/cli-argv.js +74 -0
- package/dist/cli/daemon-commands.js +105 -74
- package/dist/cli/diag.js +1 -1
- package/dist/cli/fs-command.js +18 -19
- package/dist/cli/getmeta-command.js +159 -6
- package/dist/cli/index.js +6 -12
- package/dist/cli/init-channel.js +8 -55
- package/dist/cli/init.js +125 -218
- package/dist/cli/queue-command.js +11 -8
- package/dist/cli/restart-monitor.js +177 -85
- package/dist/cli/session-command.js +1 -1
- package/dist/cli/stats.js +7 -5
- package/dist/cli/thread-command.js +103 -30
- package/dist/cli/trigger-command.js +1 -1
- package/dist/cli/watch-msg-diag.js +1 -0
- package/dist/config/access-policy.js +2 -2
- package/dist/config/boot-log.js +14 -11
- package/dist/config/config-field-policy.js +9 -1
- package/dist/config/config-manager.js +176 -90
- package/dist/config/config-operation-service.js +7 -14
- package/dist/config/contact-book-store.js +142 -26
- package/dist/config/contact-book.js +4 -2
- package/dist/config/lifecycle.js +1 -1
- package/dist/config/owner-config.js +96 -0
- package/dist/config/peer-role-resolver.js +12 -18
- package/dist/config/providers-config.js +382 -0
- package/dist/config/providers-import.js +74 -0
- package/dist/config/providers-management.js +328 -0
- package/dist/config/providers.js +22 -0
- package/dist/config/resolved-config-op.js +17 -14
- package/dist/config/snapshot.js +28 -16
- package/dist/config-store.js +18 -14
- package/dist/core/agent-ipc-registration.js +21 -63
- package/dist/core/agent-runtime.js +16 -5
- package/dist/core/auth/agent-delegation.js +199 -25
- package/dist/core/auth/auth-gateway.js +44 -2
- package/dist/core/auth/authorization-denial.js +1 -1
- package/dist/core/auth/debug-context.js +2 -1
- package/dist/core/auth/delegation-authorization.js +2 -2
- package/dist/core/auth/delegation-diagnostics.js +4 -1
- package/dist/core/auth/operation-authorizer.js +10 -1
- package/dist/core/auth/operation-catalog.js +19 -1
- package/dist/core/bootstrap-service.js +43 -20
- package/dist/core/channel-loader.js +0 -1
- package/dist/core/channel-runtime.js +30 -4
- package/dist/core/command/agent-control.js +196 -37
- package/dist/core/command/cli-intent-parser.js +60 -4
- package/dist/core/command/command-handler.js +212 -60
- package/dist/core/command/connect-menu.js +1 -0
- package/dist/core/command/diag-service.js +5 -4
- package/dist/core/command/file-search.js +368 -0
- package/dist/core/command/menu-catalog.js +2 -1
- package/dist/core/command/menu-handler.js +292 -107
- package/dist/core/command/menu-protocol.js +23 -0
- package/dist/core/command/role-menu.js +7 -19
- package/dist/core/command/skill-slash.js +130 -25
- package/dist/core/command/slash-handler.js +101 -53
- package/dist/core/command/topic-slash.js +16 -5
- package/dist/core/daemon-bootstrap.js +7 -1
- package/dist/core/daemon-control.js +19 -1
- package/dist/core/daemon-lifecycle.js +2 -1
- package/dist/core/event-catalog.js +2 -0
- package/dist/core/evolagent-registry.js +13 -2
- package/dist/core/evolagent.js +3 -6
- package/dist/core/handoff/ipc-registration.js +2 -2
- package/dist/core/handoff/runtime.js +40 -6
- package/dist/core/handoff/store.js +1 -0
- package/dist/core/inference/text-inference.js +95 -6
- package/dist/core/ipc-registration.js +43 -24
- package/dist/core/memory/consolidation-context.js +4 -1
- package/dist/core/memory/consolidation.js +25 -14
- package/dist/core/message/aun-ipc-sender.js +296 -88
- package/dist/core/message/aun-request-registry.js +226 -0
- package/dist/core/message/create-status.js +33 -4
- package/dist/core/message/message-bridge.js +62 -13
- package/dist/core/message/message-log.js +0 -1
- package/dist/core/message/message-queue.js +4 -1
- package/dist/core/message/message-utils.js +8 -1
- package/dist/core/message/peer-mode.js +17 -9
- package/dist/core/message/response-engine.js +266 -124
- package/dist/core/message/retry-scheduler.js +11 -8
- package/dist/core/model/catalog-service.js +60 -18
- package/dist/core/model/model-catalog.js +112 -9
- package/dist/core/model/model-fallback.js +94 -26
- package/dist/core/ownership/owner-resolver.js +687 -0
- package/dist/core/permission/approval-gateway.js +196 -62
- package/dist/core/permission/ec-command-parser.js +138 -25
- package/dist/core/permission/filesystem-approval-scope.js +141 -0
- package/dist/core/permission/protected-paths.js +14 -1
- package/dist/core/permission/sandbox-runtime.js +171 -18
- package/dist/core/permission/tool-policy.js +13 -2
- package/dist/core/role/runtime-policy.js +3 -4
- package/dist/core/session/session-idle-monitor.js +10 -8
- package/dist/core/session/session-manager.js +72 -45
- package/dist/core/session/session-mapper.js +18 -7
- package/dist/core/session/session-renew.js +5 -4
- package/dist/core/session/session-title.js +2 -1
- package/dist/core/session/session-turn-coordinator.js +4 -2
- package/dist/core/skill/index-generator.js +2 -16
- package/dist/core/task/task-recovery-service.js +15 -2
- package/dist/core/thread/command-parser.js +28 -13
- package/dist/core/thread/index.js +1 -0
- package/dist/core/thread/ipc-operation.js +11 -8
- package/dist/core/thread/thread-operation.js +79 -44
- package/dist/core/thread/thread-route.js +54 -6
- package/dist/core/thread/thread-service.js +236 -45
- package/dist/core/thread/topic-id.js +248 -0
- package/dist/eck/kit-renderer.js +1 -1
- package/dist/eck/message-renderer.js +12 -2
- package/dist/index.js +50 -27
- package/dist/ipc.js +59 -6
- package/dist/paths.js +1 -0
- package/dist/product.js +1 -0
- package/dist/response-system/engines/v1/proactive-flow.js +10 -3
- package/dist/stats/db.js +8 -0
- package/dist/stats/writer.js +26 -4
- package/dist/trigger/authorization.js +48 -3
- package/dist/trigger/feedback.js +28 -10
- package/dist/trigger/ipc-service.js +86 -10
- package/dist/trigger/local-files.js +55 -23
- package/dist/trigger/scheduler.js +57 -11
- package/dist/trigger/system-definitions.js +1 -0
- package/dist/trigger/validation.js +44 -15
- package/dist/utils/aid-bind.js +17 -297
- package/dist/utils/avatar-upload.js +16 -4
- package/dist/utils/cross-platform.js +115 -36
- package/dist/utils/ecweb-supervisor.js +1 -1
- package/dist/utils/ecweb-utils.js +8 -1
- package/dist/utils/error-utils.js +44 -6
- package/dist/utils/instance-registry.js +12 -2
- package/dist/utils/npm-ops.js +102 -27
- package/dist/utils/package-version-info.js +72 -27
- package/dist/utils/restart-safety.js +50 -0
- package/dist/utils/upgrade-jobs.js +304 -0
- package/dist/utils/windows-autostart.js +17 -10
- package/kits/docs/INDEX.md +5 -0
- package/kits/docs/aun/ABILITY_CALLING.md +239 -0
- package/kits/docs/evolcore/INDEX.md +14 -3
- package/kits/docs/evolcore/agent-create.md +55 -141
- package/kits/docs/evolcore/agent.md +38 -16
- package/kits/docs/evolcore/aid.md +34 -0
- package/kits/docs/evolcore/config.md +20 -1
- package/kits/docs/evolcore/event.md +2 -2
- package/kits/docs/evolcore/fs.md +18 -2
- package/kits/docs/evolcore/group-collaboration.md +13 -246
- package/kits/docs/evolcore/group.md +2 -1
- package/kits/docs/evolcore/memory-consolidation-batches.md +1 -1
- package/kits/docs/evolcore/menu-protocol.md +65 -1
- package/kits/docs/evolcore/msg.md +64 -2
- package/kits/docs/evolcore/skill.md +86 -0
- package/kits/docs/evolcore/stats.md +6 -0
- package/kits/docs/evolcore/task.md +2 -0
- package/kits/docs/evolcore/thread-chain.md +145 -51
- package/kits/docs/evolcore/trigger.md +48 -3
- package/kits/eck_manifest.json +21 -0
- package/kits/eck_message_manifest.json +4 -4
- package/kits/migrations/migrate-role-config-v5.mjs +20 -7
- package/kits/rules/01-overview.md +2 -1
- package/kits/rules/03-identity.md +3 -1
- package/kits/rules/04-relation.md +1 -1
- package/kits/rules/07-memory-and-thread.md +1 -1
- package/kits/schemas/_meta.json +16 -1
- package/kits/schemas/agent-config.schema.13.json +44 -2
- package/kits/schemas/contact-book.schema.3.json +5 -0
- package/kits/schemas/daemon.schema.6.json +3 -1
- package/kits/schemas/daemon.schema.8.json +329 -0
- package/kits/schemas/defaults.schema.5.json +39 -3
- package/kits/schemas/providers.schema.1.json +76 -0
- package/kits/schemas/relation-config.schema.9.json +5 -1
- package/kits/skills/.switches.json +28 -0
- package/kits/skills/aid-ability/SKILL.md +214 -0
- package/kits/skills/ec-agent-create/SKILL.md +162 -0
- package/kits/skills/ec-group/SKILL.md +2 -1
- package/kits/skills/ec-group-collaboration/SKILL.md +228 -0
- package/kits/skills/ec-identity/SKILL.md +143 -0
- package/kits/skills/ec-skill/scripts/cli.mjs +36 -3
- package/kits/skills/ec-skill/scripts/skill.mjs +202 -15
- package/kits/skills/ec-trigger/SKILL.md +167 -0
- package/kits/skills/ec-trigger/references/examples.md +153 -0
- package/kits/skills/thread-ops/SKILL.md +108 -420
- package/kits/templates/message-fragments/thread-context.md +1 -2
- package/kits/templates/message-fragments/trigger-thread-check.md +1 -1
- package/kits/templates/roles/member.json +1 -1
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +1 -0
- package/kits/templates/system-fragments/channel.md +2 -1
- package/kits/templates/system-fragments/commands.md +5 -4
- package/kits/templates/system-fragments/identity.md +2 -0
- package/kits/templates/system-fragments/session.md +1 -1
- package/kits/templates/system-fragments/venue.md +1 -1
- package/package.json +4 -3
|
@@ -7,12 +7,26 @@ import { isValidAunDeliveryForChannel } from './outbound.js';
|
|
|
7
7
|
import { isHClassPath } from '../permission/protected-paths.js';
|
|
8
8
|
import { evaluateOutboundContactAdmission } from './message-admission.js';
|
|
9
9
|
import { normalizeAunMentionEntries, withAunAttention } from '../../aun/msg/mention-schema.js';
|
|
10
|
-
import {
|
|
11
|
-
import { readTriggerLocalFile,
|
|
10
|
+
import { resolveManagedSendArgv } from '../../cli/aun-commands.js';
|
|
11
|
+
import { readTriggerLocalFile, resolveAttachmentLocalPath } from '../../trigger/local-files.js';
|
|
12
|
+
import { TriggerDefinitionManager } from '../../trigger/manager.js';
|
|
12
13
|
import { sameGroupAid } from '../../aun/group/identity.js';
|
|
13
14
|
import { resolveThreadRouteTarget } from '../thread/thread-route.js';
|
|
15
|
+
import { isTopicThreadId, parseMainTopicId, safeFormatMainTopicId, sessionLocalTopicId } from '../thread/topic-id.js';
|
|
14
16
|
import { ThreadService } from '../thread/thread-service.js';
|
|
15
|
-
|
|
17
|
+
import { getAunRequestRegistry, requestTtlSeconds } from './aun-request-registry.js';
|
|
18
|
+
/** payload.debug 只是诊断字段:取不到时照常发送,不带 debug。 */
|
|
19
|
+
async function resolveOutboundDebug(resolver, sessionId) {
|
|
20
|
+
if (!resolver || !sessionId)
|
|
21
|
+
return undefined;
|
|
22
|
+
try {
|
|
23
|
+
return await resolver(sessionId);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function createAunHandoffSender(sessionManager, channelInstances, getOutboundDebug) {
|
|
16
30
|
return async (handoff) => {
|
|
17
31
|
const targetSession = await sessionManager.getSessionById(handoff.target_session_id);
|
|
18
32
|
if (!targetSession)
|
|
@@ -28,7 +42,8 @@ export function createAunHandoffSender(sessionManager, channelInstances) {
|
|
|
28
42
|
const log = {
|
|
29
43
|
content: classified.content,
|
|
30
44
|
sessionId: targetSession.id,
|
|
31
|
-
|
|
45
|
+
// 消息日志用本端身份(含主话题规范 id),不上线。
|
|
46
|
+
threadId: sessionLocalTopicId(targetSession) ?? '',
|
|
32
47
|
msgType: classified.msgType,
|
|
33
48
|
payloadType: classified.payloadType,
|
|
34
49
|
payloadSummary: classified.payloadSummary,
|
|
@@ -39,6 +54,8 @@ export function createAunHandoffSender(sessionManager, channelInstances) {
|
|
|
39
54
|
if (!isValidAunDeliveryForChannel(delivery, targetSession.channelId)) {
|
|
40
55
|
return { ok: false, error: 'handoff is missing a valid immutable AUN delivery route' };
|
|
41
56
|
}
|
|
57
|
+
// debug 标识写这条消息的会话(发起方),与回复路径一致。
|
|
58
|
+
const debug = await resolveOutboundDebug(getOutboundDebug, handoff.origin_session_id);
|
|
42
59
|
const result = delivery.chatType === 'group'
|
|
43
60
|
? typeof channel.sendDaemonGroupMsg === 'function'
|
|
44
61
|
? await channel.sendDaemonGroupMsg({
|
|
@@ -46,6 +63,7 @@ export function createAunHandoffSender(sessionManager, channelInstances) {
|
|
|
46
63
|
payload: { ...handoff.request.payload, [AUN_HANDOFF_MARKER_FIELD]: handoff.handoff_id },
|
|
47
64
|
encrypt: handoff.request.encrypt,
|
|
48
65
|
causation: handoff.causation,
|
|
66
|
+
debug,
|
|
49
67
|
log,
|
|
50
68
|
})
|
|
51
69
|
: { ok: false, error: 'AUN channel does not support daemon group sends' }
|
|
@@ -55,6 +73,7 @@ export function createAunHandoffSender(sessionManager, channelInstances) {
|
|
|
55
73
|
payload: handoff.request.payload,
|
|
56
74
|
encrypt: handoff.request.encrypt,
|
|
57
75
|
causation: handoff.causation,
|
|
76
|
+
debug,
|
|
58
77
|
log,
|
|
59
78
|
})
|
|
60
79
|
: { ok: false, error: 'AUN channel does not support daemon private sends' };
|
|
@@ -64,70 +83,94 @@ export function createAunHandoffSender(sessionManager, channelInstances) {
|
|
|
64
83
|
async function applyManagedCrossThreadSendEffects(input) {
|
|
65
84
|
const originSessionId = input.runtime?.sessionId;
|
|
66
85
|
if (!originSessionId)
|
|
67
|
-
return
|
|
68
|
-
const originThreadId = input.runtime?.threadId || 'main';
|
|
86
|
+
return { triggerError: 'origin session context unavailable' };
|
|
69
87
|
const originPeer = input.runtime?.channelId || input.targetChannelId;
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
// 来源话题 id:话题用原 id;主话题用"本端+对端"拼出的规范 id(展示与持久化用)。
|
|
89
|
+
const originThreadId = isTopicThreadId(input.runtime?.threadId)
|
|
90
|
+
? input.runtime.threadId
|
|
91
|
+
: (safeFormatMainTopicId(input.selfAid, originPeer) ?? '');
|
|
92
|
+
// origin 指向复查目标对端(A),而非触发本次发送的会话对端(C)。
|
|
93
|
+
// authorizeTriggerExecution 根据 origin 对端的角色决定 trigger 能否执行;
|
|
94
|
+
// B 周期性地向 A 发消息,应检查 A 对 B 的角色,而不是 C 对 B 的角色。
|
|
95
|
+
const targetChatType = input.feedbackChatType ?? 'private';
|
|
96
|
+
const origin = {
|
|
97
|
+
channelKey: formatChannelKey({ type: 'aun', selfAID: input.selfAid, name: 'main' }),
|
|
98
|
+
channelType: 'aun',
|
|
99
|
+
channelId: input.targetChannelId,
|
|
100
|
+
session: isTopicThreadId(input.targetThreadId) ? 'thread' : 'main',
|
|
101
|
+
...(isTopicThreadId(input.targetThreadId) ? { threadId: input.targetThreadId } : {}),
|
|
102
|
+
peerId: input.targetChannelId,
|
|
103
|
+
delivery: targetChatType === 'group'
|
|
104
|
+
? { chatType: 'group', groupId: input.targetChannelId }
|
|
105
|
+
: { chatType: 'private' },
|
|
106
|
+
};
|
|
87
107
|
const triggerSeed = `${Date.now()}_${crypto.randomBytes(4).toString('hex')}`;
|
|
88
108
|
const triggerId = `trig_${triggerSeed}`;
|
|
89
|
-
const triggerName = `check-${input.targetThreadId}-from-${originThreadId}-${triggerSeed.split('_')[1]}`;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
const triggerName = `check-${targetTopicLabel(input.targetThreadId)}-from-${targetTopicLabel(originThreadId)}-${triggerSeed.split('_')[1]}`;
|
|
110
|
+
// 话题名:从索引取,取不到时降级。
|
|
111
|
+
const originEntry = isTopicThreadId(originThreadId)
|
|
112
|
+
? ThreadService.findThreadById(input.selfAid, originThreadId)
|
|
113
|
+
: ThreadService.findMainSessionEntry(input.selfAid, originPeer);
|
|
114
|
+
const targetEntry = isTopicThreadId(input.targetThreadId)
|
|
115
|
+
? ThreadService.findThreadById(input.selfAid, input.targetThreadId)
|
|
116
|
+
: ThreadService.findMainSessionEntry(input.selfAid, input.targetChannelId);
|
|
117
|
+
const originThreadName = originEntry?.name || (originThreadId || originPeer);
|
|
118
|
+
const originPeerName = originEntry?.peerName || originPeer;
|
|
119
|
+
const targetThreadName = targetEntry?.name || input.targetThreadId;
|
|
120
|
+
const targetPeerName = targetEntry?.peerName || input.targetChannelId;
|
|
121
|
+
const { buildCrossThreadReviewPrompt } = await import('../../cli/aun-commands.js');
|
|
122
|
+
const prompt = buildCrossThreadReviewPrompt({
|
|
123
|
+
triggerId,
|
|
124
|
+
originThreadId,
|
|
125
|
+
originThreadName,
|
|
126
|
+
originPeerName,
|
|
127
|
+
targetThreadName,
|
|
128
|
+
targetPeerName,
|
|
129
|
+
checkEvery: input.checkEveryLabel,
|
|
130
|
+
firstSentAt: input.timestamp,
|
|
131
|
+
originalText: input.contentSummary,
|
|
132
|
+
extra: input.triggerPromptExtra,
|
|
133
|
+
});
|
|
105
134
|
let createdTriggerId;
|
|
135
|
+
let triggerError;
|
|
106
136
|
try {
|
|
107
|
-
if (!origin)
|
|
108
|
-
throw new Error('managed task runtime context is missing a trusted Trigger origin');
|
|
109
137
|
const scheduler = input.triggerSchedulers.get(input.selfAid);
|
|
110
138
|
if (!scheduler)
|
|
111
139
|
throw new Error(`trigger scheduler not found for agent: ${input.selfAid}`);
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
140
|
+
const { buildThreadCheckTrigger } = await import('../../cli/aun-commands.js');
|
|
141
|
+
// 触发本次发送的会话对端(C):originPeer 已按 chatType 取对端 AID(私聊 peerId、群聊群 AID)。
|
|
142
|
+
// 即使 origin 已改指向 A,C 也需要保留操作权(cancel/delete/list),
|
|
143
|
+
// 所以显式写入 operatorPeers = [C, A]。
|
|
144
|
+
const operatorPeers = [...new Set([originPeer, input.targetChannelId].filter((p) => !!p))];
|
|
145
|
+
const definition = {
|
|
146
|
+
...buildThreadCheckTrigger({
|
|
147
|
+
agentAid: input.selfAid,
|
|
148
|
+
id: triggerId,
|
|
149
|
+
name: triggerName,
|
|
150
|
+
prompt,
|
|
151
|
+
everyMs: input.durationMs,
|
|
152
|
+
checkEvery: input.checkEveryLabel,
|
|
153
|
+
channelKey: formatChannelKey({ type: 'aun', selfAID: input.selfAid, name: 'main' }),
|
|
154
|
+
targetChannelId: input.targetChannelId,
|
|
155
|
+
targetThreadId: input.targetThreadId,
|
|
156
|
+
originThreadId,
|
|
157
|
+
originPeer,
|
|
158
|
+
origin,
|
|
159
|
+
feedbackChatType: input.feedbackChatType,
|
|
160
|
+
originalText: input.contentSummary,
|
|
161
|
+
firstSentAt: input.timestamp,
|
|
162
|
+
originThreadName,
|
|
163
|
+
targetThreadName,
|
|
164
|
+
}),
|
|
165
|
+
operatorPeers,
|
|
166
|
+
};
|
|
127
167
|
createdTriggerId = scheduler.create(definition, [], { enable: true }).id;
|
|
128
168
|
}
|
|
129
169
|
catch (error) {
|
|
130
|
-
|
|
170
|
+
// 失败原因随发送回执返回给调用方:只打 daemon 日志时,CLI 照样显示"已投递",
|
|
171
|
+
// 复查静默缺失无人察觉(2026-10-20 firstSentAt 类型错误即如此)。
|
|
172
|
+
triggerError = error instanceof Error ? error.message : String(error);
|
|
173
|
+
console.warn(`⚠ Trigger 创建失败: ${triggerError}(inbox 仍会写入)`);
|
|
131
174
|
}
|
|
132
175
|
try {
|
|
133
176
|
ThreadService.appendInbox(input.selfAid, {
|
|
@@ -144,9 +187,58 @@ async function applyManagedCrossThreadSendEffects(input) {
|
|
|
144
187
|
catch (error) {
|
|
145
188
|
console.warn(`⚠ 话题 inbox 写入失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
189
|
}
|
|
147
|
-
return createdTriggerId;
|
|
190
|
+
return { triggerId: createdTriggerId, triggerError };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Trigger 名称里的话题片段。
|
|
194
|
+
*
|
|
195
|
+
* 名称只用于人读与日志,不参与定位;身份在 labels 的 originThreadId /
|
|
196
|
+
* targetThreadId 里。主话题 id 含两个完整 AID 与冒号,塞进名称又长又难读,
|
|
197
|
+
* 统一缩成 `main`。
|
|
198
|
+
*/
|
|
199
|
+
function targetTopicLabel(topicId) {
|
|
200
|
+
if (!topicId)
|
|
201
|
+
return 'unknown';
|
|
202
|
+
const parsed = parseMainTopicId(topicId);
|
|
203
|
+
if (!parsed)
|
|
204
|
+
return topicId;
|
|
205
|
+
return 'main';
|
|
148
206
|
}
|
|
149
|
-
export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegationRegistry, responseEngine, handoffRuntime, triggerSchedulers, }) {
|
|
207
|
+
export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegationRegistry, responseEngine, handoffRuntime, triggerSchedulers, sessionManager, }) {
|
|
208
|
+
ipcServer.setAunRequestGetExecutor(async (params) => {
|
|
209
|
+
if (!params.sessionId || !params.delegationToken) {
|
|
210
|
+
return { ok: false, code: 'DELEGATION_REQUIRED', error: 'Request queries require an active delegated session' };
|
|
211
|
+
}
|
|
212
|
+
const authorization = agentDelegationRegistry.validateForContext(params.delegationToken, params.sessionId, params.delegationCommandHash);
|
|
213
|
+
if (!authorization.ok)
|
|
214
|
+
return { ok: false, code: authorization.code, error: authorization.reason };
|
|
215
|
+
const runtime = responseEngine.getTaskRuntimeContext(params.sessionId);
|
|
216
|
+
if (!runtime || runtime.selfAid !== params.aid || authorization.grant.selfAid !== params.aid
|
|
217
|
+
|| runtime.peerKey !== authorization.grant.peerKey) {
|
|
218
|
+
return { ok: false, code: 'SCOPE_MISMATCH', error: 'Request status is limited to the delegated session' };
|
|
219
|
+
}
|
|
220
|
+
const request = getAunRequestRegistry().get(params.aid, params.requestId);
|
|
221
|
+
if (!request?.origin || request.origin.sessionId !== params.sessionId
|
|
222
|
+
|| request.origin.peerKey !== authorization.grant.peerKey || request.origin.threadId !== runtime.threadId) {
|
|
223
|
+
return { ok: false, code: 'REQUEST_NOT_FOUND', error: 'Request is not available in this session' };
|
|
224
|
+
}
|
|
225
|
+
const targetRoute = request.origin.targetThreadId
|
|
226
|
+
? resolveThreadRouteTarget(params.aid, request.origin.targetThreadId, 'msg', request.targetAid)
|
|
227
|
+
: undefined;
|
|
228
|
+
if (request.origin.targetThreadId && !targetRoute) {
|
|
229
|
+
return { ok: false, code: 'REQUEST_NOT_FOUND', error: 'Request target topic is no longer available' };
|
|
230
|
+
}
|
|
231
|
+
const permitted = await authorizeDelegatedAunMsgSend(agentDelegationRegistry, {
|
|
232
|
+
aid: params.aid, to: request.targetAid, scope: 'msg', action: 'history',
|
|
233
|
+
sessionId: params.sessionId, messageId: runtime.messageId,
|
|
234
|
+
delegationToken: params.delegationToken, delegationCommandHash: params.delegationCommandHash,
|
|
235
|
+
threadRouted: !!targetRoute,
|
|
236
|
+
});
|
|
237
|
+
if (!permitted.ok)
|
|
238
|
+
return { ok: false, code: permitted.code, error: permitted.reason };
|
|
239
|
+
return request ? { ok: true, request: request }
|
|
240
|
+
: { ok: false, code: 'REQUEST_NOT_FOUND', error: `request not found: ${params.requestId}` };
|
|
241
|
+
});
|
|
150
242
|
const sender = async (params) => {
|
|
151
243
|
let textFile;
|
|
152
244
|
try {
|
|
@@ -162,18 +254,56 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
162
254
|
catch (error) {
|
|
163
255
|
return { ok: false, code: 'INVALID_ARGUMENT', error: error instanceof Error ? error.message : String(error) };
|
|
164
256
|
}
|
|
165
|
-
|
|
257
|
+
// 活跃任务走内存上下文;调试会话(--as-session)和已结束的会话没有内存记录,
|
|
258
|
+
// 这时从会话本身重建,否则跨话题复查会静默不创建(getTaskRuntimeContext 返回 null)。
|
|
259
|
+
let runtime = params.originSessionId ? responseEngine.getTaskRuntimeContext(params.originSessionId) : undefined;
|
|
260
|
+
if (!runtime && params.originSessionId && sessionManager) {
|
|
261
|
+
try {
|
|
262
|
+
const session = await sessionManager.getSessionById(params.originSessionId);
|
|
263
|
+
if (session) {
|
|
264
|
+
const { buildDebugTaskContext } = await import('../auth/debug-context.js');
|
|
265
|
+
const { ensureSessionRuntimeDir } = await import('../../cli/task-context.js');
|
|
266
|
+
runtime = buildDebugTaskContext({
|
|
267
|
+
session,
|
|
268
|
+
getTrigger: (agentAid, triggerId) => new TriggerDefinitionManager(agentAid).get(triggerId),
|
|
269
|
+
sessionRuntimeDir: ensureSessionRuntimeDir(session.id),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// 重建失败时保持 undefined:不影响消息发送,只是不创建复查
|
|
275
|
+
}
|
|
276
|
+
}
|
|
166
277
|
const runtimeCausation = runtime?.causation;
|
|
167
|
-
|
|
168
|
-
|
|
278
|
+
// 话题引用解析:`threadRef` 是调用方写的原值(可能是主话题 id),
|
|
279
|
+
// `threadRoute` 非空即"这是跨话题发送"——与话题 id 是否为空无关。
|
|
280
|
+
const threadRef = params.thread;
|
|
281
|
+
const threadRoute = threadRef
|
|
282
|
+
? resolveThreadRouteTarget(params.aid, threadRef, params.scope, params.to)
|
|
169
283
|
: undefined;
|
|
170
|
-
if (
|
|
171
|
-
return { ok: false, code: 'TOPIC_NOT_FOUND', error: `话题不存在或不属于目标对端: ${
|
|
284
|
+
if (threadRef && !threadRoute) {
|
|
285
|
+
return { ok: false, code: 'TOPIC_NOT_FOUND', error: `话题不存在或不属于目标对端: ${threadRef}` };
|
|
172
286
|
}
|
|
287
|
+
const threadRouted = !!threadRoute;
|
|
288
|
+
// 规范目标 id:话题保留原 id;主话题用双方拼出的规范形态(用于 Trigger 标签与通知)。
|
|
289
|
+
const targetTopicId = threadRoute
|
|
290
|
+
? (isTopicThreadId(threadRef)
|
|
291
|
+
? threadRef
|
|
292
|
+
: (safeFormatMainTopicId(params.aid, threadRoute.peer) ?? threadRef))
|
|
293
|
+
: undefined;
|
|
173
294
|
if (params.argv !== undefined && !params.delegationCommandHash) {
|
|
174
|
-
return {
|
|
295
|
+
return {
|
|
296
|
+
ok: false,
|
|
297
|
+
code: 'INVALID_DELEGATION',
|
|
298
|
+
detail_code: 'APPROVED_COMMAND_UNAVAILABLE',
|
|
299
|
+
error: 'Managed AUN sends require an approved command hash',
|
|
300
|
+
retryable: false,
|
|
301
|
+
sent: false,
|
|
302
|
+
};
|
|
175
303
|
}
|
|
176
|
-
const
|
|
304
|
+
const isSystemEvent = params.trustedSystemEvent === true
|
|
305
|
+
&& params.payload?.type === 'event' && params.payload.event === 'topic.renamed';
|
|
306
|
+
const delegation = await authorizeDelegatedAunMsgSend(agentDelegationRegistry, {
|
|
177
307
|
delegationToken: params.delegationToken,
|
|
178
308
|
delegationCommandHash: params.delegationCommandHash,
|
|
179
309
|
sessionId: params.originSessionId,
|
|
@@ -183,13 +313,23 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
183
313
|
scope: params.scope,
|
|
184
314
|
action: params.file ? 'file' : 'send',
|
|
185
315
|
threadRouted: !!threadRoute,
|
|
316
|
+
isSystemEvent,
|
|
186
317
|
});
|
|
187
318
|
if (!delegation.ok) {
|
|
188
|
-
return {
|
|
319
|
+
return {
|
|
320
|
+
ok: false,
|
|
321
|
+
error: delegation.reason,
|
|
322
|
+
code: delegation.code,
|
|
323
|
+
...(delegation.detailCode ? { detail_code: delegation.detailCode } : {}),
|
|
324
|
+
...(delegation.retryable === false ? { retryable: false } : {}),
|
|
325
|
+
...(delegation.sent === false ? { sent: false } : {}),
|
|
326
|
+
};
|
|
189
327
|
}
|
|
190
328
|
try {
|
|
191
|
-
const fileScope = runtime?.projectPath
|
|
192
|
-
|
|
329
|
+
const fileScope = runtime?.projectPath && delegation.grant
|
|
330
|
+
? { selfAid: delegation.grant.selfAid, projectPath: runtime.projectPath,
|
|
331
|
+
sessionRuntimeDir: delegation.grant.sessionRuntimeDir, cwd: runtime.projectPath }
|
|
332
|
+
: undefined;
|
|
193
333
|
if ((textFile || params.file) && !fileScope)
|
|
194
334
|
throw new Error('Current task project context is unavailable');
|
|
195
335
|
if (textFile) {
|
|
@@ -198,14 +338,15 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
198
338
|
throw new Error('Message file must contain nonempty UTF-8 text');
|
|
199
339
|
params.payload = { type: 'text', text };
|
|
200
340
|
}
|
|
201
|
-
if (params.file)
|
|
202
|
-
params.file = { ...params.file, filePath:
|
|
203
|
-
|
|
341
|
+
if (params.file) {
|
|
342
|
+
params.file = { ...params.file, filePath: resolveAttachmentLocalPath(params.file.filePath, fileScope) };
|
|
343
|
+
}
|
|
344
|
+
if (params.payload && params.rawPayload !== true)
|
|
204
345
|
params.payload = withAunAttention(params.payload);
|
|
205
346
|
const currentRelation = runtime?.channel === 'aun' && runtime.selfAid === params.aid
|
|
206
347
|
&& runtime.chatType === (params.scope === 'group' ? 'group' : 'private')
|
|
207
348
|
&& !!runtime.channelId && (params.scope === 'group' ? sameGroupAid(runtime.channelId, params.to) : runtime.channelId === params.to);
|
|
208
|
-
params.thread = typeof params.payload?.thread_id === 'string' && params.payload.thread_id.trim()
|
|
349
|
+
params.thread = params.rawPayload === true ? params.thread : typeof params.payload?.thread_id === 'string' && params.payload.thread_id.trim()
|
|
209
350
|
? params.payload.thread_id.trim() : params.thread ?? (currentRelation ? runtime?.threadId : undefined);
|
|
210
351
|
}
|
|
211
352
|
catch (error) {
|
|
@@ -286,7 +427,7 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
286
427
|
};
|
|
287
428
|
}
|
|
288
429
|
try {
|
|
289
|
-
if (Object.prototype.hasOwnProperty.call(payload, 'mentions')) {
|
|
430
|
+
if (params.rawPayload !== true && Object.prototype.hasOwnProperty.call(payload, 'mentions')) {
|
|
290
431
|
payload = { ...payload, mentions: normalizeAunMentionEntries(payload.mentions) };
|
|
291
432
|
}
|
|
292
433
|
if (params.scope === 'group' && params.mentions !== undefined) {
|
|
@@ -303,11 +444,43 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
303
444
|
code: error?.code ?? 'INVALID_MENTION_SCHEMA',
|
|
304
445
|
};
|
|
305
446
|
}
|
|
306
|
-
if (params.thread && typeof payload.thread_id !== 'string') {
|
|
447
|
+
if (params.rawPayload !== true && isTopicThreadId(params.thread) && typeof payload.thread_id !== 'string') {
|
|
307
448
|
payload = { ...payload, thread_id: params.thread };
|
|
308
449
|
}
|
|
450
|
+
let preparedRequest;
|
|
451
|
+
let requestTtl;
|
|
452
|
+
if (params.scope === 'msg' && params.returnPolicy === 'required') {
|
|
453
|
+
try {
|
|
454
|
+
requestTtl = requestTtlSeconds(params.timeoutMs);
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
return {
|
|
458
|
+
ok: false,
|
|
459
|
+
code: 'INVALID_REQUEST_TTL',
|
|
460
|
+
error: error instanceof Error ? error.message : String(error),
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
try {
|
|
464
|
+
preparedRequest = getAunRequestRegistry().prepare({
|
|
465
|
+
selfAid: params.aid,
|
|
466
|
+
targetAid: params.to,
|
|
467
|
+
payload,
|
|
468
|
+
timeoutMs: params.timeoutMs ?? 60_000,
|
|
469
|
+
...(runtime && delegation.grant ? { origin: {
|
|
470
|
+
sessionId: params.originSessionId, peerKey: delegation.grant.peerKey,
|
|
471
|
+
threadId: runtime.threadId, targetThreadId: threadRoute ? params.thread : undefined,
|
|
472
|
+
} } : {}),
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
return { ok: false, code: error?.code ?? 'REQUEST_REGISTRATION_FAILED',
|
|
477
|
+
error: error instanceof Error ? error.message : String(error) };
|
|
478
|
+
}
|
|
479
|
+
payload = preparedRequest.payload;
|
|
480
|
+
getAunRequestRegistry().markSending(params.aid, preparedRequest.requestId);
|
|
481
|
+
}
|
|
309
482
|
let targetSessionId;
|
|
310
|
-
if (params.originSessionId && params.originMessageId) {
|
|
483
|
+
if (params.originSessionId && params.originMessageId && params.returnPolicy !== 'required') {
|
|
311
484
|
try {
|
|
312
485
|
const created = await handoffRuntime.createOutbound({
|
|
313
486
|
selfAid: params.aid,
|
|
@@ -320,6 +493,9 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
320
493
|
targetChatType: params.scope === 'group' ? 'group' : 'private',
|
|
321
494
|
explicitReturnPolicy: params.returnPolicy,
|
|
322
495
|
handoffContext: params.handoffContext,
|
|
496
|
+
// 跨话题发送的目标侧上下文由话题链(thread-inbox)负责注入;
|
|
497
|
+
// handoff 只管投递,回复时不再拼"本地发言"段。
|
|
498
|
+
threadRouted: threadRouted && params.checkEveryMs !== undefined,
|
|
323
499
|
originAuthorization: {
|
|
324
500
|
actorId: delegation.grant.actorId,
|
|
325
501
|
channelKey: delegation.grant.channel,
|
|
@@ -339,24 +515,28 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
339
515
|
handoff_id: created.handoff.handoff_id,
|
|
340
516
|
target_session_id: created.targetSession.id,
|
|
341
517
|
};
|
|
342
|
-
|
|
343
|
-
|
|
518
|
+
// 排队未投递(无 message_id)时也要写 inbox + 建复查:handoff 已不再
|
|
519
|
+
// 承载目标侧上下文,跳过这里就会丢上下文。
|
|
520
|
+
if (threadRouted && params.checkEveryMs !== undefined && threadRoute) {
|
|
521
|
+
const effects = await applyManagedCrossThreadSendEffects({
|
|
344
522
|
triggerSchedulers,
|
|
345
523
|
runtime,
|
|
346
524
|
selfAid: params.aid,
|
|
347
|
-
targetThreadId: params.thread,
|
|
525
|
+
targetThreadId: targetTopicId ?? params.thread ?? "",
|
|
348
526
|
targetSessionId: threadRoute.sessionId,
|
|
349
527
|
targetChannelId: params.to,
|
|
350
528
|
feedbackChatType: params.scope === 'group' ? 'group' : 'private',
|
|
351
|
-
messageId: response.message_id,
|
|
529
|
+
messageId: response.message_id ?? created.handoff.handoff_id,
|
|
352
530
|
contentSummary: params.log?.content ?? classifyAunPayloadForLog(payload).content,
|
|
353
531
|
timestamp: response.timestamp ?? Date.now(),
|
|
354
532
|
durationMs: params.checkEveryMs,
|
|
355
533
|
checkEveryLabel: params.checkEvery ?? '5m',
|
|
356
534
|
triggerPromptExtra: params.triggerPromptExtra,
|
|
357
535
|
});
|
|
358
|
-
if (triggerId)
|
|
359
|
-
response.trigger_id = triggerId;
|
|
536
|
+
if (effects.triggerId)
|
|
537
|
+
response.trigger_id = effects.triggerId;
|
|
538
|
+
if (effects.triggerError)
|
|
539
|
+
response.trigger_error = effects.triggerError;
|
|
360
540
|
}
|
|
361
541
|
return response;
|
|
362
542
|
}
|
|
@@ -376,6 +556,7 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
376
556
|
};
|
|
377
557
|
}
|
|
378
558
|
}
|
|
559
|
+
const debug = await resolveOutboundDebug(sessionId => responseEngine.getOutboundDebug(sessionId), params.originSessionId);
|
|
379
560
|
if (params.scope === 'group') {
|
|
380
561
|
if (typeof ch.sendDaemonGroupMsg !== 'function') {
|
|
381
562
|
return { ok: false, error: 'AUN channel does not support daemon group sends', code: 'AUN_GROUP_UNSUPPORTED' };
|
|
@@ -385,10 +566,11 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
385
566
|
payload,
|
|
386
567
|
mentions: params.mentions,
|
|
387
568
|
encrypt,
|
|
569
|
+
debug,
|
|
388
570
|
log: params.log ? { ...params.log, sessionId: targetSessionId ?? params.log.sessionId } : undefined,
|
|
389
571
|
});
|
|
390
572
|
if (params.thread && params.checkEveryMs !== undefined && sent.ok && sent.message_id && threadRoute) {
|
|
391
|
-
const
|
|
573
|
+
const effects = await applyManagedCrossThreadSendEffects({
|
|
392
574
|
triggerSchedulers,
|
|
393
575
|
runtime,
|
|
394
576
|
selfAid: params.aid,
|
|
@@ -403,8 +585,10 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
403
585
|
checkEveryLabel: params.checkEvery ?? '5m',
|
|
404
586
|
triggerPromptExtra: params.triggerPromptExtra,
|
|
405
587
|
});
|
|
406
|
-
if (triggerId)
|
|
407
|
-
sent.trigger_id = triggerId;
|
|
588
|
+
if (effects.triggerId)
|
|
589
|
+
sent.trigger_id = effects.triggerId;
|
|
590
|
+
if (effects.triggerError)
|
|
591
|
+
sent.trigger_error = effects.triggerError;
|
|
408
592
|
}
|
|
409
593
|
return sent;
|
|
410
594
|
}
|
|
@@ -414,12 +598,34 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
414
598
|
const sent = await ch.sendDaemonMsg({
|
|
415
599
|
to: params.to,
|
|
416
600
|
payload,
|
|
601
|
+
rawPayload: params.rawPayload,
|
|
602
|
+
ttl: requestTtl,
|
|
417
603
|
encrypt,
|
|
418
604
|
causation: runtimeCausation,
|
|
605
|
+
debug,
|
|
419
606
|
log: params.log ? { ...params.log, sessionId: targetSessionId ?? params.log.sessionId } : undefined,
|
|
420
607
|
});
|
|
608
|
+
if (preparedRequest) {
|
|
609
|
+
if (!sent.ok || !sent.message_id) {
|
|
610
|
+
const transportError = sent.error || 'transport send failed';
|
|
611
|
+
const request = getAunRequestRegistry().markFailed(params.aid, preparedRequest.requestId, transportError);
|
|
612
|
+
if (request?.state === 'completed') {
|
|
613
|
+
return { ok: true, request_id: preparedRequest.requestId, request_state: request.state,
|
|
614
|
+
response: request.responsePayload, transport_error: transportError, retryable: false, sent: true };
|
|
615
|
+
}
|
|
616
|
+
return { ...sent, ok: false, request_id: preparedRequest.requestId, request_state: request?.state ?? 'failed' };
|
|
617
|
+
}
|
|
618
|
+
getAunRequestRegistry().markTransportAccepted(params.aid, preparedRequest.requestId, sent.message_id, sent.status);
|
|
619
|
+
const completed = await getAunRequestRegistry().wait(params.aid, preparedRequest.requestId, params.timeoutMs ?? 60_000);
|
|
620
|
+
return {
|
|
621
|
+
...sent,
|
|
622
|
+
request_id: preparedRequest.requestId,
|
|
623
|
+
request_state: completed?.state ?? 'unknown',
|
|
624
|
+
...(completed?.responsePayload ? { response: completed.responsePayload } : {}),
|
|
625
|
+
};
|
|
626
|
+
}
|
|
421
627
|
if (params.thread && params.checkEveryMs !== undefined && sent.ok && sent.message_id && threadRoute) {
|
|
422
|
-
const
|
|
628
|
+
const effects = await applyManagedCrossThreadSendEffects({
|
|
423
629
|
triggerSchedulers,
|
|
424
630
|
runtime,
|
|
425
631
|
selfAid: params.aid,
|
|
@@ -434,8 +640,10 @@ export function registerAunIpcSender({ ipcServer, channelInstances, agentDelegat
|
|
|
434
640
|
checkEveryLabel: params.checkEvery ?? '5m',
|
|
435
641
|
triggerPromptExtra: params.triggerPromptExtra,
|
|
436
642
|
});
|
|
437
|
-
if (triggerId)
|
|
438
|
-
sent.trigger_id = triggerId;
|
|
643
|
+
if (effects.triggerId)
|
|
644
|
+
sent.trigger_id = effects.triggerId;
|
|
645
|
+
if (effects.triggerError)
|
|
646
|
+
sent.trigger_error = effects.triggerError;
|
|
439
647
|
}
|
|
440
648
|
return sent;
|
|
441
649
|
};
|