fix(mom): re-apply msg_too_long truncation logic lost in refactoring (#1776)

The truncation logic and error handling added in e1d3c2b7 (Dec 4, 2025)
was lost when message handling was refactored from slack.ts to main.ts.

Changes:
- Add try/catch to all Slack message functions (respond, replaceMessage,
  respondInThread, setTyping, setWorking)
- Truncate main messages at 35K chars (Slack limit 40K)
- Truncate thread messages at 20K chars
- Add helpful user-facing notes when truncation occurs
- Log Slack API errors as warnings instead of crashing

Fixes: msg_too_long API errors causing process crash

Co-authored-by: mom bot <mom-bot@living-bio.iam.gserviceaccount.com>
This commit is contained in:
David Chen 2026-03-04 00:45:06 +08:00 committed by GitHub
parent bc4e4691d4
commit 9a4fe52654
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -141,17 +141,30 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
respond: async (text: string, shouldLog = true) => { respond: async (text: string, shouldLog = true) => {
updatePromise = updatePromise.then(async () => { updatePromise = updatePromise.then(async () => {
accumulatedText = accumulatedText ? `${accumulatedText}\n${text}` : text; try {
const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText; accumulatedText = accumulatedText ? `${accumulatedText}\n${text}` : text;
if (messageTs) { // Truncate accumulated text if too long (Slack limit is 40K, we use 35K for safety)
await slack.updateMessage(event.channel, messageTs, displayText); const MAX_MAIN_LENGTH = 35000;
} else { const truncationNote = "\n\n_(message truncated, ask me to elaborate on specific parts)_";
messageTs = await slack.postMessage(event.channel, displayText); if (accumulatedText.length > MAX_MAIN_LENGTH) {
} accumulatedText =
accumulatedText.substring(0, MAX_MAIN_LENGTH - truncationNote.length) + truncationNote;
}
if (shouldLog && messageTs) { const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;
slack.logBotResponse(event.channel, text, messageTs);
if (messageTs) {
await slack.updateMessage(event.channel, messageTs, displayText);
} else {
messageTs = await slack.postMessage(event.channel, displayText);
}
if (shouldLog && messageTs) {
slack.logBotResponse(event.channel, text, messageTs);
}
} catch (err) {
log.logWarning("Slack respond error", err instanceof Error ? err.message : String(err));
} }
}); });
await updatePromise; await updatePromise;
@ -159,12 +172,25 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
replaceMessage: async (text: string) => { replaceMessage: async (text: string) => {
updatePromise = updatePromise.then(async () => { updatePromise = updatePromise.then(async () => {
accumulatedText = text; try {
const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText; // Replace the accumulated text entirely, with truncation
if (messageTs) { const MAX_MAIN_LENGTH = 35000;
await slack.updateMessage(event.channel, messageTs, displayText); const truncationNote = "\n\n_(message truncated, ask me to elaborate on specific parts)_";
} else { if (text.length > MAX_MAIN_LENGTH) {
messageTs = await slack.postMessage(event.channel, displayText); accumulatedText = text.substring(0, MAX_MAIN_LENGTH - truncationNote.length) + truncationNote;
} else {
accumulatedText = text;
}
const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;
if (messageTs) {
await slack.updateMessage(event.channel, messageTs, displayText);
} else {
messageTs = await slack.postMessage(event.channel, displayText);
}
} catch (err) {
log.logWarning("Slack replaceMessage error", err instanceof Error ? err.message : String(err));
} }
}); });
await updatePromise; await updatePromise;
@ -172,9 +198,20 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
respondInThread: async (text: string) => { respondInThread: async (text: string) => {
updatePromise = updatePromise.then(async () => { updatePromise = updatePromise.then(async () => {
if (messageTs) { try {
const ts = await slack.postInThread(event.channel, messageTs, text); if (messageTs) {
threadMessageTs.push(ts); // Truncate thread messages if too long (20K limit for safety)
const MAX_THREAD_LENGTH = 20000;
let threadText = text;
if (threadText.length > MAX_THREAD_LENGTH) {
threadText = `${threadText.substring(0, MAX_THREAD_LENGTH - 50)}\n\n_(truncated)_`;
}
const ts = await slack.postInThread(event.channel, messageTs, threadText);
threadMessageTs.push(ts);
}
} catch (err) {
log.logWarning("Slack respondInThread error", err instanceof Error ? err.message : String(err));
} }
}); });
await updatePromise; await updatePromise;
@ -183,9 +220,13 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
setTyping: async (isTyping: boolean) => { setTyping: async (isTyping: boolean) => {
if (isTyping && !messageTs) { if (isTyping && !messageTs) {
updatePromise = updatePromise.then(async () => { updatePromise = updatePromise.then(async () => {
if (!messageTs) { try {
accumulatedText = eventFilename ? `_Starting event: ${eventFilename}_` : "_Thinking_"; if (!messageTs) {
messageTs = await slack.postMessage(event.channel, accumulatedText + workingIndicator); accumulatedText = eventFilename ? `_Starting event: ${eventFilename}_` : "_Thinking_";
messageTs = await slack.postMessage(event.channel, accumulatedText + workingIndicator);
}
} catch (err) {
log.logWarning("Slack setTyping error", err instanceof Error ? err.message : String(err));
} }
}); });
await updatePromise; await updatePromise;
@ -198,10 +239,14 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
setWorking: async (working: boolean) => { setWorking: async (working: boolean) => {
updatePromise = updatePromise.then(async () => { updatePromise = updatePromise.then(async () => {
isWorking = working; try {
if (messageTs) { isWorking = working;
const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText; if (messageTs) {
await slack.updateMessage(event.channel, messageTs, displayText); const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;
await slack.updateMessage(event.channel, messageTs, displayText);
}
} catch (err) {
log.logWarning("Slack setWorking error", err instanceof Error ? err.message : String(err));
} }
}); });
await updatePromise; await updatePromise;