@@ -89,6 +89,41 @@ function createUndescribedImageContext(
8989}
9090
9191/** Resolves current-turn image attachments that were not already described by media understanding. */
92+ export function takeCurrentTurnImages ( ctx : MsgContext ) : {
93+ images ?: ImageContent [ ] ;
94+ imageOrder ?: PromptImageOrderEntry [ ] ;
95+ } {
96+ const images = ctx . CurrentTurnImages ;
97+ if ( images && images . length > 0 ) {
98+ const imageOrder = ctx . CurrentTurnImageOrder ;
99+ delete ctx . CurrentTurnImages ;
100+ delete ctx . CurrentTurnImageOrder ;
101+ return { images, imageOrder } ;
102+ }
103+ return { } ;
104+ }
105+
106+ function mergeImagePayloads ( params : {
107+ baseImages ?: ImageContent [ ] ;
108+ baseImageOrder ?: PromptImageOrderEntry [ ] ;
109+ nextImages ?: ImageContent [ ] ;
110+ nextImageOrder ?: PromptImageOrderEntry [ ] ;
111+ } ) : { images ?: ImageContent [ ] ; imageOrder ?: PromptImageOrderEntry [ ] } {
112+ const nextImages = params . nextImages ?? [ ] ;
113+ if ( nextImages . length === 0 ) {
114+ return { images : params . baseImages , imageOrder : params . baseImageOrder } ;
115+ }
116+ const images = [ ...( params . baseImages ?? [ ] ) , ...nextImages ] ;
117+ const nextOrder =
118+ params . nextImageOrder && params . nextImageOrder . length === nextImages . length
119+ ? params . nextImageOrder
120+ : nextImages . map ( ( ) : PromptImageOrderEntry => "inline" ) ;
121+ return {
122+ images,
123+ imageOrder : [ ...( params . baseImageOrder ?? [ ] ) , ...nextOrder ] ,
124+ } ;
125+ }
126+
92127export async function resolveCurrentTurnImages ( params : {
93128 ctx : MsgContext ;
94129 cfg : OpenClawConfig ;
@@ -98,30 +133,37 @@ export async function resolveCurrentTurnImages(params: {
98133 images ?: ImageContent [ ] ;
99134 imageOrder ?: PromptImageOrderEntry [ ] ;
100135} > {
136+ const extracted = takeCurrentTurnImages ( params . ctx ) ;
137+ let merged = mergeImagePayloads ( {
138+ baseImages : params . images ,
139+ baseImageOrder : params . imageOrder ,
140+ nextImages : extracted . images ,
141+ nextImageOrder : extracted . imageOrder ,
142+ } ) ;
101143 if ( Array . isArray ( params . images ) && params . images . length > 0 ) {
102- return { images : params . images , imageOrder : params . imageOrder } ;
144+ return merged ;
103145 }
104146
105147 const currentImageAttachments = collectCurrentImageAttachments ( params . ctx ) ;
106148 if ( currentImageAttachments . length === 0 ) {
107- return { images : params . images , imageOrder : params . imageOrder } ;
149+ return merged ;
108150 }
109151 const describedImageIndexes = collectDescribedImageAttachmentIndexes ( params . ctx ) ;
110152 const undescribedImageAttachments = currentImageAttachments . filter (
111153 ( attachment ) => ! describedImageIndexes . has ( attachment . index ) ,
112154 ) ;
113155 if ( undescribedImageAttachments . length === 0 ) {
114- return { images : params . images , imageOrder : params . imageOrder } ;
156+ return merged ;
115157 }
116158
117159 try {
118160 // Only send undescribed current images natively; described images already exist as text context.
119- const resolved = await resolveAgentTurnAttachments ( {
161+ const attachmentResult = await resolveAgentTurnAttachments ( {
120162 ctx : createUndescribedImageContext ( params . ctx , undescribedImageAttachments ) ,
121163 cfg : params . cfg ,
122164 includeRecentHistoryImages : false ,
123165 } ) ;
124- const images = resolved . attachments . map (
166+ const images = attachmentResult . attachments . map (
125167 ( attachment ) : ImageContent => ( {
126168 type : "image" ,
127169 data : attachment . data ,
@@ -132,15 +174,22 @@ export async function resolveCurrentTurnImages(params: {
132174 logVerbose (
133175 `agent-runner: native OpenClaw media resolution produced ${ images . length } /${ undescribedImageAttachments . length } current image attachment(s); falling back to prompt image refs` ,
134176 ) ;
135- return { images : params . images , imageOrder : params . imageOrder } ;
177+ return merged ;
178+ }
179+ if ( images . length === 0 ) {
180+ return merged ;
136181 }
137- return images . length > 0
138- ? { images, imageOrder : images . map ( ( ) => "inline" as const ) }
139- : { images : params . images , imageOrder : params . imageOrder } ;
182+ merged = mergeImagePayloads ( {
183+ baseImages : merged . images ,
184+ baseImageOrder : merged . imageOrder ,
185+ nextImages : images ,
186+ nextImageOrder : images . map ( ( ) : PromptImageOrderEntry => "inline" ) ,
187+ } ) ;
188+ return merged ;
140189 } catch ( error ) {
141190 logVerbose (
142191 `agent-runner: media attachment image resolution failed, proceeding without native images: ${ formatErrorMessage ( error ) } ` ,
143192 ) ;
144- return { images : params . images , imageOrder : params . imageOrder } ;
193+ return merged ;
145194 }
146195}
0 commit comments