|
1 | 1 | import crypto from "node:crypto"; |
2 | | -import type { ImageContent } from "@earendil-works/pi-ai"; |
3 | 2 | import { |
4 | 3 | hasOutboundReplyContent, |
5 | 4 | resolveSendableOutboundReplyParts, |
@@ -95,8 +94,8 @@ import { |
95 | 94 | resolveQueuedReplyRuntimeConfig, |
96 | 95 | resolveModelFallbackOptions, |
97 | 96 | } from "./agent-runner-utils.js"; |
98 | | -import { resolveAgentTurnAttachments } from "./agent-turn-attachments.js"; |
99 | 97 | import { type BlockReplyPipeline } from "./block-reply-pipeline.js"; |
| 98 | +import { resolveCurrentTurnImages } from "./current-turn-images.js"; |
100 | 99 | import { resolveOriginMessageProvider } from "./origin-routing.js"; |
101 | 100 | import { |
102 | 101 | classifyProviderRequestError, |
@@ -168,80 +167,6 @@ const FALLBACK_SELECTION_STATE_KEYS = [ |
168 | 167 | "authProfileOverrideCompactionCount", |
169 | 168 | ] as const satisfies ReadonlyArray<keyof FallbackSelectionState>; |
170 | 169 |
|
171 | | -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 | | - |
245 | 170 | function setFallbackSelectionStateField( |
246 | 171 | entry: SessionEntry, |
247 | 172 | key: keyof FallbackSelectionState, |
@@ -1252,11 +1177,11 @@ export async function runAgentTurnWithFallback(params: { |
1252 | 1177 | requesterSenderUsername: params.followupRun.run.senderUsername, |
1253 | 1178 | requesterSenderE164: params.followupRun.run.senderE164, |
1254 | 1179 | }); |
1255 | | - const nativePiTurnImages = await resolveNativePiTurnImages({ |
| 1180 | + const currentTurnImages = await resolveCurrentTurnImages({ |
1256 | 1181 | ctx: params.sessionCtx, |
1257 | 1182 | cfg: 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, |
1260 | 1185 | }); |
1261 | 1186 | let didNotifyAgentRunStart = false; |
1262 | 1187 | const notifyAgentRunStart = () => { |
@@ -1770,8 +1695,8 @@ export async function runAgentTurnWithFallback(params: { |
1770 | 1695 | bootstrapPromptWarningSignaturesSeen[ |
1771 | 1696 | bootstrapPromptWarningSignaturesSeen.length - 1 |
1772 | 1697 | ], |
1773 | | - images: params.opts?.images, |
1774 | | - imageOrder: params.opts?.imageOrder, |
| 1698 | + images: currentTurnImages.images, |
| 1699 | + imageOrder: currentTurnImages.imageOrder, |
1775 | 1700 | skillsSnapshot: params.followupRun.run.skillsSnapshot, |
1776 | 1701 | messageChannel: params.followupRun.originatingChannel ?? undefined, |
1777 | 1702 | messageProvider: hookMessageProvider, |
@@ -1889,8 +1814,8 @@ export async function runAgentTurnWithFallback(params: { |
1889 | 1814 | forceHeartbeatTool: params.opts?.forceHeartbeatTool, |
1890 | 1815 | bootstrapContextMode: params.opts?.bootstrapContextMode, |
1891 | 1816 | bootstrapContextRunKind: params.opts?.isHeartbeat ? "heartbeat" : "default", |
1892 | | - images: nativePiTurnImages.images, |
1893 | | - imageOrder: nativePiTurnImages.imageOrder, |
| 1817 | + images: currentTurnImages.images, |
| 1818 | + imageOrder: currentTurnImages.imageOrder, |
1894 | 1819 | abortSignal: params.replyOperation?.abortSignal ?? params.opts?.abortSignal, |
1895 | 1820 | replyOperation: params.replyOperation, |
1896 | 1821 | blockReplyBreak: params.resolvedBlockStreamingBreak, |
|
0 commit comments