





























@@ -1,5 +1,4 @@
11import crypto from "node:crypto";
2-import type { ImageContent } from "@earendil-works/pi-ai";
32import {
43hasOutboundReplyContent,
54resolveSendableOutboundReplyParts,
@@ -95,8 +94,8 @@ import {
9594resolveQueuedReplyRuntimeConfig,
9695resolveModelFallbackOptions,
9796} from "./agent-runner-utils.js";
98-import { resolveAgentTurnAttachments } from "./agent-turn-attachments.js";
9997import { type BlockReplyPipeline } from "./block-reply-pipeline.js";
98+import { resolveCurrentTurnImages } from "./current-turn-images.js";
10099import { resolveOriginMessageProvider } from "./origin-routing.js";
101100import {
102101classifyProviderRequestError,
@@ -168,80 +167,6 @@ const FALLBACK_SELECTION_STATE_KEYS = [
168167"authProfileOverrideCompactionCount",
169168] as const satisfies ReadonlyArray<keyof FallbackSelectionState>;
170169171-function countCurrentPiImageAttachmentCandidates(ctx: TemplateContext): number {
172-const pathsFromArray = Array.isArray(ctx.MediaPaths) ? ctx.MediaPaths : undefined;
173-const paths =
174-pathsFromArray && pathsFromArray.length > 0
175- ? pathsFromArray
176- : normalizeOptionalString(ctx.MediaPath)
177- ? [ctx.MediaPath]
178- : [];
179-if (paths.length === 0) {
180-return 0;
181-}
182-const types =
183-Array.isArray(ctx.MediaTypes) && ctx.MediaTypes.length === paths.length
184- ? ctx.MediaTypes
185- : undefined;
186-let count = 0;
187-for (const [index, pathValue] of paths.entries()) {
188-const mediaPath = normalizeOptionalString(pathValue);
189-const mediaType = normalizeOptionalString(types?.[index] ?? ctx.MediaType);
190-if (mediaPath && mediaType?.startsWith("image/")) {
191-count++;
192-}
193-}
194-return count;
195-}
196-197-async function resolveNativePiTurnImages(params: {
198-ctx: TemplateContext;
199-cfg: OpenClawConfig;
200-images?: ImageContent[];
201-imageOrder?: GetReplyOptions["imageOrder"];
202-}): Promise<{
203-images?: ImageContent[];
204-imageOrder?: GetReplyOptions["imageOrder"];
205-}> {
206-if (Array.isArray(params.images) && params.images.length > 0) {
207-return { images: params.images, imageOrder: params.imageOrder };
208-}
209-210-const currentImageCandidateCount = countCurrentPiImageAttachmentCandidates(params.ctx);
211-if (currentImageCandidateCount === 0) {
212-return { images: params.images, imageOrder: params.imageOrder };
213-}
214-215-try {
216-const resolved = await resolveAgentTurnAttachments({
217-ctx: params.ctx,
218-cfg: params.cfg,
219-includeRecentHistoryImages: false,
220-});
221-const images = resolved.attachments.map(
222-(attachment): ImageContent => ({
223-type: "image",
224-data: attachment.data,
225-mimeType: attachment.mediaType,
226-}),
227-);
228-if (images.length < currentImageCandidateCount) {
229-logVerbose(
230-`agent-runner: native PI media resolution produced ${images.length}/${currentImageCandidateCount} current image attachment(s); falling back to prompt image refs`,
231-);
232-return { images: params.images, imageOrder: params.imageOrder };
233-}
234-return images.length > 0
235- ? { images, imageOrder: images.map(() => "inline" as const) }
236- : { images: params.images, imageOrder: params.imageOrder };
237-} catch (error) {
238-logVerbose(
239-`agent-runner: media attachment image resolution failed, proceeding without native images: ${formatErrorMessage(error)}`,
240-);
241-return { images: params.images, imageOrder: params.imageOrder };
242-}
243-}
244-245170function setFallbackSelectionStateField(
246171entry: SessionEntry,
247172key: keyof FallbackSelectionState,
@@ -1252,11 +1177,11 @@ export async function runAgentTurnWithFallback(params: {
12521177requesterSenderUsername: params.followupRun.run.senderUsername,
12531178requesterSenderE164: params.followupRun.run.senderE164,
12541179});
1255-const nativePiTurnImages = await resolveNativePiTurnImages({
1180+const currentTurnImages = await resolveCurrentTurnImages({
12561181ctx: params.sessionCtx,
12571182cfg: runtimeConfig,
1258-images: params.opts?.images,
1259-imageOrder: params.opts?.imageOrder,
1183+images: params.followupRun.images ?? params.opts?.images,
1184+imageOrder: params.followupRun.imageOrder ?? params.opts?.imageOrder,
12601185});
12611186let didNotifyAgentRunStart = false;
12621187const notifyAgentRunStart = () => {
@@ -1770,8 +1695,8 @@ export async function runAgentTurnWithFallback(params: {
17701695bootstrapPromptWarningSignaturesSeen[
17711696bootstrapPromptWarningSignaturesSeen.length - 1
17721697],
1773-images: params.opts?.images,
1774-imageOrder: params.opts?.imageOrder,
1698+images: currentTurnImages.images,
1699+imageOrder: currentTurnImages.imageOrder,
17751700skillsSnapshot: params.followupRun.run.skillsSnapshot,
17761701messageChannel: params.followupRun.originatingChannel ?? undefined,
17771702messageProvider: hookMessageProvider,
@@ -1889,8 +1814,8 @@ export async function runAgentTurnWithFallback(params: {
18891814forceHeartbeatTool: params.opts?.forceHeartbeatTool,
18901815bootstrapContextMode: params.opts?.bootstrapContextMode,
18911816bootstrapContextRunKind: params.opts?.isHeartbeat ? "heartbeat" : "default",
1892-images: nativePiTurnImages.images,
1893-imageOrder: nativePiTurnImages.imageOrder,
1817+images: currentTurnImages.images,
1818+imageOrder: currentTurnImages.imageOrder,
18941819abortSignal: params.replyOperation?.abortSignal ?? params.opts?.abortSignal,
18951820replyOperation: params.replyOperation,
18961821blockReplyBreak: params.resolvedBlockStreamingBreak,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。