

























@@ -1,5 +1,9 @@
11import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
2-import { clearHistoryEntriesIfEnabled } from "../../auto-reply/reply/history.js";
2+import {
3+clearHistoryEntriesIfEnabled,
4+recordPendingHistoryEntryWithMedia,
5+} from "../../auto-reply/reply/history.js";
6+import type { HistoryMediaEntry } from "../../auto-reply/reply/history.types.js";
37import { createChannelReplyPipeline } from "../message/reply-pipeline.js";
48import type { CreateChannelReplyPipelineParams } from "../message/reply-pipeline.js";
59import { recordChannelBotPairLoopAndCheckSuppression } from "./bot-loop-protection.js";
@@ -38,6 +42,8 @@ import type {
3842ChannelTurnResolved,
3943ChannelTurnResult,
4044DispatchedChannelTurnResult,
45+InboundMediaFacts,
46+NormalizedTurnInput,
4147PreparedChannelTurn,
4248PreflightFacts,
4349RunChannelTurnParams,
@@ -61,6 +67,7 @@ export type {
6167ChannelTurnAdapter,
6268ChannelTurnAdmission,
6369ChannelTurnDeliveryAdapter,
70+ChannelTurnDroppedHistoryOptions,
6471ChannelTurnHistoryFinalizeOptions,
6572ChannelTurnDispatcherOptions,
6673ChannelTurnLogEvent,
@@ -152,6 +159,85 @@ function clearPendingHistoryAfterTurn(params?: ChannelTurnHistoryFinalizeOptions
152159});
153160}
154161162+function historyMediaFromInboundFacts(
163+media: readonly InboundMediaFacts[] | readonly HistoryMediaEntry[] | null | undefined,
164+messageId: string,
165+): HistoryMediaEntry[] {
166+if (!Array.isArray(media)) {
167+return [];
168+}
169+return media.map((entry) => ({
170+path: entry.path,
171+url: entry.url,
172+contentType: entry.contentType,
173+kind: entry.kind,
174+messageId: entry.messageId ?? messageId,
175+}));
176+}
177+178+function resolveDroppedHistorySender(input: NormalizedTurnInput, preflight: PreflightFacts) {
179+return (
180+preflight.message?.senderLabel ??
181+preflight.message?.envelopeFrom ??
182+(typeof input.raw === "object" &&
183+input.raw &&
184+"sender" in input.raw &&
185+typeof (input.raw as { sender?: unknown }).sender === "string"
186+ ? (input.raw as { sender: string }).sender
187+ : undefined) ??
188+"unknown"
189+);
190+}
191+192+function resolveDroppedHistoryBody(input: NormalizedTurnInput, preflight: PreflightFacts) {
193+return (
194+preflight.message?.bodyForAgent ??
195+preflight.message?.body ??
196+preflight.message?.rawBody ??
197+input.textForAgent ??
198+input.rawText
199+);
200+}
201+202+export async function recordDroppedChannelTurnHistory(params: {
203+input: NormalizedTurnInput;
204+preflight: PreflightFacts;
205+admission?: ChannelTurnAdmission;
206+}): Promise<void> {
207+const admission = params.admission ?? params.preflight.admission;
208+if (admission?.kind !== "drop") {
209+return;
210+}
211+const history = params.preflight.history;
212+if (!history || history.limit <= 0 || !(history.recordOnDrop || admission.recordHistory)) {
213+return;
214+}
215+const body = resolveDroppedHistoryBody(params.input, params.preflight);
216+const entry =
217+body.trim().length > 0
218+ ? {
219+sender: resolveDroppedHistorySender(params.input, params.preflight),
220+ body,
221+timestamp: params.input.timestamp,
222+messageId: params.input.id,
223+}
224+ : null;
225+const media = params.preflight.media;
226+await recordPendingHistoryEntryWithMedia({
227+historyMap: history.historyMap,
228+historyKey: history.key,
229+limit: history.limit,
230+ entry,
231+mediaLimit: history.mediaLimit,
232+messageId: params.input.id,
233+shouldRecord: history.shouldRecord,
234+media:
235+typeof media === "function"
236+ ? async () => historyMediaFromInboundFacts(await media(), params.input.id)
237+ : historyMediaFromInboundFacts(media, params.input.id),
238+});
239+}
240+155241function resolveAssembledReplyPipeline(
156242params: AssembledChannelTurn,
157243): Pick<AssembledChannelTurn, "dispatcherOptions" | "replyOptions"> {
@@ -522,6 +608,11 @@ export async function runChannelTurn<
522608preflightAdmission.kind !== "dispatch" &&
523609preflightAdmission.kind !== "observeOnly"
524610) {
611+await recordDroppedChannelTurnHistory({
612+ input,
613+ preflight,
614+admission: preflightAdmission,
615+});
525616emit({
526617 ...params,
527618event: {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。