Avoid unless necessary; Python's garbage collector typically handles object deletion
del v1_image_url["extras"]
1"""Derivations of standard content blocks from LangChain v0 multimodal content."""23from typing import Any, cast45from langchain_core.messages import content as types678def _convert_v0_multimodal_input_to_v1(9 content: list[types.ContentBlock],10) -> list[types.ContentBlock]:11 """Convert v0 multimodal blocks to v1 format.1213 During the `content_blocks` parsing process, we wrap blocks not recognized as a v114 block as a `'non_standard'` block with the original block stored in the `value`15 field. This function attempts to unpack those blocks and convert any v0 format16 blocks to v1 format.1718 If conversion fails, the block is left as a `'non_standard'` block.1920 Args:21 content: List of content blocks to process.2223 Returns:24 v1 content blocks.25 """26 converted_blocks = []27 unpacked_blocks: list[dict[str, Any]] = [28 cast("dict[str, Any]", block)29 if block.get("type") != "non_standard"30 else block["value"] # type: ignore[typeddict-item] # this is only non-standard blocks31 for block in content32 ]33 for block in unpacked_blocks:34 if block.get("type") in {"image", "audio", "file"} and "source_type" in block:35 converted_block = _convert_legacy_v0_content_block_to_v1(block)36 converted_blocks.append(cast("types.ContentBlock", converted_block))37 elif block.get("type") in types.KNOWN_BLOCK_TYPES:38 # Guard in case this function is used outside of the .content_blocks flow39 converted_blocks.append(cast("types.ContentBlock", block))40 else:41 converted_blocks.append({"type": "non_standard", "value": block})4243 return converted_blocks444546def _convert_legacy_v0_content_block_to_v1(47 block: dict,48) -> types.ContentBlock | dict:49 """Convert a LangChain v0 content block to v1 format.5051 Preserves unknown keys as extras to avoid data loss.5253 Returns the original block unchanged if it's not in v0 format.54 """5556 def _extract_v0_extras(block_dict: dict, known_keys: set[str]) -> dict[str, Any]:57 """Extract unknown keys from v0 block to preserve as extras.5859 Args:60 block_dict: The original v0 block dictionary.61 known_keys: Set of keys known to be part of the v0 format for this block.6263 Returns:64 A dictionary of extra keys not part of the known v0 format.65 """66 return {k: v for k, v in block_dict.items() if k not in known_keys}6768 # Check if this is actually a v0 format block69 block_type = block.get("type")70 if block_type not in {"image", "audio", "file"} or "source_type" not in block:71 # Not a v0 format block, return unchanged72 return block7374 if block.get("type") == "image":75 source_type = block.get("source_type")76 if source_type == "url":77 # image-url78 known_keys = {"mime_type", "type", "source_type", "url"}79 extras = _extract_v0_extras(block, known_keys)80 if "id" in block:81 return types.create_image_block(82 url=block["url"],83 mime_type=block.get("mime_type"),84 id=block["id"],85 **extras,86 )8788 # Don't construct with an ID if not present in original block89 v1_image_url = types.ImageContentBlock(type="image", url=block["url"])90 if block.get("mime_type"):91 v1_image_url["mime_type"] = block["mime_type"]9293 v1_image_url["extras"] = {}94 for key, value in extras.items():95 if value is not None:96 v1_image_url["extras"][key] = value97 if v1_image_url["extras"] == {}:98 del v1_image_url["extras"]99100 return v1_image_url101 if source_type == "base64":102 # image-base64103 known_keys = {"mime_type", "type", "source_type", "data"}104 extras = _extract_v0_extras(block, known_keys)105 if "id" in block:106 return types.create_image_block(107 base64=block["data"],108 mime_type=block.get("mime_type"),109 id=block["id"],110 **extras,111 )112113 v1_image_base64 = types.ImageContentBlock(114 type="image", base64=block["data"]115 )116 if block.get("mime_type"):117 v1_image_base64["mime_type"] = block["mime_type"]118119 v1_image_base64["extras"] = {}120 for key, value in extras.items():121 if value is not None:122 v1_image_base64["extras"][key] = value123 if v1_image_base64["extras"] == {}:124 del v1_image_base64["extras"]125126 return v1_image_base64127 if source_type == "id":128 # image-id129 known_keys = {"type", "source_type", "id"}130 extras = _extract_v0_extras(block, known_keys)131 # For id `source_type`, `id` is the file reference, not block ID132 v1_image_id = types.ImageContentBlock(type="image", file_id=block["id"])133134 v1_image_id["extras"] = {}135 for key, value in extras.items():136 if value is not None:137 v1_image_id["extras"][key] = value138 if v1_image_id["extras"] == {}:139 del v1_image_id["extras"]140141 return v1_image_id142 elif block.get("type") == "audio":143 source_type = block.get("source_type")144 if source_type == "url":145 # audio-url146 known_keys = {"mime_type", "type", "source_type", "url"}147 extras = _extract_v0_extras(block, known_keys)148 if "id" in block:149 return types.create_audio_block(150 url=block["url"],151 mime_type=block.get("mime_type"),152 id=block["id"],153 **extras,154 )155156 # Don't construct with an ID if not present in original block157 v1_audio_url: types.AudioContentBlock = types.AudioContentBlock(158 type="audio", url=block["url"]159 )160 if block.get("mime_type"):161 v1_audio_url["mime_type"] = block["mime_type"]162163 v1_audio_url["extras"] = {}164 for key, value in extras.items():165 if value is not None:166 v1_audio_url["extras"][key] = value167 if v1_audio_url["extras"] == {}:168 del v1_audio_url["extras"]169170 return v1_audio_url171 if source_type == "base64":172 # audio-base64173 known_keys = {"mime_type", "type", "source_type", "data"}174 extras = _extract_v0_extras(block, known_keys)175 if "id" in block:176 return types.create_audio_block(177 base64=block["data"],178 mime_type=block.get("mime_type"),179 id=block["id"],180 **extras,181 )182183 v1_audio_base64: types.AudioContentBlock = types.AudioContentBlock(184 type="audio", base64=block["data"]185 )186 if block.get("mime_type"):187 v1_audio_base64["mime_type"] = block["mime_type"]188189 v1_audio_base64["extras"] = {}190 for key, value in extras.items():191 if value is not None:192 v1_audio_base64["extras"][key] = value193 if v1_audio_base64["extras"] == {}:194 del v1_audio_base64["extras"]195196 return v1_audio_base64197 if source_type == "id":198 # audio-id199 known_keys = {"type", "source_type", "id"}200 extras = _extract_v0_extras(block, known_keys)201 v1_audio_id: types.AudioContentBlock = types.AudioContentBlock(202 type="audio", file_id=block["id"]203 )204205 v1_audio_id["extras"] = {}206 for key, value in extras.items():207 if value is not None:208 v1_audio_id["extras"][key] = value209 if v1_audio_id["extras"] == {}:210 del v1_audio_id["extras"]211212 return v1_audio_id213 elif block.get("type") == "file":214 source_type = block.get("source_type")215 if source_type == "url":216 # file-url217 known_keys = {"mime_type", "type", "source_type", "url"}218 extras = _extract_v0_extras(block, known_keys)219 if "id" in block:220 return types.create_file_block(221 url=block["url"],222 mime_type=block.get("mime_type"),223 id=block["id"],224 **extras,225 )226227 v1_file_url: types.FileContentBlock = types.FileContentBlock(228 type="file", url=block["url"]229 )230 if block.get("mime_type"):231 v1_file_url["mime_type"] = block["mime_type"]232233 v1_file_url["extras"] = {}234 for key, value in extras.items():235 if value is not None:236 v1_file_url["extras"][key] = value237 if v1_file_url["extras"] == {}:238 del v1_file_url["extras"]239240 return v1_file_url241 if source_type == "base64":242 # file-base64243 known_keys = {"mime_type", "type", "source_type", "data"}244 extras = _extract_v0_extras(block, known_keys)245 if "id" in block:246 return types.create_file_block(247 base64=block["data"],248 mime_type=block.get("mime_type"),249 id=block["id"],250 **extras,251 )252253 v1_file_base64: types.FileContentBlock = types.FileContentBlock(254 type="file", base64=block["data"]255 )256 if block.get("mime_type"):257 v1_file_base64["mime_type"] = block["mime_type"]258259 v1_file_base64["extras"] = {}260 for key, value in extras.items():261 if value is not None:262 v1_file_base64["extras"][key] = value263 if v1_file_base64["extras"] == {}:264 del v1_file_base64["extras"]265266 return v1_file_base64267 if source_type == "id":268 # file-id269 known_keys = {"type", "source_type", "id"}270 extras = _extract_v0_extras(block, known_keys)271 return types.create_file_block(file_id=block["id"], **extras)272 if source_type == "text":273 # file-text274 known_keys = {"mime_type", "type", "source_type", "url"}275 extras = _extract_v0_extras(block, known_keys)276 if "id" in block:277 return types.create_plaintext_block(278 # In v0, URL points to the text file content279 # TODO: attribute this claim280 text=block["url"],281 id=block["id"],282 **extras,283 )284285 v1_file_text: types.PlainTextContentBlock = types.PlainTextContentBlock(286 type="text-plain", text=block["url"], mime_type="text/plain"287 )288 if block.get("mime_type"):289 v1_file_text["mime_type"] = block["mime_type"]290291 v1_file_text["extras"] = {}292 for key, value in extras.items():293 if value is not None:294 v1_file_text["extras"][key] = value295 if v1_file_text["extras"] == {}:296 del v1_file_text["extras"]297298 return v1_file_text299300 # If we can't convert, return the block unchanged301 return block
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.