# CodeGeeX IntelliJ 插件补丁工具
**Repository Path**: ariostar/codegeex-intellij-plugin-patch
## Basic Information
- **Project Name**: CodeGeeX IntelliJ 插件补丁工具
- **Description**: 由于CodeGeeX官方长期没有更新,导致IDEA最新的2026版本不能正常运行CodeGeeX。
本项目的目标是以补丁的方式修复此问题。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-15
- **Last Updated**: 2026-09-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# CodeGeeX IntelliJ 插件补丁工具
一个自包含的工具,把**官方** CodeGeeX IntelliJ 插件 jar 转换成一份可直接使用的补丁 jar,使其能在**不受支持的 IDE 版本**上运行(已在 IntelliJ IDEA 2026.2.2 / IU-262.10315.125 上验证),并且不再冻结 IDE。
它是单个可执行 jar —— 无需外部补丁工具、无需手工改 XML、无需 Gradle。从 JetBrains Marketplace 的 [官方历史版本页](https://plugins.jetbrains.com/plugin/20587-codegeex-ai-coding-assistant/versions) 下载官方 CodeGeeX 插件包 `(codegeex-intellij-extension-2.27.4-223.jar)`,用一条命令打上补丁即可。
## 它修复了什么
1. **兼容版本号** —— 改写 `plugin.xml` 里的 `until-build`,让插件能在更新的 IDE 上加载。默认版本号:`262.*`。
2. **IDE 冻结(死锁)** —— `ai/codegeex/plugin/util/PsiUtil.pruneJava` 会在线程池线程上执行 AST 裁剪任务,然后在调用方已持有读锁的情况下阻塞在 `Future.get()` 上。在 IDEA 2026 的锁模型(`NestedLocksThreadingSupport`)下这会造成环状等待,补全 JIT 触发时整个 IDE 卡死。
修复:用 ASM 把该方法体改写为对 `PrunePatch.javaPrune()` 的单一委托,后者在 `ReadAction.compute` 下内联执行(对已持有读锁的线程可重入)—— 没有跨线程等待,也就没有死锁。
3. **JCEF 登录崩溃(IDEA >= 2026.2)** —— `org.cef.*` 从平台类加载器移到了内置模块插件 `com.intellij.modules.jcef`。修复描述符,使用 *可选 + config-file* 形式的依赖:
```xml
com.intellij.modules.jcef
```
同时打入 `META-INF/jcef-plugin.xml` 片段。(若用普通*必选* ``,在 2026.2 上会报 `invalid plugin descriptor`。)
4. **"生成 commit message" 报 EDT 错误(IDEA >= 2026.2)** —— 点击提交窗口的"生成 commit message"时,`CommitMessageSuggestionAction.actionPerformed` 会在 **EDT(UI 线程)** 上同步构建 git diff(`VcsPrompting.prepareContext` → `DiffSimplifier.simplify` → `IdeaTextPatchBuilder.buildPatch` → `GitContentRevision.getContentAsBytes`)。IDEA 2026 起平台明确禁止在 EDT 上调用该方法,直接抛出 `GitContentRevision.getContentAsBytes() should not be called from EDT`,功能不可用。
修复:用 ASM 把该方法体改写为对 `CommitMessageSuggestionActionPatch.perform()` 的单一委托。新实现把 diff 构建放到线程池,UI 更新回到 EDT(`invokeLater`),网络请求照旧在后台线程 —— **绝不在 EDT 上等待后台任务**,因此也避开了与之前死锁修复相同的反模式。它还把 diff 构建做成**健壮化**:若任意单个文件的旧内容取不到(比如移动/删除文件的 `FakeRevision`),逐文件跳过该文件继续生成,而不是整个功能失败(上游 `DiffSimplifier` 会把单文件失败当成整体失败)。
5. **消除"候选问题"服务缺失导致的日志刷屏(上游打包 bug)** —— 官方 `plugin.xml` 声明了 `serviceImplementation="ai.codegeex.plugin.predictions.CodegeexPredictionServiceImpl"`,但该类在官方 jar 中并不存在(只有接口 `CodegeexPredictionService` 和一个实现 `CodegeexPrediction` 接口的 `CodegeexPredictionImpl`,后者也没有无参构造器),导致 IDEA 每次保存设置都会抛 `ClassNotFoundException`。补丁会直接剥离这条无效声明(插件代码里没有任何地方引用该服务),日志恢复干净。
6. **切换工程时报 "Read access" 错误(IDEA >= 2026.2)** —— 插件的全局动作监听器 `CodegeexEditorActionTracker$ActionListener.beforeActionPerformed` 会在**没有持读锁**的情况下调用 `CommonDataKeys.EDITOR.getData(event.getDataContext())`。IDEA 2026 起平台对 PSI 数据源的解析做了硬性断言,在任何动作触发时(比如切换工程的同时触发 `Diff.OpenInEditor`)都会抛出 `Read access is allowed from inside read-action only`。
修复:用 ASM 只把这一处内联数据访问(5 条指令)原位替换为 `CodegeexEditorActionTrackerPatch.getEditor()`,它在 `ReadAction.compute` 内做同样的查找 —— 其余逻辑(字段记录、`isAvailable`)逐字节保留。
7. **Chat 面板空白(JCEF-144 兼容,IDEA >= 2026.2)** —— 插件的 3 个自定 scheme 处理器 `CustomResourceHandler` / `WelcomeResourceHandler` / `ProjectMapResourceHandler` 直接实现了 `org.cef.handler.CefResourceHandler`,但只实现了旧的 4 个方法(`processRequest` / `getResponseHeaders` / `readResponse` / `cancel`)。JCEF 144(Chromium 新内核)给该接口**新增了 3 个抽象方法**:`open()` / `read()` / `skip()`。引擎每次加载资源都会先调用 `open()`,插件的类没有实现它 → 抛 `AbstractMethodError` → Chat 面板一个资源都加载不出来,显示空白。
修复:用 ASM 给这 3 个类各注入 `open` / `read` / `skip` 三个方法,方法体与官方 `CefResourceHandlerAdapter` 默认实现完全一致(即 `open` 设 `handle_request=false` 返回 false;`read` 设 `bytes_read=-1` 返回 false;`skip` 设 `bytes_skipped=-2` 返回 false)。这是 CEF **官方文档化的向后兼容路径**:`open=false,false` 时引擎自动回调废弃的 `ProcessRequest()`、`read=-1,false` 时自动回调废弃的 `ReadResponse()`,所以插件的原有加载逻辑被原样复用,业务零改动。
## 使用方法
```bash
# 在输入 jar 同级生成 <输入名>-patched.jar
java -jar codegeex-patch-tool/lib/cgx-patcher.jar path/to/codegeex-intellij-extension-2.27.4-223.jar
# 指定输出路径
java -jar codegeex-patch-tool/lib/cgx-patcher.jar in.jar out.jar
# 可选参数
java -jar codegeex-patch-tool/lib/cgx-patcher.jar --until-build 263.* in.jar # 自定义版本号
java -jar codegeex-patch-tool/lib/cgx-patcher.jar --no-compat in.jar # 不改 until-build
```
Windows 下也可用:`patch.bat in.jar [out.jar]`
然后把生成的 jar 替换到:
`<用户目录>/AppData/Roaming/JetBrains/IntelliJIdea2026.2/plugins/codegeex-intellij-extension/lib/`
**替换前务必完全退出 IDEA。**
## 幂等性
对已打过补丁的 jar 再运行一次是无操作(no-op),产出的 jar 逐字节相同。
## 从源码构建
`lib/cgx-patcher.jar` 已构建好并随仓库提交,所以只有修改 `src/` 时才需要构建,见 `build.sh`。
```bash
IDEA_HOME="/c/Program Files/JetBrains/IntelliJ IDEA 2026.2" \
JAVA_HOME="/c/Program Files/JetBrains/IntelliJ IDEA 2026.2/jbr" \
PLUGIN_DIR="/c/Users/<你>/AppData/Roaming/JetBrains/IntelliJIdea2026.2/plugins/codegeex-intellij-extension" \
./build.sh
```
- `PLUGIN_DIR` 指向**官方 CodeGeeX 插件的安装目录**。只有设置了它,构建产物才会包含第 4 项(commit message EDT)和第 6 项(编辑器动作跟踪器)修复,因为 `CommitMessageSuggestionActionPatch.java` / `CodegeexEditorActionTrackerPatch.java` 需要引用插件自身的类才能编译。*不加 PLUGIN_DIR 也可以构建,*此时补丁器仍包含死锁 / JCEF / 兼容号 / prediction 清理 / 资源处理器桥接等五项修复,并在打补丁时打印 WARN 提示跳过这两项 EDT 修复。
- IDEA 安装目录里的平台 jar 仅用于编译用到 PSI 的 `PrunePatch.java`、以及 (可选) 引用插件类的 `CommitMessageSuggestionActionPatch.java` / `CodegeexEditorActionTrackerPatch.java`;最终产出的 fat jar 在任何 JDK 17+ 上都能直接运行。
## 注意事项
- 字节码改写依据方法名 + 描述符定位(`pruneJava` / `(Lcom/intellij/psi/PsiFile;)Ljava/lang/String;`、`actionPerformed` / `(Lcom/intellij/openapi/actionSystem/AnActionEvent;)V`,以及 `beforeActionPerformed` / `(Lcom/intellij/openapi/actionSystem/AnAction;Lcom/intellij/openapi/actionSystem/AnActionEvent;)V`)。如果未来插件版本重构了这些方法,对应修复会静默失效 -- 工具会打印它到底改了哪些内容,请注意查看输出。
- 验证方式是手动的:插件能加载、JCEF 登录正常、补全不再抛 `VerifyError`、也不再把 IDE 卡死;"生成 commit message"不再报 EDT 错误并正常产出文案;切换工程不再弹 "Read access" 错误;**Chat 面板能正常显示内容**;`idea.log` 里不再刷 `CodegeexPredictionServiceImpl` 的 `ClassNotFoundException`。
## AI 辅助开发声明
本项目的设计、编码与调试在 **opencode**(一款交互式命令行 AI 编程助手)的辅助下完成,由 **big-pickle** 大模型(模型 ID:`opencode/big-pickle`)驱动,并由作者人工审核、验证与发布。
- 人类作者:**ariostar**
- AI 辅助工具:opencode(https://opencode.ai)
- 使用的模型:big-pickle(`opencode/big-pickle`)
涉及 AI 辅助完成的主要工作:死锁根因分析与方案设计、ASM 字节码补丁实现、JCEF 兼容性修复、"生成 commit message" 的 EDT 阻塞修复(反编译定位、异步化方案、补丁实现)、打包与自动化脚本、测试验证与仓库维护。所有生成内容均经过人工复核。
## 免责声明
本项目是独立开发的兼容性补丁,针对智谱 AI(Zhipu.AI)发布的 [CodeGeeX](https://codegeex.cn) IntelliJ 插件,该插件在 JetBrains Marketplace 上声明的许可是 **Apache License 2.0**。本补丁与 CodeGeeX 官方或 JetBrains 无任何关联。
## 许可证
本项目采用 **Apache License 2.0**,详见 [LICENSE](LICENSE)。
- 随仓库发布的 `lib/cgx-patcher.jar` 内嵌了 ObjectWeb ASM(BSD-3-Clause),其版权声明见 [NOTICE](NOTICE)。
- `PrunePatch.java` 是基于上游 [CodeGeeX](https://codegeex.cn) IntelliJ 插件(厂商声明的 Apache-2.0)裁剪逻辑的免死锁改写作品,文件头含衍生声明,相关引用见 [NOTICE](NOTICE)。按 Apache-2.0 §4(b)-(c),再分发经本工具修改的插件 jar 时须保留上游声明并标注修改。