refactor: route remaining channel history through window (#82220)

This commit is contained in:
Peter Steinberger
2026-05-15 17:27:00 +01:00
committed by GitHub
parent c96795d272
commit 4e6c85d930
21 changed files with 119 additions and 122 deletions

View File

@@ -1,2 +1,2 @@
01967db7ff4d52e187f557a21f6433f7640542b96872eee9d4e97c72e7a4e30c plugin-sdk-api-baseline.json
c88fe1415b3fde1ba1ede62222022768695054c2ad5c97a5975dbe28cd03df75 plugin-sdk-api-baseline.jsonl
0e7b5b1515042e63598a05b23f13e9dedfdfcc2d760e51ffc940d84ff57d284a plugin-sdk-api-baseline.json
82496afcfb75d3c45df5ead23e8aa4140153f502ccb1dfe053794f2411a5a3cd plugin-sdk-api-baseline.jsonl

View File

@@ -51,20 +51,17 @@ export function buildDiscordUntrustedContext(params: {
if (!params.isGuild) {
return undefined;
}
const entries = [
typeof params.channelTopic === "string" && params.channelTopic.trim().length > 0
? {
label: "Discord channel metadata",
source: "discord",
type: "channel_metadata",
payload: {
topic: params.channelTopic.trim(),
},
}
: undefined,
].filter((entry): entry is NonNullable<MsgContext["UntrustedStructuredContext"]>[number] =>
Boolean(entry),
);
const entries: NonNullable<MsgContext["UntrustedStructuredContext"]> = [];
if (typeof params.channelTopic === "string" && params.channelTopic.trim().length > 0) {
entries.push({
label: "Discord channel metadata",
source: "discord",
type: "channel_metadata",
payload: {
topic: params.channelTopic.trim(),
},
});
}
return entries.length > 0 ? entries : undefined;
}

View File

@@ -7,11 +7,8 @@ import {
} from "openclaw/plugin-sdk/conversation-runtime";
import { resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/outbound-runtime";
import {
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
clearHistoryEntriesIfEnabled,
DEFAULT_GROUP_HISTORY_LIMIT,
recordPendingHistoryEntryIfEnabled,
createChannelHistoryWindow,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import {
@@ -679,10 +676,9 @@ export async function handleFeishuMessage(params: {
// Record to pending history for non-broadcast groups only. For broadcast groups,
// the mentioned handler's broadcast dispatch writes the turn directly into all
// agent sessions — buffering here would cause duplicate replay when this account
// later becomes active via buildPendingHistoryContextFromMap.
// later becomes active via the channel history window.
if (!broadcastAgents && chatHistories && groupHistoryKey) {
recordPendingHistoryEntryIfEnabled({
historyMap: chatHistories,
createChannelHistoryWindow({ historyMap: chatHistories }).record({
historyKey: groupHistoryKey,
limit: historyLimit,
entry: {
@@ -1058,8 +1054,8 @@ export async function handleFeishuMessage(params: {
const historyKey = groupHistoryKey;
if (isGroup && historyKey && chatHistories) {
combinedBody = buildPendingHistoryContextFromMap({
historyMap: chatHistories,
const channelHistory = createChannelHistoryWindow({ historyMap: chatHistories });
combinedBody = channelHistory.buildPendingContext({
historyKey,
limit: historyLimit,
currentMessage: combinedBody,
@@ -1077,8 +1073,7 @@ export async function handleFeishuMessage(params: {
const inboundHistory =
isGroup && historyKey && historyLimit > 0 && chatHistories
? buildInboundHistoryFromMap({
historyMap: chatHistories,
? createChannelHistoryWindow({ historyMap: chatHistories }).buildInboundHistory({
historyKey,
limit: historyLimit,
})
@@ -1534,8 +1529,7 @@ export async function handleFeishuMessage(params: {
}
if (isGroup && historyKey && chatHistories) {
clearHistoryEntriesIfEnabled({
historyMap: chatHistories,
createChannelHistoryWindow({ historyMap: chatHistories }).clear({
historyKey,
limit: historyLimit,
});

View File

@@ -20,12 +20,7 @@ import {
import { hasControlCommand } from "openclaw/plugin-sdk/command-auth-native";
import type { DmPolicy, GroupPolicy, OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
import {
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
recordPendingHistoryEntryIfEnabled,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import { createChannelHistoryWindow, type HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
@@ -846,8 +841,7 @@ export async function resolveIMessageInboundDecision(params: {
const effectiveWasMentioned = mentionDecision.effectiveWasMentioned;
if (isGroup && requireMention && canDetectMention && mentionDecision.shouldSkip) {
params.logVerbose?.(`imessage: skipping group message (no mention)`);
recordPendingHistoryEntryIfEnabled({
historyMap: params.groupHistories,
createChannelHistoryWindow({ historyMap: params.groupHistories }).record({
historyKey: historyKey ?? "",
limit: params.historyLimit,
entry: historyKey
@@ -969,8 +963,8 @@ export function buildIMessageInboundContext(params: {
let combinedBody = body;
if (decision.isGroup && decision.historyKey) {
combinedBody = buildPendingHistoryContextFromMap({
historyMap: params.groupHistories,
const channelHistory = createChannelHistoryWindow({ historyMap: params.groupHistories });
combinedBody = channelHistory.buildPendingContext({
historyKey: decision.historyKey,
limit: params.historyLimit,
currentMessage: combinedBody,
@@ -990,8 +984,7 @@ export function buildIMessageInboundContext(params: {
const imessageTo = (decision.isGroup ? chatTarget : undefined) || `imessage:${decision.sender}`;
const inboundHistory =
decision.isGroup && decision.historyKey && params.historyLimit > 0
? buildInboundHistoryFromMap({
historyMap: params.groupHistories,
? createChannelHistoryWindow({ historyMap: params.groupHistories }).buildInboundHistory({
historyKey: decision.historyKey,
limit: params.historyLimit,
})

View File

@@ -54,6 +54,29 @@ vi.mock("openclaw/plugin-sdk/runtime-env", () => ({
}));
vi.mock("openclaw/plugin-sdk/reply-history", () => ({
DEFAULT_GROUP_HISTORY_LIMIT: 20,
createChannelHistoryWindow: ({ historyMap }: { historyMap: Map<string, HistoryEntry[]> }) => ({
record: ({
historyKey,
limit,
entry,
}: {
historyKey: string;
limit: number;
entry: HistoryEntry;
}) => {
const existing = historyMap.get(historyKey) ?? [];
historyMap.set(historyKey, [...existing, entry].slice(-limit));
},
buildInboundHistory: ({ historyKey, limit }: { historyKey: string; limit: number }) => {
if (limit <= 0) {
return undefined;
}
return (historyMap.get(historyKey) ?? []).slice(-limit);
},
clear: ({ historyKey }: { historyKey: string }) => {
historyMap.delete(historyKey);
},
}),
buildInboundHistoryFromMap: ({
historyMap,
historyKey,

View File

@@ -12,8 +12,7 @@ import {
import { createClaimableDedupe, type ClaimableDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
import {
DEFAULT_GROUP_HISTORY_LIMIT,
clearHistoryEntriesIfEnabled,
recordPendingHistoryEntryIfEnabled,
createChannelHistoryWindow,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
@@ -450,8 +449,7 @@ async function handleMessageEvent(event: MessageEvent, context: LineHandlerConte
const historyKey = groupId ?? roomId;
const senderId = sourceInfo.userId ?? "unknown";
if (historyKey && context.groupHistories) {
recordPendingHistoryEntryIfEnabled({
historyMap: context.groupHistories,
createChannelHistoryWindow({ historyMap: context.groupHistories }).record({
historyKey,
limit: context.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT,
entry: {
@@ -503,8 +501,7 @@ async function handleMessageEvent(event: MessageEvent, context: LineHandlerConte
if (isGroup && context.groupHistories) {
const historyKey = groupId ?? roomId;
if (historyKey && context.groupHistories.has(historyKey)) {
clearHistoryEntriesIfEnabled({
historyMap: context.groupHistories,
createChannelHistoryWindow({ historyMap: context.groupHistories }).clear({
historyKey,
limit: context.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT,
});

View File

@@ -14,7 +14,7 @@ import {
resolveRuntimeConversationBindingRoute,
} from "openclaw/plugin-sdk/conversation-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime";
import { buildInboundHistoryFromMap, type HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import { createChannelHistoryWindow, type HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -469,8 +469,7 @@ export async function buildLineMessageContext(params: BuildLineMessageContextPar
const historyKey = isGroup ? peerId : undefined;
const inboundHistory =
historyKey && groupHistories && (historyLimit ?? 0) > 0
? buildInboundHistoryFromMap({
historyMap: groupHistories,
? createChannelHistoryWindow({ historyMap: groupHistories }).buildInboundHistory({
historyKey,
limit: historyLimit ?? 0,
})

View File

@@ -57,6 +57,7 @@ export { rawDataToString } from "openclaw/plugin-sdk/webhook-ingress";
export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
export {
DEFAULT_GROUP_HISTORY_LIMIT,
createChannelHistoryWindow,
buildPendingHistoryContextFromMap,
clearHistoryEntriesIfEnabled,
recordPendingHistoryEntryIfEnabled,

View File

@@ -88,14 +88,12 @@ import type {
import {
buildAgentMediaPayload,
buildModelsProviderData,
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
createChannelHistoryWindow,
createChannelPairingController,
createChannelMessageReplyPipeline,
DEFAULT_GROUP_HISTORY_LIMIT,
logInboundDrop,
logTypingFailure,
recordPendingHistoryEntryIfEnabled,
registerPluginHttpRoute,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveChannelMediaMaxBytes,
@@ -1413,8 +1411,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
const pendingSender = senderName;
const recordPendingHistory = () => {
const trimmed = pendingBody.trim();
recordPendingHistoryEntryIfEnabled({
historyMap: channelHistories,
createChannelHistoryWindow({ historyMap: channelHistories }).record({
limit: historyLimit,
historyKey: historyKey ?? "",
entry:
@@ -1506,8 +1503,8 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
});
let combinedBody = body;
if (historyKey) {
combinedBody = buildPendingHistoryContextFromMap({
historyMap: channelHistories,
const channelHistory = createChannelHistoryWindow({ historyMap: channelHistories });
combinedBody = channelHistory.buildPendingContext({
historyKey,
limit: historyLimit,
currentMessage: combinedBody,
@@ -1530,8 +1527,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
const commandBody = rawText.trim();
const inboundHistory =
historyKey && historyLimit > 0
? buildInboundHistoryFromMap({
historyMap: channelHistories,
? createChannelHistoryWindow({ historyMap: channelHistories }).buildInboundHistory({
historyKey,
limit: historyLimit,
})

View File

@@ -30,6 +30,7 @@ export { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
export {
DEFAULT_GROUP_HISTORY_LIMIT,
createChannelHistoryWindow,
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
recordPendingHistoryEntryIfEnabled,

View File

@@ -16,6 +16,7 @@ export {
type ChatType,
chunkTextForOutbound,
clearHistoryEntriesIfEnabled,
createChannelHistoryWindow,
createAccountStatusSink,
createChannelPairingController,
createChannelMessageReplyPipeline,

View File

@@ -15,10 +15,8 @@ import {
resolveInboundReplyDispatchCounts,
} from "openclaw/plugin-sdk/inbound-reply-dispatch";
import {
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
DEFAULT_GROUP_HISTORY_LIMIT,
recordPendingHistoryEntryIfEnabled,
createChannelHistoryWindow,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import {
@@ -538,8 +536,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
requireMention,
mentioned,
});
recordPendingHistoryEntryIfEnabled({
historyMap: conversationHistories,
createChannelHistoryWindow({ historyMap: conversationHistories }).record({
historyKey: conversationId,
limit: historyLimit,
entry: {
@@ -712,8 +709,8 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
const isRoomish = !isDirectMessage;
const historyKey = isRoomish ? conversationId : undefined;
if (isRoomish && historyKey) {
combinedBody = buildPendingHistoryContextFromMap({
historyMap: conversationHistories,
const channelHistory = createChannelHistoryWindow({ historyMap: conversationHistories });
combinedBody = channelHistory.buildPendingContext({
historyKey,
limit: historyLimit,
currentMessage: combinedBody,
@@ -730,8 +727,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
const inboundHistory =
isRoomish && historyKey && historyLimit > 0
? buildInboundHistoryFromMap({
historyMap: conversationHistories,
? createChannelHistoryWindow({ historyMap: conversationHistories }).buildInboundHistory({
historyKey,
limit: historyLimit,
})

View File

@@ -5,9 +5,7 @@ import {
import { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-mention-gating";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import {
buildPendingHistoryContextFromMap,
clearHistoryEntriesIfEnabled,
recordPendingHistoryEntryIfEnabled,
createChannelHistoryWindow,
type HistoryEntry as SdkHistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import { resolveQQBotEffectivePolicies } from "../engine/access/resolve-policy.js";
@@ -34,8 +32,7 @@ export function createSdkHistoryAdapter(): HistoryPort {
entry?: T | null;
limit: number;
}) {
return recordPendingHistoryEntryIfEnabled({
historyMap: asSdkMap(params.historyMap),
return createChannelHistoryWindow({ historyMap: asSdkMap(params.historyMap) }).record({
historyKey: params.historyKey,
entry: params.entry as SdkHistoryEntry | undefined,
limit: params.limit,
@@ -43,8 +40,9 @@ export function createSdkHistoryAdapter(): HistoryPort {
},
buildPendingHistoryContext(params) {
return buildPendingHistoryContextFromMap({
return createChannelHistoryWindow({
historyMap: asSdkMap(params.historyMap),
}).buildPendingContext({
historyKey: params.historyKey,
limit: params.limit,
currentMessage: params.currentMessage,
@@ -54,8 +52,7 @@ export function createSdkHistoryAdapter(): HistoryPort {
},
clearPendingHistory(params) {
clearHistoryEntriesIfEnabled({
historyMap: asSdkMap(params.historyMap),
createChannelHistoryWindow({ historyMap: asSdkMap(params.historyMap) }).clear({
historyKey: params.historyKey,
limit: params.limit,
});

View File

@@ -26,11 +26,7 @@ import {
} from "openclaw/plugin-sdk/hook-runtime";
import { runInboundReplyTurn } from "openclaw/plugin-sdk/inbound-reply-dispatch";
import { kindFromMime } from "openclaw/plugin-sdk/media-runtime";
import {
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
recordPendingHistoryEntryIfEnabled,
} from "openclaw/plugin-sdk/reply-history";
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
import { dispatchInboundMessage } from "openclaw/plugin-sdk/reply-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
import { createReplyDispatcherWithTyping } from "openclaw/plugin-sdk/reply-runtime";
@@ -162,8 +158,8 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
let combinedBody = body;
const historyKey = entry.isGroup ? (entry.groupId ?? "unknown") : undefined;
if (entry.isGroup && historyKey) {
combinedBody = buildPendingHistoryContextFromMap({
historyMap: deps.groupHistories,
const channelHistory = createChannelHistoryWindow({ historyMap: deps.groupHistories });
combinedBody = channelHistory.buildPendingContext({
historyKey,
limit: deps.historyLimit,
currentMessage: combinedBody,
@@ -187,8 +183,7 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
const signalTo = normalizeSignalMessagingTarget(signalToRaw) ?? signalToRaw;
const inboundHistory =
entry.isGroup && historyKey && deps.historyLimit > 0
? buildInboundHistoryFromMap({
historyMap: deps.groupHistories,
? createChannelHistoryWindow({ historyMap: deps.groupHistories }).buildInboundHistory({
historyKey,
limit: deps.historyLimit,
})
@@ -723,8 +718,7 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
})();
const pendingBodyText = messageText || pendingPlaceholder || visibleQuoteText;
const historyKey = groupId ?? "unknown";
recordPendingHistoryEntryIfEnabled({
historyMap: deps.groupHistories,
createChannelHistoryWindow({ historyMap: deps.groupHistories }).record({
historyKey,
limit: deps.historyLimit,
entry: {

View File

@@ -21,10 +21,7 @@ import {
toInternalMessageReceivedContext,
triggerInternalHook,
} from "openclaw/plugin-sdk/hook-runtime";
import {
recordPendingHistoryEntryIfEnabled,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import { createChannelHistoryWindow, type HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -357,8 +354,7 @@ export async function resolveTelegramInboundBody(params: {
const effectiveWasMentioned = mentionDecision.effectiveWasMentioned;
if (isGroup && requireMention && canDetectMention && mentionDecision.shouldSkip) {
logger.info({ chatId, reason: "no-mention" }, "skipping group message");
recordPendingHistoryEntryIfEnabled({
historyMap: groupHistories,
createChannelHistoryWindow({ historyMap: groupHistories }).record({
historyKey: historyKey ?? "",
limit: historyLimit,
entry: historyKey

View File

@@ -14,11 +14,7 @@ import type {
TelegramTopicConfig,
} from "openclaw/plugin-sdk/config-contracts";
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
import {
buildInboundHistoryFromMap,
buildPendingHistoryContextFromMap,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import { createChannelHistoryWindow, type HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import type { ResolvedAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
@@ -374,8 +370,8 @@ export async function buildTelegramInboundContextPayload(params: {
});
let combinedBody = body;
if (isGroup && historyKey && historyLimit > 0) {
combinedBody = buildPendingHistoryContextFromMap({
historyMap: groupHistories,
const channelHistory = createChannelHistoryWindow({ historyMap: groupHistories });
combinedBody = channelHistory.buildPendingContext({
historyKey,
limit: historyLimit,
currentMessage: combinedBody,
@@ -401,8 +397,7 @@ export async function buildTelegramInboundContextPayload(params: {
});
const inboundHistory =
isGroup && historyKey && historyLimit > 0
? buildInboundHistoryFromMap({
historyMap: groupHistories,
? createChannelHistoryWindow({ historyMap: groupHistories }).buildInboundHistory({
historyKey,
limit: historyLimit,
})

View File

@@ -40,7 +40,7 @@ import {
projectOutboundPayloadPlanForDelivery,
} from "openclaw/plugin-sdk/outbound-runtime";
import { chunkMarkdownTextWithMode } from "openclaw/plugin-sdk/reply-chunking";
import { clearHistoryEntriesIfEnabled } from "openclaw/plugin-sdk/reply-history";
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-payload";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
@@ -876,8 +876,7 @@ export const dispatchTelegramMessage = async ({
);
const clearGroupHistory = () => {
if (isGroup && historyKey) {
clearHistoryEntriesIfEnabled({
historyMap: groupHistories,
createChannelHistoryWindow({ historyMap: groupHistories }).clear({
historyKey,
limit: historyLimit,
});

View File

@@ -3,6 +3,6 @@ export {
resolveInboundMentionDecision,
} from "openclaw/plugin-sdk/channel-mention-gating";
export { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
export { recordPendingHistoryEntryIfEnabled } from "openclaw/plugin-sdk/reply-history";
export { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
export { parseActivationCommand } from "openclaw/plugin-sdk/group-activation";
export { normalizeE164 } from "../../text-runtime.js";

View File

@@ -17,7 +17,7 @@ import {
implicitMentionKindWhen,
normalizeE164,
parseActivationCommand,
recordPendingHistoryEntryIfEnabled,
createChannelHistoryWindow,
resolveInboundMentionDecision,
} from "./group-gating.runtime.js";
import { noteGroupMember } from "./group-members.js";
@@ -73,8 +73,7 @@ function recordPendingGroupHistoryEntry(params: {
senderIdentity.e164 ??
getPrimaryIdentityId(senderIdentity) ??
"Unknown");
recordPendingHistoryEntryIfEnabled({
historyMap: params.groupHistories,
createChannelHistoryWindow({ historyMap: params.groupHistories }).record({
historyKey: params.groupHistoryKey,
limit: params.groupHistoryLimit,
entry: {

View File

@@ -9,15 +9,11 @@ import type { HistoryEntry, HistoryMediaEntry } from "../../auto-reply/reply/his
type MaybePromise<T> = T | Promise<T>;
export type ChannelHistoryWindow = {
record: (params: {
historyKey: string;
entry?: HistoryEntry | null;
limit: number;
}) => HistoryEntry[];
export type ChannelHistoryWindow<T extends HistoryEntry = HistoryEntry> = {
record: (params: { historyKey: string; entry?: T | null; limit: number }) => T[];
recordWithMedia: (params: {
historyKey: string;
entry?: HistoryEntry | null;
entry?: T | null;
limit: number;
media?:
| readonly HistoryMediaEntry[]
@@ -26,12 +22,12 @@ export type ChannelHistoryWindow = {
mediaLimit?: number;
messageId?: string;
shouldRecord?: () => boolean;
}) => Promise<HistoryEntry[]>;
}) => Promise<T[]>;
buildPendingContext: (params: {
historyKey: string;
limit: number;
currentMessage: string;
formatEntry: (entry: HistoryEntry) => string;
formatEntry: (entry: T) => string;
lineBreak?: string;
}) => string;
buildInboundHistory: (params: {
@@ -41,9 +37,9 @@ export type ChannelHistoryWindow = {
clear: (params: { historyKey: string; limit: number }) => void;
};
export function createChannelHistoryWindow(params: {
historyMap: Map<string, HistoryEntry[]>;
}): ChannelHistoryWindow {
export function createChannelHistoryWindow<T extends HistoryEntry = HistoryEntry>(params: {
historyMap: Map<string, T[]>;
}): ChannelHistoryWindow<T> {
const { historyMap } = params;
return {
record: (recordParams) =>
@@ -70,7 +66,7 @@ export function createChannelHistoryWindow(params: {
historyKey: contextParams.historyKey,
limit: contextParams.limit,
currentMessage: contextParams.currentMessage,
formatEntry: contextParams.formatEntry,
formatEntry: contextParams.formatEntry as (entry: HistoryEntry) => string,
lineBreak: contextParams.lineBreak,
}),
buildInboundHistory: (historyParams) =>

View File

@@ -8,13 +8,36 @@ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../
const migratedMessageTurnFiles = [
"extensions/discord/src/monitor/message-handler.context.ts",
"extensions/discord/src/monitor/message-handler.preflight.ts",
"extensions/feishu/src/bot.ts",
"extensions/imessage/src/monitor/inbound-processing.ts",
"extensions/line/src/bot-handlers.ts",
"extensions/line/src/bot-message-context.ts",
"extensions/mattermost/src/mattermost/monitor.ts",
"extensions/msteams/src/monitor-handler/message-handler.ts",
"extensions/signal/src/monitor/event-handler.ts",
"extensions/slack/src/monitor/message-handler/prepare.ts",
"extensions/telegram/src/bot-message-context.body.ts",
"extensions/telegram/src/bot-message-context.session.ts",
"extensions/telegram/src/bot-message-dispatch.ts",
"extensions/whatsapp/src/auto-reply/monitor/group-gating.ts",
"extensions/zalouser/src/monitor.ts",
];
const historyWindowFiles = [
"extensions/discord/src/monitor/message-handler.context.ts",
"extensions/feishu/src/bot.ts",
"extensions/imessage/src/monitor/inbound-processing.ts",
"extensions/line/src/bot-handlers.ts",
"extensions/line/src/bot-message-context.ts",
"extensions/mattermost/src/mattermost/monitor.ts",
"extensions/msteams/src/monitor-handler/message-handler.ts",
"extensions/qqbot/src/bridge/sdk-adapter.ts",
"extensions/signal/src/monitor/event-handler.ts",
"extensions/slack/src/monitor/message-handler/prepare.ts",
"extensions/telegram/src/bot-message-context.body.ts",
"extensions/telegram/src/bot-message-context.session.ts",
"extensions/telegram/src/bot-message-dispatch.ts",
"extensions/whatsapp/src/auto-reply/monitor/group-gating.ts",
"extensions/zalouser/src/monitor.ts",
];