



























@@ -92,6 +92,42 @@ function buildLocationContextPayload(ctx: TemplateContext): Record<string, unkno
9292return Object.values(payload).some((value) => value !== undefined) ? payload : undefined;
9393}
949495+function buildReplyChainPayload(ctx: TemplateContext): Array<Record<string, unknown>> {
96+if (!Array.isArray(ctx.ReplyChain)) {
97+return [];
98+}
99+return ctx.ReplyChain.flatMap((entry) => {
100+const body = sanitizePromptBody(entry.body);
101+const mediaType = normalizePromptMetadataString(entry.mediaType);
102+const mediaPath = normalizePromptMetadataString(entry.mediaPath);
103+const mediaRef = normalizePromptMetadataString(entry.mediaRef);
104+if (!body && !mediaType && !mediaPath && !mediaRef) {
105+return [];
106+}
107+return [
108+{
109+message_id: normalizePromptMetadataString(entry.messageId),
110+thread_id: normalizePromptMetadataString(entry.threadId),
111+sender: normalizePromptMetadataString(entry.sender),
112+sender_id: normalizePromptMetadataString(entry.senderId),
113+sender_username: normalizePromptMetadataString(entry.senderUsername),
114+timestamp_ms: typeof entry.timestamp === "number" ? entry.timestamp : undefined,
115+ body,
116+is_quote: entry.isQuote === true ? true : undefined,
117+media_type: mediaType,
118+media_path: mediaPath,
119+media_ref: mediaRef,
120+reply_to_id: normalizePromptMetadataString(entry.replyToId),
121+forwarded_from: normalizePromptMetadataString(entry.forwardedFrom),
122+forwarded_from_id: normalizePromptMetadataString(entry.forwardedFromId),
123+forwarded_from_username: normalizePromptMetadataString(entry.forwardedFromUsername),
124+forwarded_date_ms:
125+typeof entry.forwardedDate === "number" ? entry.forwardedDate : undefined,
126+},
127+];
128+});
129+}
130+95131function formatConversationTimestamp(
96132value: unknown,
97133envelope?: EnvelopeFormatOptions,
@@ -194,6 +230,7 @@ export function buildInboundUserContextPrefix(
194230const timestampStr = formatConversationTimestamp(ctx.Timestamp, envelope);
195231const inboundHistory = Array.isArray(ctx.InboundHistory) ? ctx.InboundHistory : [];
196232const boundedHistory = inboundHistory.slice(-MAX_UNTRUSTED_HISTORY_ENTRIES);
233+const replyChainPayload = buildReplyChainPayload(ctx);
197234198235// Keep volatile conversation/message identifiers in the user-role block so the system
199236// prompt stays byte-stable across task-scoped sessions and reply turns.
@@ -227,7 +264,8 @@ export function buildInboundUserContextPrefix(
227264is_forum: ctx.IsForum === true ? true : undefined,
228265is_group_chat: !isDirect ? true : undefined,
229266was_mentioned: ctx.WasMentioned === true ? true : undefined,
230-has_reply_context: sanitizePromptBody(ctx.ReplyToBody) ? true : undefined,
267+has_reply_context:
268+replyChainPayload.length > 0 || sanitizePromptBody(ctx.ReplyToBody) ? true : undefined,
231269has_forwarded_context: normalizePromptMetadataString(ctx.ForwardedFrom) ? true : undefined,
232270has_thread_starter: sanitizePromptBody(ctx.ThreadStarterBody) ? true : undefined,
233271history_count: boundedHistory.length > 0 ? boundedHistory.length : undefined,
@@ -267,7 +305,14 @@ export function buildInboundUserContextPrefix(
267305}
268306269307const replyToBody = sanitizePromptBody(ctx.ReplyToBody);
270-if (replyToBody) {
308+if (replyChainPayload.length > 0) {
309+blocks.push(
310+formatUntrustedJsonBlock(
311+"Reply chain of current user message (untrusted, nearest first):",
312+replyChainPayload,
313+),
314+);
315+} else if (replyToBody) {
271316blocks.push(
272317formatUntrustedJsonBlock("Reply target of current user message (untrusted, for context):", {
273318sender_label: normalizePromptMetadataString(ctx.ReplyToSender),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。