VS Code 中 Codex 无法粘贴图片的排查与修复:微信能粘,Codex 粘不上

背景

最近在 VS Code 中使用 OpenAI Codex 扩展时,遇到一个很奇怪的问题:

  • 在微信里可以正常 Ctrl + V 粘贴图片。
  • 在 VS Code 的 Codex 输入框里,图片有时能粘贴,有时完全没反应。
  • 偶尔 Ctrl + C / Ctrl + V 还会让 VS Code 短暂卡住。
  • 有时粘贴出来的并不是当前想粘的图片,而是剪贴板里残留的截图或文件。

这个问题表面看像是 VS Code、剪贴板、Codex 扩展、远程桌面软件或微信之间的兼容问题。实际排查后发现,根因是:不同软件复制图片时,写入 Windows 剪贴板的格式并不一样,而 Codex 扩展原本只识别其中一种格式。

现象复现

典型现象如下:

  1. 从微信、截图工具、资源管理器或远程桌面窗口复制一张图片。
  2. 在微信聊天框中粘贴,图片正常出现。
  3. 切到 VS Code 的 Codex 面板中粘贴,图片不出现。
  4. 有时 VS Code 会把图片保存成 Markdown 图片链接,有时完全无反应。
  5. 打开 Codex 面板时可能短暂卡顿,但之后又能恢复。

这类问题很容易误判为:

  • VS Code 坏了。
  • Codex 扩展坏了。
  • 剪贴板权限异常。
  • 图片太大。
  • Windows 系统剪贴板异常。

但真正的问题不在图片本身,而在剪贴板格式。

第一步:确认剪贴板里到底是什么

Windows 剪贴板并不是只有一种“图片”格式。复制图片时,剪贴板里可能出现以下几类数据:

  • Bitmap
  • PNG
  • DIB
  • FileDrop
  • FileNameW
  • FileContents
  • FileGroupDescriptorW
  • text/html
  • text/plain

不同软件写入的格式不同。例如:

  • 截图工具可能写入 Bitmap
  • 资源管理器复制图片文件时,写入的是 FileDrop
  • 微信、远程桌面或部分截图工具可能写入“虚拟文件”格式,如 FileGroupDescriptorW / FileContents
  • Markdown 编辑器可能把图片保存成本地文件,并把 Markdown 链接写回剪贴板。

可以用 PowerShell 检查当前剪贴板格式:

Add-Type -AssemblyName System.Windows.Forms

$data = [System.Windows.Forms.Clipboard]::GetDataObject()

"FORMATS:"
$data.GetFormats() | ForEach-Object { $_ }

"CONTAINS_IMAGE=$([System.Windows.Forms.Clipboard]::ContainsImage())"
"CONTAINS_TEXT=$([System.Windows.Forms.Clipboard]::ContainsText())"
"CONTAINS_FILE_DROP=$([System.Windows.Forms.Clipboard]::ContainsFileDropList())"

if ([System.Windows.Forms.Clipboard]::ContainsFileDropList()) {
    $files = [System.Windows.Forms.Clipboard]::GetFileDropList()
    $files | ForEach-Object { "FILE=$_" }
}

如果输出类似下面这样:

FORMATS:
Shell IDList Array
DataObjectAttributes
Preferred DropEffect
FileDrop
FileNameW
FileName
FileContents
FileGroupDescriptorW

CONTAINS_IMAGE=False
CONTAINS_TEXT=False
CONTAINS_FILE_DROP=True
FILE=<某个图片文件>.png

说明当前剪贴板里不是传统意义上的 Bitmap/Image,而是“文件型图片”。

这就解释了为什么微信能粘贴,而 Codex 粘不上:微信支持这种文件型剪贴板格式,但 Codex 扩展的粘贴逻辑没有覆盖这个分支。

第二步:定位 Codex 扩展的粘贴逻辑

VS Code 扩展的 Webview 前端通常会被打包成一个压缩后的 JS 文件。Codex 扩展中负责图片粘贴的逻辑大致如下:

let onPaste = (event) => {
  if (event.defaultPrevented) return;

  let clipboardData = event.clipboardData;
  if (!clipboardData) return;

  let items = Array.from(clipboardData.items ?? []);
  let files = [];

  for (let item of items) {
    if (item.kind === "file" && item.type.startsWith("image/")) {
      let file = item.getAsFile();
      if (file) files.push(file);
    }
  }

  if (files.length !== 0) {
    event.preventDefault();
    handleImages(files);
  }
};

这段逻辑的问题在于,它只接受:

item.kind === "file" && item.type.startsWith("image/")

也就是说,只有剪贴板条目的 MIME 类型明确是 image/pngimage/jpeg 等,Codex 才会把它当作图片。

