@@ -655,10 +655,6 @@ type DeliverOutboundPayloadsCoreRuntimeParams = DeliverOutboundPayloadsCoreParam
655655 onPlatformSendStart ?: ( ) => Promise < void > ;
656656} ;
657657
658- function collectPayloadMediaSources ( plan : readonly OutboundPayloadPlan [ ] ) : string [ ] {
659- return plan . flatMap ( ( entry ) => entry . parts . mediaUrls ) ;
660- }
661-
662658/**
663659 * @deprecated Direct outbound delivery is compatibility/runtime substrate.
664660 * New message lifecycle code should use `sendDurableMessageBatch` from
@@ -1391,8 +1387,7 @@ async function deliverOutboundPayloadsCore(
13911387 const accountId = params . accountId ;
13921388 const deps = params . deps ;
13931389 const abortSignal = params . abortSignal ;
1394- const mediaSources = collectPayloadMediaSources ( outboundPayloadPlan ) ;
1395- const mediaAccess =
1390+ const resolveMediaAccess = ( mediaSources : readonly string [ ] ) : OutboundMediaAccess =>
13961391 mediaSources . length > 0
13971392 ? resolveAgentScopedOutboundMediaAccess ( {
13981393 cfg,
@@ -1408,25 +1403,42 @@ async function deliverOutboundPayloadsCore(
14081403 requesterSenderE164 : params . session ?. requesterSenderE164 ,
14091404 } )
14101405 : ( params . mediaAccess ?? { } ) ;
1406+ const createHandler = ( mediaSources : readonly string [ ] ) =>
1407+ createChannelHandler ( {
1408+ cfg,
1409+ channel,
1410+ to,
1411+ deps,
1412+ accountId,
1413+ replyToId : params . replyToId ,
1414+ replyToMode : params . replyToMode ,
1415+ formatting : params . formatting ,
1416+ threadId : params . threadId ,
1417+ identity : params . identity ,
1418+ gifPlayback : params . gifPlayback ,
1419+ forceDocument : params . forceDocument ,
1420+ silent : params . silent ,
1421+ mediaAccess : resolveMediaAccess ( mediaSources ) ,
1422+ gatewayClientScopes : params . gatewayClientScopes ,
1423+ ...( params . onPlatformSendStart ? { onPlatformSendStart : params . onPlatformSendStart } : { } ) ,
1424+ } ) ;
1425+ const baseHandler = await createHandler ( [ ] ) ;
1426+ const handlerByMediaSources = new Map < string , Promise < ChannelHandler > > ( ) ;
1427+ const getDeliveryHandler = ( mediaSources : readonly string [ ] ) : Promise < ChannelHandler > => {
1428+ if ( mediaSources . length === 0 ) {
1429+ return Promise . resolve ( baseHandler ) ;
1430+ }
1431+ const key = JSON . stringify ( mediaSources ) ;
1432+ const cached = handlerByMediaSources . get ( key ) ;
1433+ if ( cached ) {
1434+ return cached ;
1435+ }
1436+ const created = createHandler ( mediaSources ) ;
1437+ handlerByMediaSources . set ( key , created ) ;
1438+ return created ;
1439+ } ;
14111440 const results : OutboundDeliveryResult [ ] = [ ] ;
1412- const handler = await createChannelHandler ( {
1413- cfg,
1414- channel,
1415- to,
1416- deps,
1417- accountId,
1418- replyToId : params . replyToId ,
1419- replyToMode : params . replyToMode ,
1420- formatting : params . formatting ,
1421- threadId : params . threadId ,
1422- identity : params . identity ,
1423- gifPlayback : params . gifPlayback ,
1424- forceDocument : params . forceDocument ,
1425- silent : params . silent ,
1426- mediaAccess,
1427- gatewayClientScopes : params . gatewayClientScopes ,
1428- ...( params . onPlatformSendStart ? { onPlatformSendStart : params . onPlatformSendStart } : { } ) ,
1429- } ) ;
1441+ const handler = baseHandler ;
14301442 const configuredTextLimit = handler . chunker
14311443 ? resolveTextChunkLimit ( cfg , channel , accountId , {
14321444 fallbackLimit : handler . textChunkLimit ,
@@ -1445,13 +1457,17 @@ async function deliverOutboundPayloadsCore(
14451457 replyToMode : params . replyToMode ,
14461458 } ) ;
14471459
1448- const sendTextChunks = async ( text : string , overrides : OutboundMessageSendOverrides = { } ) => {
1460+ const sendTextChunks = async (
1461+ sendHandler : ChannelHandler ,
1462+ text : string ,
1463+ overrides : OutboundMessageSendOverrides = { } ,
1464+ ) => {
14491465 const units = planOutboundTextMessageUnits ( {
14501466 text,
14511467 overrides,
1452- chunker : handler . chunker ,
1453- chunkerMode : handler . chunkerMode ,
1454- chunkedTextFormatting : handler . chunkedTextFormatting ,
1468+ chunker : sendHandler . chunker ,
1469+ chunkerMode : sendHandler . chunkerMode ,
1470+ chunkedTextFormatting : sendHandler . chunkedTextFormatting ,
14551471 textLimit,
14561472 chunkMode,
14571473 formatting : params . formatting ,
@@ -1465,7 +1481,7 @@ async function deliverOutboundPayloadsCore(
14651481 continue ;
14661482 }
14671483 throwIfAborted ( abortSignal ) ;
1468- results . push ( await handler . sendText ( unit . text , unit . overrides ) ) ;
1484+ results . push ( await sendHandler . sendText ( unit . text , unit . overrides ) ) ;
14691485 }
14701486 } ;
14711487 const normalizedPayloads = normalizePayloadsForChannelDelivery ( outboundPayloadPlan , handler ) ;
@@ -1606,11 +1622,17 @@ async function deliverOutboundPayloadsCore(
16061622 continue ;
16071623 }
16081624 deliveryPayload = hookResult . payload ;
1625+ const presentationHandler = await getDeliveryHandler (
1626+ buildPayloadSummary ( deliveryPayload ) . mediaUrls ,
1627+ ) ;
16091628 const renderedPayload = stripInternalRuntimeScaffoldingFromPayload (
1610- await renderPresentationForDelivery ( handler , deliveryPayload ) ,
1629+ await renderPresentationForDelivery ( presentationHandler , deliveryPayload ) ,
1630+ ) ;
1631+ const renderedHandler = await getDeliveryHandler (
1632+ buildPayloadSummary ( renderedPayload ) . mediaUrls ,
16111633 ) ;
1612- const normalizedEffectivePayload = handler . normalizePayload
1613- ? handler . normalizePayload ( renderedPayload )
1634+ const normalizedEffectivePayload = renderedHandler . normalizePayload
1635+ ? renderedHandler . normalizePayload ( renderedPayload )
16141636 : renderedPayload ;
16151637 const effectivePayload = normalizedEffectivePayload
16161638 ? normalizeEmptyPayloadForDelivery (
@@ -1631,6 +1653,7 @@ async function deliverOutboundPayloadsCore(
16311653 continue ;
16321654 }
16331655 payloadSummary = buildPayloadSummary ( effectivePayload ) ;
1656+ const deliveryHandler = await getDeliveryHandler ( payloadSummary . mediaUrls ) ;
16341657 startDeliveryDiagnostics ( deliveryKindForPayload ( effectivePayload , payloadSummary ) ) ;
16351658
16361659 params . onPayload ?.( payloadSummary ) ;
@@ -1648,18 +1671,19 @@ async function deliverOutboundPayloadsCore(
16481671 applyReplyToConsumption ( overrides , {
16491672 consumeImplicitReply : replyToResolution . source === "implicit" ,
16501673 } ) ;
1651- const deliveryTarget = handler . buildTargetRef ( { threadId : sendOverrides . threadId } ) ;
1674+ const deliveryTarget = deliveryHandler . buildTargetRef ( { threadId : sendOverrides . threadId } ) ;
16521675 if (
1653- handler . sendPayload &&
1654- ( ( effectivePayload . isError === true && handler . sendTextOnlyErrorPayloads === true ) ||
1676+ deliveryHandler . sendPayload &&
1677+ ( ( effectivePayload . isError === true &&
1678+ deliveryHandler . sendTextOnlyErrorPayloads === true ) ||
16551679 hasReplyPayloadContent ( {
16561680 presentation : effectivePayload . presentation ,
16571681 interactive : effectivePayload . interactive ,
16581682 channelData : effectivePayload . channelData ,
16591683 } ) ||
16601684 effectivePayload . audioAsVoice === true )
16611685 ) {
1662- const delivery = await handler . sendPayload (
1686+ const delivery = await deliveryHandler . sendPayload (
16631687 effectivePayload ,
16641688 applySendReplyToConsumption ( sendOverrides ) ,
16651689 ) ;
@@ -1677,13 +1701,13 @@ async function deliverOutboundPayloadsCore(
16771701 recordPayloadOutcome ( { index : payloadIndex , status : "sent" , results : [ delivery ] } ) ;
16781702 recordDeliveredMirrorPayload ( payloadSummary , [ delivery ] ) ;
16791703 await maybePinDeliveredMessage ( {
1680- handler,
1704+ handler : deliveryHandler ,
16811705 payload : effectivePayload ,
16821706 target : deliveryTarget ,
16831707 messageId : delivery . messageId ,
16841708 } ) ;
16851709 await maybeNotifyAfterDeliveredPayload ( {
1686- handler,
1710+ handler : deliveryHandler ,
16871711 payload : effectivePayload ,
16881712 target : deliveryTarget ,
16891713 results : [ delivery ] ,
@@ -1698,15 +1722,15 @@ async function deliverOutboundPayloadsCore(
16981722 }
16991723 if ( payloadSummary . mediaUrls . length === 0 ) {
17001724 const beforeCount = results . length ;
1701- if ( handler . sendFormattedText ) {
1725+ if ( deliveryHandler . sendFormattedText ) {
17021726 results . push (
1703- ...( await handler . sendFormattedText (
1727+ ...( await deliveryHandler . sendFormattedText (
17041728 payloadSummary . text ,
17051729 applySendReplyToConsumption ( sendOverrides ) ,
17061730 ) ) ,
17071731 ) ;
17081732 } else {
1709- await sendTextChunks ( payloadSummary . text , sendOverrides ) ;
1733+ await sendTextChunks ( deliveryHandler , payloadSummary . text , sendOverrides ) ;
17101734 }
17111735 const deliveredResults = results . slice ( beforeCount ) ;
17121736 if ( deliveredResults . length > 0 ) {
@@ -1727,13 +1751,13 @@ async function deliverOutboundPayloadsCore(
17271751 const messageId = results . at ( - 1 ) ?. messageId ;
17281752 const pinMessageId = deliveredResults . find ( ( entry ) => entry . messageId ) ?. messageId ;
17291753 await maybePinDeliveredMessage ( {
1730- handler,
1754+ handler : deliveryHandler ,
17311755 payload : effectivePayload ,
17321756 target : deliveryTarget ,
17331757 messageId : pinMessageId ,
17341758 } ) ;
17351759 await maybeNotifyAfterDeliveredPayload ( {
1736- handler,
1760+ handler : deliveryHandler ,
17371761 payload : effectivePayload ,
17381762 target : deliveryTarget ,
17391763 results : deliveredResults ,
@@ -1747,7 +1771,7 @@ async function deliverOutboundPayloadsCore(
17471771 continue ;
17481772 }
17491773
1750- if ( ! handler . supportsMedia ) {
1774+ if ( ! deliveryHandler . supportsMedia ) {
17511775 log . warn (
17521776 "Plugin outbound adapter does not implement sendMedia; media URLs will be dropped and text fallback will be used" ,
17531777 {
@@ -1763,7 +1787,7 @@ async function deliverOutboundPayloadsCore(
17631787 ) ;
17641788 }
17651789 const beforeCount = results . length ;
1766- await sendTextChunks ( fallbackText , sendOverrides ) ;
1790+ await sendTextChunks ( deliveryHandler , fallbackText , sendOverrides ) ;
17671791 const deliveredResults = results . slice ( beforeCount ) ;
17681792 if ( deliveredResults . length > 0 ) {
17691793 recordPayloadOutcome ( {
@@ -1783,13 +1807,13 @@ async function deliverOutboundPayloadsCore(
17831807 const messageId = results . at ( - 1 ) ?. messageId ;
17841808 const pinMessageId = deliveredResults . find ( ( entry ) => entry . messageId ) ?. messageId ;
17851809 await maybePinDeliveredMessage ( {
1786- handler,
1810+ handler : deliveryHandler ,
17871811 payload : effectivePayload ,
17881812 target : deliveryTarget ,
17891813 messageId : pinMessageId ,
17901814 } ) ;
17911815 await maybeNotifyAfterDeliveredPayload ( {
1792- handler,
1816+ handler : deliveryHandler ,
17931817 payload : effectivePayload ,
17941818 target : deliveryTarget ,
17951819 results : deliveredResults ,
@@ -1817,21 +1841,25 @@ async function deliverOutboundPayloadsCore(
18171841 continue ;
18181842 }
18191843 throwIfAborted ( abortSignal ) ;
1820- const delivery = handler . sendFormattedMedia
1821- ? await handler . sendFormattedMedia ( unit . caption ?? "" , unit . mediaUrl , unit . overrides )
1822- : await handler . sendMedia ( unit . caption ?? "" , unit . mediaUrl , unit . overrides ) ;
1844+ const delivery = deliveryHandler . sendFormattedMedia
1845+ ? await deliveryHandler . sendFormattedMedia (
1846+ unit . caption ?? "" ,
1847+ unit . mediaUrl ,
1848+ unit . overrides ,
1849+ )
1850+ : await deliveryHandler . sendMedia ( unit . caption ?? "" , unit . mediaUrl , unit . overrides ) ;
18231851 results . push ( delivery ) ;
18241852 firstMessageId ??= delivery . messageId ;
18251853 lastMessageId = delivery . messageId ;
18261854 }
18271855 await maybePinDeliveredMessage ( {
1828- handler,
1856+ handler : deliveryHandler ,
18291857 payload : effectivePayload ,
18301858 target : deliveryTarget ,
18311859 messageId : firstMessageId ,
18321860 } ) ;
18331861 await maybeNotifyAfterDeliveredPayload ( {
1834- handler,
1862+ handler : deliveryHandler ,
18351863 payload : effectivePayload ,
18361864 target : deliveryTarget ,
18371865 results : results . slice ( beforeCount ) ,
0 commit comments