From 31c305cbbb8ce729733a1c6f7a2d2fba6799ac63 Mon Sep 17 00:00:00 2001 From: Greg Scher Date: Mon, 23 Mar 2026 12:57:37 -0400 Subject: [PATCH] Escape Markdown in alert signals and cap OSINT text in ideas prompt Addresses PR review: escape Markdown-sensitive characters in _formatTieredAlert signal bullets to prevent Telegram Bot API rejections, and add a 1500-char budget for URGENT_OSINT in compactSweepForLLM to bound prompt size while keeping full text upstream. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/alerts/telegram.mjs | 7 ++++++- lib/llm/ideas.mjs | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/alerts/telegram.mjs b/lib/alerts/telegram.mjs index 36a06cf..1a7f6ae 100644 --- a/lib/alerts/telegram.mjs +++ b/lib/alerts/telegram.mjs @@ -730,7 +730,7 @@ Respond with ONLY valid JSON: if (evaluation.signals?.length) { lines.push('', `*Signals:*`); for (const sig of evaluation.signals) { - lines.push(`• ${sig}`); + lines.push(`• ${escapeMd(sig)}`); } } @@ -742,6 +742,11 @@ Respond with ONLY valid JSON: // ─── Helpers ────────────────────────────────────────────────────────────── +function escapeMd(text) { + if (!text) return ''; + return text.replace(/([_*\[\]()~`>#+\-=|{}.!\\])/g, '\\$1'); +} + function parseJSON(text) { if (!text) return null; let cleaned = text.trim(); diff --git a/lib/llm/ideas.mjs b/lib/llm/ideas.mjs index 12a0fc1..1e78e23 100644 --- a/lib/llm/ideas.mjs +++ b/lib/llm/ideas.mjs @@ -88,10 +88,20 @@ function compactSweepForLLM(data, delta, previousIdeas) { sections.push(`SUPPLY_CHAIN: GSCPI=${data.gscpi.value} (${data.gscpi.interpretation})`); } - // Geopolitical signals + // Geopolitical signals (cap total OSINT text to ~1500 chars to keep prompt compact) const urgentPosts = (data.tg?.urgent || []).slice(0, 5); if (urgentPosts.length) { - sections.push(`URGENT_OSINT:\n${urgentPosts.map(p => `- ${p.text || ''}`).join('\n')}`); + const MAX_OSINT_CHARS = 1500; + let remaining = MAX_OSINT_CHARS; + const lines = []; + for (const p of urgentPosts) { + const text = p.text || ''; + if (remaining <= 0) break; + const trimmed = text.length > remaining ? text.substring(0, remaining) + '…' : text; + lines.push(`- ${trimmed}`); + remaining -= trimmed.length; + } + sections.push(`URGENT_OSINT:\n${lines.join('\n')}`); } // Thermal / fire detections