但很多 Windows 剪贴板来源并不会给 clipboardData.items 设置 image/* MIME。它们可能只提供:

  • clipboardData.files
  • 文件名是 .png,但 MIME 是空字符串
  • FileDrop 路径
  • 虚拟文件对象

这种情况下,原逻辑就会漏掉图片。

第三步:确认不是临时补丁或其它扩展导致

排查时需要避免“修了一个问题,引入另一个问题”。因此要确认:

  • 没有额外的临时脚本继续拦截 paste
  • 没有多个粘贴 handler 同时处理图片。
  • JS bundle 语法正常。
  • VS Code 日志中没有模块加载失败、语法错误等问题。

可以重点搜索这些关键词:

SyntaxError
Unexpected token
Failed to load module
module script
paste
clipboard
webview

同时检查 VS Code 日志。如果只有类似下面的报错,通常和图片粘贴逻辑无关:

  • WSL 状态检查失败。
  • GitHub 或 ChatGPT 插件同步失败。
  • 网络请求失败。
  • 实验功能开关同步失败。
  • Git workspace metadata warning。

这些可能会导致 Codex 打开时短暂卡顿,但不是图片粘贴失败的根因。

根因总结

最终确认的根因是:

Codex 扩展原始粘贴逻辑只识别 clipboardData.items 中 MIME 类型为 image/* 的文件,但 Windows 下很多复制图片的方式会把图片放在 clipboardData.filesFileDrop 中,并且 MIME 可能为空。结果就是:微信能识别并粘贴,Codex 却漏掉。

也就是说,这不是图片损坏,也不是 VS Code 不支持图片,而是 剪贴板格式兼容性问题

修复思路

修复方法是扩展 Codex 的图片识别条件:

  1. 继续支持原本的 image/* MIME 判断。
  2. 增加对 clipboardData.files 的读取。
  3. 如果 MIME 为空,则根据文件扩展名判断是否是图片。
  4. 避免重复添加同一个文件。

支持的图片扩展名可以包括:

avif
bmp
gif
ico
jpeg
jpg
png
tif
tiff
webp

修复后的核心逻辑

修复后的逻辑可以抽象为:

const isImageFile = (file) => {
  const extension = file?.name?.split(".").pop()?.toLowerCase();

  return (
    file?.type?.startsWith("image/") ||
    [
      "avif",
      "bmp",
      "gif",
      "ico",
      "jpeg",
      "jpg",
      "png",
      "tif",
      "tiff",
      "webp",
    ].includes(extension)
  );
};

const onPaste = (event) => {
  if (event.defaultPrevented) return;

  const clipboardData = event.clipboardData;
  if (!clipboardData) return;

  const files = [];

  for (const item of Array.from(clipboardData.items ?? [])) {
    if (item.kind !== "file") continue;

    const file = item.getAsFile();
    if (file && isImageFile(file)) {
      files.push(file);
    }
  }

  for (const file of Array.from(clipboardData.files ?? [])) {
    if (!isImageFile(file)) continue;

    const exists = files.some(
      (existing) =>
        existing.name === file.name &&
        existing.size === file.size &&
        existing.lastModified === file.lastModified,
    );

    if (!exists) {
      files.push(file);
    }
  }

  if (files.length !== 0) {
    event.preventDefault();
    handleImages(files);
  }
};

这段逻辑的关键点是:

  • 不再只依赖 item.type.startsWith("image/")
  • 增加 clipboardData.files
  • 对 MIME 为空但扩展名是 .png.jpg 等的文件也进行识别。

验证方法

修复后可以用以下方法验证。

1. 检查当前剪贴板格式

复制一张图片文件后,用 PowerShell 检查:

Add-Type -AssemblyName System.Windows.Forms

$data = [System.Windows.Forms.Clipboard]::GetDataObject()
$data.GetFormats()

[System.Windows.Forms.Clipboard]::ContainsImage()
[System.Windows.Forms.Clipboard]::ContainsFileDropList()

如果出现:

ContainsImage() = False
ContainsFileDropList() = True

并且文件扩展名是 .png.jpg 等,那么这就是以前 Codex 容易漏掉的场景。

2. 在微信中粘贴

如果微信能粘贴,说明剪贴板内容本身没有坏。

3. 在 Codex 输入框中粘贴

修复后,Codex 输入框也应该能直接接收图片附件。

4. 检查 JS 语法

如果直接修改了打包后的 JS 文件,可以用 Node.js 做语法检查:

node --check <扩展目录中的 webview 主 JS 文件>

没有输出错误即可。

5. 检查 VS Code 日志

重点确认没有以下错误:

SyntaxError
Unexpected token
Failed to load module

如果只有网络、WSL、插件同步相关 warning/error,通常和粘贴逻辑无关。

为什么打开 Codex 时会卡一下

排查过程中还发现,打开 Codex 面板时可能会有短暂卡顿。这和图片粘贴不是同一个问题。

常见原因包括:

  • Codex 启动时检查 WSL 状态。
  • Codex 尝试同步远程插件。
  • Codex 访问 GitHub 或 ChatGPT 服务失败后等待超时。
  • 扩展初始化时读取 Git workspace 信息。
  • 网络环境不稳定导致请求失败。

这些问题通常会出现在 VS Code 日志里,但不会影响图片粘贴 handler 的逻辑正确性。

注意事项

这个修复本质上是对已安装 VS Code 扩展的前端 bundle 做了兼容性补丁。需要注意:

  1. 扩展自动升级后,修改可能会被覆盖。
  2. 如果扩展版本变化,打包文件名可能变化,需要重新定位粘贴处理逻辑。
  3. 更理想的方式是把这个问题反馈给扩展维护方,由官方在源码中加入兼容逻辑。
  4. 修改前一定要备份原文件。
  5. 修改后一定要做语法检查,并重载 VS Code 窗口。

结论

这次问题的核心不是“VS Code 不能粘贴图片”,也不是“微信特殊处理了图片”,而是:

Windows 剪贴板中图片可能以多种格式存在,而 Codex 扩展原本只识别 image/* MIME 格式,漏掉了 FileDrop / 空 MIME / 文件扩展名可识别的图片。

修复方式也很明确:

  • 保留原来的 image/* 判断。
  • 增加 clipboardData.files
  • 根据图片扩展名兜底识别。
  • 避免重复文件。

修复后,从微信、截图工具、资源管理器等来源复制出来的 .png.jpg 等图片,都可以在 VS Code 的 Codex 输入框中正常粘贴。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