import type { AgentMessage } from "@mariozechner/pi-agent-core"; import type { ClawdbotConfig } from "../../config/config.js"; /** * Limits conversation history to the last N user turns (and their associated * assistant responses). This reduces token usage for long-running DM sessions. */ export function limitHistoryTurns( messages: AgentMessage[], limit: number | undefined, ): AgentMessage[] { if (!limit || limit <= 0 || messages.length === 0) return messages; let userCount = 0; let lastUserIndex = messages.length; for (let i = messages.length - 1; i >= 0; i--) { if (messages[i].role === "user") { userCount++; if (userCount > limit) { return messages.slice(lastUserIndex); } lastUserIndex = i; } } return messages; } /** * Extract provider + user ID from a session key and look up dmHistoryLimit. * Supports per-DM overrides and provider defaults. */ export function getDmHistoryLimitFromSessionKey( sessionKey: string | undefined, config: ClawdbotConfig | undefined, ): number | undefined { if (!sessionKey || !config) return undefined; const parts = sessionKey.split(":").filter(Boolean); const providerParts = parts.length >= 3 && parts[0] === "agent" ? parts.slice(2) : parts; const provider = providerParts[0]?.toLowerCase(); if (!provider) return undefined; const kind = providerParts[1]?.toLowerCase(); const userId = providerParts.slice(2).join(":"); if (kind !== "dm") return undefined; const getLimit = ( providerConfig: | { dmHistoryLimit?: number; dms?: Record; } | undefined, ): number | undefined => { if (!providerConfig) return undefined; if (userId && providerConfig.dms?.[userId]?.historyLimit !== undefined) { return providerConfig.dms[userId].historyLimit; } return providerConfig.dmHistoryLimit; }; switch (provider) { case "telegram": return getLimit(config.channels?.telegram); case "whatsapp": return getLimit(config.channels?.whatsapp); case "discord": return getLimit(config.channels?.discord); case "slack": return getLimit(config.channels?.slack); case "signal": return getLimit(config.channels?.signal); case "imessage": return getLimit(config.channels?.imessage); case "msteams": return getLimit(config.channels?.msteams); default: return undefined; } }