@@ -193,18 +193,67 @@ function resolveInboundEchoMessageIds(message: IMessagePayload): string[] {
193193 return ids ;
194194}
195195
196+ export function rememberIMessageSkippedFromMeForSelfChatDedupe ( params : {
197+ accountId : string ;
198+ message : IMessagePayload ;
199+ bodyText : string ;
200+ selfChatCache ?: SelfChatCache ;
201+ } ) : void {
202+ if ( params . message . is_from_me !== true ) {
203+ return ;
204+ }
205+ const sender = params . message . sender ?. trim ( ) ;
206+ if ( ! sender ) {
207+ return ;
208+ }
209+ const chatId = params . message . chat_id ?? undefined ;
210+ const isGroup = Boolean ( params . message . is_group ) ;
211+ const chatIdentifierNormalized =
212+ normalizeIMessageHandle ( params . message . chat_identifier ?? "" ) || undefined ;
213+ const destinationCallerIdNormalized =
214+ normalizeIMessageHandle ( params . message . destination_caller_id ?? "" ) || undefined ;
215+ const senderNormalized = normalizeIMessageHandle ( sender ) ;
216+ const createdAt = params . message . created_at ? Date . parse ( params . message . created_at ) : undefined ;
217+ const lookup = {
218+ accountId : params . accountId ,
219+ isGroup,
220+ chatId,
221+ sender,
222+ text : params . bodyText . trim ( ) ,
223+ createdAt,
224+ } ;
225+ const matchesSelfChatDestination =
226+ destinationCallerIdNormalized != null && destinationCallerIdNormalized === senderNormalized ;
227+ const isSelfChat =
228+ ! isGroup &&
229+ chatIdentifierNormalized != null &&
230+ senderNormalized === chatIdentifierNormalized &&
231+ matchesSelfChatDestination ;
232+ const isAmbiguousSelfThread =
233+ ! isGroup &&
234+ chatIdentifierNormalized != null &&
235+ senderNormalized === chatIdentifierNormalized &&
236+ destinationCallerIdNormalized == null ;
237+ if ( isSelfChat ) {
238+ params . selfChatCache ?. remember ( { ...lookup , allowCreatedAtSkew : true } ) ;
239+ } else if ( isAmbiguousSelfThread ) {
240+ params . selfChatCache ?. remember ( lookup ) ;
241+ }
242+ }
243+
196244function hasIMessageEchoMatch ( params : {
197245 echoCache : {
198246 has : (
199247 scope : string ,
200248 lookup : { text ?: string ; messageId ?: string } ,
201- skipIdShortCircuit ?: boolean ,
249+ options ?: boolean | { skipIdShortCircuit ?: boolean ; includePendingText ?: boolean } ,
202250 ) => boolean ;
203251 } ;
204252 scope : string | readonly string [ ] ;
205253 text ?: string ;
206254 messageIds : string [ ] ;
207255 skipIdShortCircuit ?: boolean ;
256+ includePendingText ?: boolean ;
208257} ) : boolean {
209258 // Outbound sends persist echo scopes keyed by whichever target shape was
210259 // used (chat_id, chat_guid, chat_identifier, or imessage:<handle>). Inbound
@@ -232,7 +281,10 @@ function hasIMessageEchoMatch(params: {
232281 params . echoCache . has (
233282 scope ,
234283 { text : params . text , messageId : fallbackMessageId } ,
235- params . skipIdShortCircuit ,
284+ {
285+ skipIdShortCircuit : params . skipIdShortCircuit ,
286+ includePendingText : params . includePendingText ,
287+ } ,
236288 )
237289 ) {
238290 return true ;
@@ -349,7 +401,7 @@ export async function resolveIMessageInboundDecision(params: {
349401 has : (
350402 scope : string ,
351403 lookup : { text ?: string ; messageId ?: string } ,
352- skipIdShortCircuit ?: boolean ,
404+ options ?: boolean | { skipIdShortCircuit ?: boolean ; includePendingText ?: boolean } ,
353405 ) => boolean ;
354406 } ;
355407 selfChatCache ?: SelfChatCache ;
@@ -453,6 +505,7 @@ export async function resolveIMessageInboundDecision(params: {
453505 text : bodyText || undefined ,
454506 messageIds : inboundMessageIds ,
455507 skipIdShortCircuit : ! hasInboundGuid ,
508+ includePendingText : true ,
456509 } )
457510 ) {
458511 return { kind : "drop" , reason : "agent echo in self-chat" } ;
@@ -649,6 +702,7 @@ export async function resolveIMessageInboundDecision(params: {
649702 scope : echoScope ,
650703 text : bodyText || undefined ,
651704 messageIds : inboundMessageIds ,
705+ includePendingText : isSelfChat ,
652706 } )
653707 ) {
654708 params . logVerbose ?.(
0 commit comments