diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a32fba17..b9a550c5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,8 @@ Docs: https://docs.clawd.bot - Docs: add Bedrock EC2 instance role setup + IAM steps. (#1625) Thanks @sergical. https://docs.clawd.bot/bedrock - Exec approvals: forward approval prompts to chat with `/approve` for all channels (including plugins). (#1621) Thanks @czekaj. https://docs.clawd.bot/tools/exec-approvals https://docs.clawd.bot/tools/slash-commands - Gateway: expose config.patch in the gateway tool with safe partial updates + restart sentinel. (#1653) Thanks @Glucksberg. -- Telegram: treat DM topics as separate sessions and keep DM history limits stable with thread suffixes. -- Telegram: add verbose raw-update logging for inbound Telegram updates. +- Telegram: treat DM topics as separate sessions and keep DM history limits stable with thread suffixes. (#1597) Thanks @rohannagpal. +- Telegram: add verbose raw-update logging for inbound Telegram updates. (#1597) Thanks @rohannagpal. ### Fixes - BlueBubbles: keep part-index GUIDs in reply tags when short IDs are missing. @@ -41,9 +41,9 @@ Docs: https://docs.clawd.bot - Google Chat: tighten email allowlist matching, typing cleanup, media caps, and onboarding/docs/tests. (#1635) Thanks @iHildy. - Google Chat: normalize space targets without double `spaces/` prefix. - Messaging: keep newline chunking safe for fenced markdown blocks across channels. -- Tests: cap Vitest workers on CI macOS to reduce timeouts. -- Tests: avoid fake-timer dependency in embedded runner stream mock to reduce CI flakes. -- Tests: increase embedded runner ordering test timeout to reduce CI flakes. +- Tests: cap Vitest workers on CI macOS to reduce timeouts. (#1597) Thanks @rohannagpal. +- Tests: avoid fake-timer dependency in embedded runner stream mock to reduce CI flakes. (#1597) Thanks @rohannagpal. +- Tests: increase embedded runner ordering test timeout to reduce CI flakes. (#1597) Thanks @rohannagpal. ## 2026.1.23-1 diff --git a/src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts b/src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts index ec2b58f79..8c3be721b 100644 --- a/src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts +++ b/src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts @@ -131,6 +131,16 @@ describe("getDmHistoryLimitFromSessionKey", () => { expect(getDmHistoryLimitFromSessionKey("agent:main:telegram:dm:123:topic:555", config)).toBe(7); expect(getDmHistoryLimitFromSessionKey("telegram:dm:123:thread:999", config)).toBe(7); }); + it("keeps non-numeric thread markers in dm ids", () => { + const config = { + channels: { + telegram: { dms: { "user:thread:abc": { historyLimit: 9 } } }, + }, + } as ClawdbotConfig; + expect(getDmHistoryLimitFromSessionKey("agent:main:telegram:dm:user:thread:abc", config)).toBe( + 9, + ); + }); it("returns undefined for non-dm session kinds", () => { const config = { channels: { diff --git a/src/agents/pi-embedded-runner/history.ts b/src/agents/pi-embedded-runner/history.ts index 37e3e0edf..91706222a 100644 --- a/src/agents/pi-embedded-runner/history.ts +++ b/src/agents/pi-embedded-runner/history.ts @@ -2,17 +2,11 @@ import type { AgentMessage } from "@mariozechner/pi-agent-core"; import type { ClawdbotConfig } from "../../config/config.js"; -const THREAD_SUFFIX_MARKERS = [":thread:", ":topic:"]; +const THREAD_SUFFIX_REGEX = /^(.*)(?::(?:thread|topic):\d+)$/i; function stripThreadSuffix(value: string): string { - const lower = value.toLowerCase(); - let idx = -1; - for (const marker of THREAD_SUFFIX_MARKERS) { - const pos = lower.lastIndexOf(marker); - if (pos > idx) idx = pos; - } - if (idx <= 0) return value; - return value.slice(0, idx); + const match = value.match(THREAD_SUFFIX_REGEX); + return match?.[1] ?? value; } /** diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index 652aaa4e7..d958d5616 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -164,12 +164,36 @@ export function createTelegramBot(opts: TelegramBotOptions) { }; const rawUpdateLogger = createSubsystemLogger("gateway/channels/telegram/raw-update"); + const MAX_RAW_UPDATE_CHARS = 8000; + const MAX_RAW_UPDATE_STRING = 500; + const MAX_RAW_UPDATE_ARRAY = 20; + const stringifyUpdate = (update: unknown) => { + const seen = new WeakSet(); + return JSON.stringify(update ?? null, (key, value) => { + if (typeof value === "string" && value.length > MAX_RAW_UPDATE_STRING) { + return `${value.slice(0, MAX_RAW_UPDATE_STRING)}...`; + } + if (Array.isArray(value) && value.length > MAX_RAW_UPDATE_ARRAY) { + return [ + ...value.slice(0, MAX_RAW_UPDATE_ARRAY), + `...(${value.length - MAX_RAW_UPDATE_ARRAY} more)`, + ]; + } + if (value && typeof value === "object") { + const obj = value as object; + if (seen.has(obj)) return "[Circular]"; + seen.add(obj); + } + return value; + }); + }; bot.use(async (ctx, next) => { if (shouldLogVerbose()) { try { - const raw = JSON.stringify(ctx.update ?? null); - const preview = raw.length > 8000 ? raw.slice(0, 8000) + "…" : raw; + const raw = stringifyUpdate(ctx.update); + const preview = + raw.length > MAX_RAW_UPDATE_CHARS ? `${raw.slice(0, MAX_RAW_UPDATE_CHARS)}...` : raw; rawUpdateLogger.debug(`telegram update: ${preview}`); } catch (err) { rawUpdateLogger.debug(`telegram update log failed: ${String(err)}`);