44 ButtonStyle ,
55 Client ,
66 GatewayIntentBits ,
7+ MessageFlags ,
78 ModalBuilder ,
89 Partials ,
910 StringSelectMenuBuilder ,
@@ -36,11 +37,12 @@ import {
3637 setGitHubInfoForUser ,
3738 setUserGeneralSettings ,
3839} from "@/config" ;
40+ import { findReplyThreadIdByStatusMessageTs } from "@/config/local/sessions" ;
3941import { isThreadActive , markThreadActive } from "@/config/local/settings" ;
4042import { log } from "@/utils" ;
4143
4244const DISCORD_MESSAGE_LIMIT = 2000 ;
43- const DISCORD_THREAD_NAME_LIMIT = 100 ;
45+ const DISCORD_THREAD_NAME_LIMIT = 25 ;
4446const DISCORD_MODAL_CHANNEL = "ode:modal:channel_details" ;
4547const DISCORD_MODAL_GITHUB = "ode:modal:github" ;
4648const STATUS_FORMAT_OPTIONS = [ "aggressive" , "medium" , "minimum" ] as const ;
@@ -132,25 +134,31 @@ async function updateMessage(
132134 _asMarkdown = true
133135) : Promise < void > {
134136 try {
135- const threadId = statusMessageThreadMap . get ( messageId ) || channelId ;
137+ const mappedThreadId = statusMessageThreadMap . get ( messageId ) ;
138+ const persistedThreadId = findReplyThreadIdByStatusMessageTs ( messageId ) ;
139+ const threadId = mappedThreadId || persistedThreadId || channelId ;
136140 if ( ! threadId ) {
137141 log . warn ( "Cannot update Discord message without known thread" , { messageId } ) ;
138142 return ;
139143 }
144+ if ( ! mappedThreadId && persistedThreadId ) {
145+ statusMessageThreadMap . set ( messageId , persistedThreadId ) ;
146+ }
140147 const channel = await resolveTextChannel ( threadId ) ;
141148 const message = await channel . messages . fetch ( messageId ) ;
142149 await message . edit ( splitForDiscord ( text ) [ 0 ] ?? text ) ;
143150 } catch ( error ) {
144151 log . warn ( "Failed to update Discord message" , {
145152 messageId,
146153 channelId,
154+ resolvedChannelId : statusMessageThreadMap . get ( messageId ) || findReplyThreadIdByStatusMessageTs ( messageId ) || channelId ,
147155 error : String ( error ) ,
148156 } ) ;
149157 }
150158}
151159
152160async function deleteMessage ( _channelId : string , messageId : string ) : Promise < void > {
153- const threadId = statusMessageThreadMap . get ( messageId ) ;
161+ const threadId = statusMessageThreadMap . get ( messageId ) || findReplyThreadIdByStatusMessageTs ( messageId ) ;
154162 if ( ! threadId ) return ;
155163 const channel = await resolveTextChannel ( threadId ) ;
156164 const message = await channel . messages . fetch ( messageId ) ;
@@ -539,7 +547,7 @@ async function handleLauncherButtonInteraction(interaction: any): Promise<void>
539547 channelId,
540548 userId : interaction . user . id ,
541549 } ) ;
542- await interaction . reply ( { ...payload , ephemeral : true } ) ;
550+ await interaction . reply ( { ...payload , flags : MessageFlags . Ephemeral } ) ;
543551 return ;
544552 }
545553
@@ -548,7 +556,7 @@ async function handleLauncherButtonInteraction(interaction: any): Promise<void>
548556 channelId,
549557 userId : interaction . user . id ,
550558 } ) ;
551- await interaction . reply ( { ...payload , ephemeral : true } ) ;
559+ await interaction . reply ( { ...payload , flags : MessageFlags . Ephemeral } ) ;
552560 return ;
553561 }
554562
@@ -573,7 +581,7 @@ async function handleModalSubmitInteraction(interaction: any): Promise<void> {
573581 setChannelBaseBranch ( channelId , baseBranch ) ;
574582 setChannelSystemMessage ( channelId , channelSystemMessage ) ;
575583
576- await interaction . reply ( { content : "Channel settings updated." , ephemeral : true } ) ;
584+ await interaction . reply ( { content : "Channel settings updated." , flags : MessageFlags . Ephemeral } ) ;
577585 return ;
578586 }
579587
@@ -586,7 +594,7 @@ async function handleModalSubmitInteraction(interaction: any): Promise<void> {
586594 gitName,
587595 gitEmail,
588596 } ) ;
589- await interaction . reply ( { content : "GitHub info updated." , ephemeral : true } ) ;
597+ await interaction . reply ( { content : "GitHub info updated." , flags : MessageFlags . Ephemeral } ) ;
590598 }
591599}
592600
@@ -606,7 +614,7 @@ async function handleGeneralSettingsComponentInteraction(interaction: any): Prom
606614 const selected = interaction . values ?. [ 0 ] as string | undefined ;
607615 const parsed = selected ? parseGeneralStatusFormat ( selected ) : null ;
608616 if ( ! parsed ) {
609- await interaction . reply ( { content : "Invalid status format." , ephemeral : true } ) ;
617+ await interaction . reply ( { content : "Invalid status format." , flags : MessageFlags . Ephemeral } ) ;
610618 return true ;
611619 }
612620 generalSettingsDrafts . set ( key , {
@@ -622,7 +630,7 @@ async function handleGeneralSettingsComponentInteraction(interaction: any): Prom
622630 const selected = interaction . values ?. [ 0 ] as string | undefined ;
623631 const parsed = selected ? parseGitStrategy ( selected ) : null ;
624632 if ( ! parsed ) {
625- await interaction . reply ( { content : "Invalid git strategy." , ephemeral : true } ) ;
633+ await interaction . reply ( { content : "Invalid git strategy." , flags : MessageFlags . Ephemeral } ) ;
626634 return true ;
627635 }
628636 generalSettingsDrafts . set ( key , {
@@ -640,7 +648,7 @@ async function handleGeneralSettingsComponentInteraction(interaction: any): Prom
640648 gitStrategy : draft . gitStrategy ,
641649 } ) ;
642650 generalSettingsDrafts . delete ( key ) ;
643- await interaction . reply ( { content : "General settings updated." , ephemeral : true } ) ;
651+ await interaction . reply ( { content : "General settings updated." , flags : MessageFlags . Ephemeral } ) ;
644652 return true ;
645653 }
646654
@@ -663,7 +671,7 @@ async function handleChannelSettingsComponentInteraction(interaction: any): Prom
663671 const selected = interaction . values ?. [ 0 ] as string | undefined ;
664672 const parsed = selected ? parseProvider ( selected ) : null ;
665673 if ( ! parsed || ! isAgentEnabled ( parsed ) ) {
666- await interaction . reply ( { content : "Selected provider is invalid or disabled." , ephemeral : true } ) ;
674+ await interaction . reply ( { content : "Selected provider is invalid or disabled." , flags : MessageFlags . Ephemeral } ) ;
667675 return true ;
668676 }
669677 const models = getProviderModels ( parsed ) ;
@@ -693,7 +701,7 @@ async function handleChannelSettingsComponentInteraction(interaction: any): Prom
693701 if ( action === "save" ) {
694702 const models = getProviderModels ( draft . provider ) ;
695703 if ( models . length > 0 && draft . model && ! hasModel ( models , draft . model ) ) {
696- await interaction . reply ( { content : "Selected model is no longer available." , ephemeral : true } ) ;
704+ await interaction . reply ( { content : "Selected model is no longer available." , flags : MessageFlags . Ephemeral } ) ;
697705 return true ;
698706 }
699707
@@ -704,7 +712,7 @@ async function handleChannelSettingsComponentInteraction(interaction: any): Prom
704712 setChannelModel ( channelId , draft . model ) ;
705713 }
706714 channelSettingsDrafts . delete ( key ) ;
707- await interaction . reply ( { content : "Channel provider/model updated." , ephemeral : true } ) ;
715+ await interaction . reply ( { content : "Channel provider/model updated." , flags : MessageFlags . Ephemeral } ) ;
708716 return true ;
709717 }
710718
@@ -881,7 +889,7 @@ export async function startDiscordRuntime(reason: string): Promise<boolean> {
881889
882890 await interaction . reply ( {
883891 ...payload ,
884- ephemeral : true ,
892+ flags : MessageFlags . Ephemeral ,
885893 } ) ;
886894 } catch ( error ) {
887895 log . error ( "Discord interaction handler failed" , { error : String ( error ) } ) ;
0 commit comments