( input: string | Array<ContentBlockParam>, mode: PromptInputMode, setToolJSX: SetToolJSXFn, context: ProcessUserInputContext, pastedContents?: Record<number, PastedContent>, ideSelection?: IDESelection, messages?: Message[], uuid?: string, isAlreadyProcessing?: boolean, querySource?: QuerySource, canUseTool?: CanUseToolFn, permissionMode?: PermissionMode, skipSlashCommands?: boolean, bridgeOrigin?: boolean, isMeta?: boolean, skipAttachments?: boolean, preExpansionInput?: string, )
| 279 | } |
| 280 | |
| 281 | async function processUserInputBase( |
| 282 | input: string | Array<ContentBlockParam>, |
| 283 | mode: PromptInputMode, |
| 284 | setToolJSX: SetToolJSXFn, |
| 285 | context: ProcessUserInputContext, |
| 286 | pastedContents?: Record<number, PastedContent>, |
| 287 | ideSelection?: IDESelection, |
| 288 | messages?: Message[], |
| 289 | uuid?: string, |
| 290 | isAlreadyProcessing?: boolean, |
| 291 | querySource?: QuerySource, |
| 292 | canUseTool?: CanUseToolFn, |
| 293 | permissionMode?: PermissionMode, |
| 294 | skipSlashCommands?: boolean, |
| 295 | bridgeOrigin?: boolean, |
| 296 | isMeta?: boolean, |
| 297 | skipAttachments?: boolean, |
| 298 | preExpansionInput?: string, |
| 299 | ): Promise<ProcessUserInputBaseResult> { |
| 300 | let inputString: string | null = null |
| 301 | let precedingInputBlocks: ContentBlockParam[] = [] |
| 302 | |
| 303 | // Collect image metadata texts for isMeta message |
| 304 | const imageMetadataTexts: string[] = [] |
| 305 | |
| 306 | // Normalized view of `input` with image blocks resized. For string input |
| 307 | // this is just `input`; for array input it's the processed blocks. We pass |
| 308 | // this (not raw `input`) to processTextPrompt so resized/normalized image |
| 309 | // blocks actually reach the API — otherwise the resize work above is |
| 310 | // discarded for the regular prompt path. Also normalizes bridge inputs |
| 311 | // where iOS may send `mediaType` instead of `media_type` (mobile-apps#5825). |
| 312 | let normalizedInput: string | ContentBlockParam[] = input |
| 313 | |
| 314 | if (typeof input === 'string') { |
| 315 | inputString = input |
| 316 | } else if (input.length > 0) { |
| 317 | queryCheckpoint('query_image_processing_start') |
| 318 | const processedBlocks: ContentBlockParam[] = [] |
| 319 | for (const block of input) { |
| 320 | if (block.type === 'image') { |
| 321 | const resized = await maybeResizeAndDownsampleImageBlock(block) |
| 322 | // Collect image metadata for isMeta message |
| 323 | if (resized.dimensions) { |
| 324 | const metadataText = createImageMetadataText(resized.dimensions) |
| 325 | if (metadataText) { |
| 326 | imageMetadataTexts.push(metadataText) |
| 327 | } |
| 328 | } |
| 329 | processedBlocks.push(resized.block) |
| 330 | } else { |
| 331 | processedBlocks.push(block) |
| 332 | } |
| 333 | } |
| 334 | normalizedInput = processedBlocks |
| 335 | queryCheckpoint('query_image_processing_end') |
| 336 | // Extract the input string from the last content block if it is text, |
| 337 | // and keep track of the preceding content blocks |
| 338 | const lastBlock = processedBlocks[processedBlocks.length - 1] |
no test coverage detected