refactor(display): remove details prepend path, add Matrix reasoning via formatReasoningDisplay

- Remove formatReasoningAsCodeBlock (was experimental, leaked into PR)
- Remove htmlPrefix from OutboundMessage and editMessage signatures
- Add Matrix-specific <details> collapsible to formatReasoningDisplay
- Matrix adapter handles parseMode='HTML' to skip double-escaping
- Reasoning now flows through the standard display path like all adapters
This commit is contained in:
Ani Tunturi
2026-03-17 13:50:01 -04:00
committed by Ani
parent 228b9d74c4
commit f4f1d98655
3 changed files with 14 additions and 34 deletions

View File

@@ -21,7 +21,7 @@ export interface ChannelAdapter {
// Messaging // Messaging
sendMessage(msg: OutboundMessage): Promise<{ messageId: string }>; sendMessage(msg: OutboundMessage): Promise<{ messageId: string }>;
editMessage(chatId: string, messageId: string, text: string, htmlPrefix?: string): Promise<void>; editMessage(chatId: string, messageId: string, text: string): Promise<void>;
sendTypingIndicator(chatId: string): Promise<void>; sendTypingIndicator(chatId: string): Promise<void>;
stopTypingIndicator?(chatId: string): Promise<void>; stopTypingIndicator?(chatId: string): Promise<void>;

View File

@@ -230,6 +230,19 @@ export function formatReasoningDisplay(
// Signal: no blockquote support, use italic // Signal: no blockquote support, use italic
return { text: `**Thinking**\n_${truncated}_` }; return { text: `**Thinking**\n_${truncated}_` };
} }
if (channelId === 'matrix') {
// Matrix: collapsible <details> block — rendered natively by Element Web,
// falls back to visible block on mobile clients.
const escaped = truncated
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\n/g, '<br>');
return {
text: `<details><summary>🧠 Thinking</summary>${escaped}</details>`,
parseMode: 'HTML',
};
}
if (channelId === 'telegram' || channelId === 'telegram-mtproto') { if (channelId === 'telegram' || channelId === 'telegram-mtproto') {
// Telegram: use HTML blockquote to bypass telegramify-markdown spacing. // Telegram: use HTML blockquote to bypass telegramify-markdown spacing.
// Convert basic markdown inline formatting to HTML tags so bold/italic // Convert basic markdown inline formatting to HTML tags so bold/italic
@@ -255,36 +268,6 @@ export function formatReasoningDisplay(
return { text: `> **Thinking**\n${quoted}` }; return { text: `> **Thinking**\n${quoted}` };
} }
/**
* Format reasoning as a collapsible <details> block for prepending to the response.
* Returns pre-escaped HTML meant to be injected directly into formatted_body
* (bypasses the adapter's markdown-to-HTML conversion to avoid double-escaping).
*/
export function formatReasoningAsCodeBlock(
text: string,
channelId?: string,
reasoningMaxChars?: number,
): { text: string } | null {
const maxChars = reasoningMaxChars ?? 0;
const cleaned = text.split('\n').map(line => line.trimStart()).join('\n').trim();
if (!cleaned) return null;
const truncated = maxChars > 0 && cleaned.length > maxChars
? cleaned.slice(0, maxChars) + '...'
: cleaned;
// HTML-escape the reasoning content, then convert newlines to <br>
const escaped = truncated
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\n/g, '<br>');
return {
text: `<details><summary>🧠 Thinking</summary><br>${escaped}</details><br>`,
};
}
/** /**
* Format AskUserQuestion options for channel display. * Format AskUserQuestion options for channel display.
*/ */

View File

@@ -132,9 +132,6 @@ export interface OutboundMessage {
* 'HTML') and to skip its default markdown conversion. Adapters that don't * 'HTML') and to skip its default markdown conversion. Adapters that don't
* support the specified mode ignore this and fall back to default. */ * support the specified mode ignore this and fall back to default. */
parseMode?: string; parseMode?: string;
/** Pre-escaped HTML to prepend to formatted_body only (bypasses markdown conversion).
* Used for reasoning blocks with <details> tags that would be double-escaped. */
htmlPrefix?: string;
} }
/** /**