@@ -87,7 +87,11 @@ import {
8787 shouldApplyCrossContextMarker ,
8888} from "./outbound-policy.js" ;
8989import { executePollAction , executeSendAction } from "./outbound-send-service.js" ;
90- import { ensureOutboundSessionEntry , resolveOutboundSessionRoute } from "./outbound-session.js" ;
90+ import {
91+ ensureOutboundSessionEntry ,
92+ resolveOutboundSessionRoute ,
93+ type OutboundSessionRoute ,
94+ } from "./outbound-session.js" ;
9195import { normalizeTargetForProvider } from "./target-normalization.js" ;
9296import { resolveChannelTarget , type ResolvedMessagingTarget } from "./target-resolver.js" ;
9397import { extractToolPayload } from "./tool-payload.js" ;
@@ -1073,6 +1077,116 @@ async function buildSendPayloadParts(params: {
10731077 } ;
10741078}
10751079
1080+ function isCurrentSourceOutboundRoute ( params : {
1081+ input : RunMessageActionParams ;
1082+ actionParams : Record < string , unknown > ;
1083+ outboundRoute : OutboundSessionRoute | null ;
1084+ dryRun : boolean ;
1085+ } ) : boolean {
1086+ if ( params . dryRun ) {
1087+ return false ;
1088+ }
1089+ const currentSessionKey = normalizeOptionalLowercaseString ( params . input . sessionKey ) ;
1090+ const outboundSessionKey = normalizeOptionalLowercaseString ( params . outboundRoute ?. sessionKey ) ;
1091+ if ( currentSessionKey && outboundSessionKey && currentSessionKey === outboundSessionKey ) {
1092+ return true ;
1093+ }
1094+ return (
1095+ ! hasExplicitNonCurrentChannelParam ( params . input , params . actionParams ) &&
1096+ isCurrentSourceTargetParam ( params . input , params . actionParams )
1097+ ) ;
1098+ }
1099+
1100+ function collectDeliveryEvidencePayloads (
1101+ payloadRecord : Record < string , unknown > ,
1102+ ) : Record < string , unknown > [ ] {
1103+ const nested = payloadRecord . result ;
1104+ if ( nested && typeof nested === "object" && ! Array . isArray ( nested ) ) {
1105+ return [ payloadRecord , nested as Record < string , unknown > ] ;
1106+ }
1107+ return [ payloadRecord ] ;
1108+ }
1109+
1110+ function payloadHasPositiveDeliveryEvidence ( payloadRecord : Record < string , unknown > ) : boolean {
1111+ let hasDeliveredStatus = false ;
1112+ let hasMessageId = false ;
1113+ for ( const candidate of collectDeliveryEvidencePayloads ( payloadRecord ) ) {
1114+ const deliveryStatus = normalizeOptionalString ( candidate . deliveryStatus ) ?. toLowerCase ( ) ;
1115+ const status = normalizeOptionalString ( candidate . status ) ?. toLowerCase ( ) ;
1116+ if (
1117+ deliveryStatus === "failed" ||
1118+ deliveryStatus === "error" ||
1119+ deliveryStatus === "undelivered" ||
1120+ status === "failed" ||
1121+ status === "error" ||
1122+ status === "undelivered" ||
1123+ candidate . ok === false
1124+ ) {
1125+ return false ;
1126+ }
1127+ hasDeliveredStatus ||= deliveryStatus === "sent" || deliveryStatus === "delivered" ;
1128+ hasDeliveredStatus ||= status === "sent" || status === "delivered" ;
1129+ hasMessageId ||= Boolean (
1130+ normalizeOptionalString ( candidate . messageId ) ?? normalizeOptionalString ( candidate . message_id ) ,
1131+ ) ;
1132+ }
1133+ return hasDeliveredStatus || hasMessageId ;
1134+ }
1135+
1136+ function annotatePayloadForCurrentSourceReply ( params : {
1137+ payload : unknown ;
1138+ sendPayload : SendPayloadParts ;
1139+ input : RunMessageActionParams ;
1140+ actionParams : Record < string , unknown > ;
1141+ outboundRoute : OutboundSessionRoute | null ;
1142+ dryRun : boolean ;
1143+ } ) : unknown {
1144+ if ( ! isCurrentSourceOutboundRoute ( params ) ) {
1145+ return params . payload ;
1146+ }
1147+ const payloadRecord : Record < string , unknown > =
1148+ params . payload && typeof params . payload === "object" && ! Array . isArray ( params . payload )
1149+ ? { ...( params . payload as Record < string , unknown > ) }
1150+ : { result : params . payload } ;
1151+ if ( ! payloadHasPositiveDeliveryEvidence ( payloadRecord ) ) {
1152+ return params . payload ;
1153+ }
1154+ return {
1155+ ...payloadRecord ,
1156+ deliveryStatus : "sent" ,
1157+ sourceReplySink : "internal-ui" as const ,
1158+ ...( params . input . sourceReplyDeliveryMode
1159+ ? { sourceReplyDeliveryMode : params . input . sourceReplyDeliveryMode }
1160+ : { } ) ,
1161+ sourceReply : params . sendPayload . payload ,
1162+ ...( params . sendPayload . message ? { message : params . sendPayload . message } : { } ) ,
1163+ ...( params . sendPayload . mediaUrl ? { mediaUrl : params . sendPayload . mediaUrl } : { } ) ,
1164+ ...( params . sendPayload . mediaUrls ?. length ? { mediaUrls : params . sendPayload . mediaUrls } : { } ) ,
1165+ } ;
1166+ }
1167+
1168+ function annotateToolResultForCurrentSourceReply (
1169+ toolResult : AgentToolResult < unknown > | undefined ,
1170+ params : {
1171+ sendPayload : SendPayloadParts ;
1172+ input : RunMessageActionParams ;
1173+ actionParams : Record < string , unknown > ;
1174+ outboundRoute : OutboundSessionRoute | null ;
1175+ dryRun : boolean ;
1176+ } ,
1177+ ) : AgentToolResult < unknown > | undefined {
1178+ if ( ! toolResult || ! isCurrentSourceOutboundRoute ( params ) ) {
1179+ return toolResult ;
1180+ }
1181+ return {
1182+ ...toolResult ,
1183+ details : annotatePayloadForCurrentSourceReply ( {
1184+ payload : toolResult . details ,
1185+ ...params ,
1186+ } ) ,
1187+ } ;
1188+ }
1189+
10761190async function handleSendAction ( ctx : ResolvedActionContext ) : Promise < MessageActionRunResult > {
10771191 const {
10781192 cfg,
@@ -1171,7 +1285,27 @@ async function handleSendAction(ctx: ResolvedActionContext): Promise<MessageActi
11711285 } ) ,
11721286 } ) ;
11731287 if ( gatewayPluginAction ) {
1174- return gatewayPluginAction ;
1288+ if ( gatewayPluginAction . kind !== "send" ) {
1289+ return gatewayPluginAction ;
1290+ }
1291+ return {
1292+ ...gatewayPluginAction ,
1293+ payload : annotatePayloadForCurrentSourceReply ( {
1294+ payload : gatewayPluginAction . payload ,
1295+ sendPayload,
1296+ input,
1297+ actionParams : params ,
1298+ outboundRoute,
1299+ dryRun,
1300+ } ) ,
1301+ toolResult : annotateToolResultForCurrentSourceReply ( gatewayPluginAction . toolResult , {
1302+ sendPayload,
1303+ input,
1304+ actionParams : params ,
1305+ outboundRoute,
1306+ dryRun,
1307+ } ) ,
1308+ } ;
11751309 }
11761310
11771311 const send = await executeSendAction ( {
@@ -1230,8 +1364,21 @@ async function handleSendAction(ctx: ResolvedActionContext): Promise<MessageActi
12301364 action,
12311365 to,
12321366 handledBy : send . handledBy ,
1233- payload : send . payload ,
1234- toolResult : send . toolResult ,
1367+ payload : annotatePayloadForCurrentSourceReply ( {
1368+ payload : send . payload ,
1369+ sendPayload,
1370+ input,
1371+ actionParams : params ,
1372+ outboundRoute,
1373+ dryRun,
1374+ } ) ,
1375+ toolResult : annotateToolResultForCurrentSourceReply ( send . toolResult , {
1376+ sendPayload,
1377+ input,
1378+ actionParams : params ,
1379+ outboundRoute,
1380+ dryRun,
1381+ } ) ,
12351382 sendResult : send . sendResult ,
12361383 dryRun,
12371384 } ;
0 commit comments