Grok Bot 开源复刻,卡点究竟在哪
xAI 把 Grok Bot 客户端做成黑盒,b-nnett 凭什么能用源码级方式复刻 0.18.0?本文拆解 2487 星仓库里五个真实工程卡点。
grok-bot-0.18-reconstructed 是开发者 b-nnett 在 GitHub 上发起的非官方项目,目标是以源码导向(source-oriented)的方式复刻并扩展 xAI 的 Grok Bot 0.18.0 客户端。截至 2026 年 8 月 26 日,该仓库已获得 2487 颗星。它火起来的原因很直接——xAI 把 Grok Bot 的客户端逻辑做成黑盒,外部开发者拿不到 JS bundle 之外的任何说明,而这个项目把反编译、模块切分、接口对齐、扩展注入做成了可复现的工程流程,让”读懂 Grok”不再是少数人的特权。
问题一:闭源 bundle 如何拆出可用模块
拿到 0.18.0 发行包,第一关就是拆 bundle。主文件是带字符串混淆的 webpack 输出,直接 require 会报 Cannot find module './chunk-xxx'。根因是 xAI 用了 webpack5 + module federation 做了按需加载,运行时才拼装模块,磁盘上的文件其实只是半成品。
复刻者通过 webpack --json 导出模块清单,再用社区维护的 unwebpack 还原目录树:
npm i -g unwebpack
unwebpack ./grok-bot-0.18.0.asar -o ./src
解法关键:unpack 后保持原 chunk 编号,扩展代码放在 src/extensions/ 平行目录,import 路径与原模块一致,日后合并上游 patch 时 diff 最小。
问题二:扩展代码如何与原模块共存而不覆盖
直接修改拆出的源码会让 0.18.1 升级时整个 diff 炸掉。根因是原作者使用 ast-patch 这一工具,对每个目标函数做 AST 注入,注入位置通过 md5(moduleId + exportName) 锁定,避免版本漂移时误伤。
// src/extensions/streaming-token-counter/index.js
const { patch } = require('ast-patch');
patch('./src/core/chat/sendMessage.js', {
exportName: 'sendMessage',
after: 'stream.onToken'
}, (token) => {
metrics.inc('tokens', token.length);
});
这样做的好处是上游发版只需要重跑 patch 脚本,无需重新解包整个 asar。
问题三:上下文窗口对齐 Grok 2 推理层
Grok Bot 0.18.0 默认调用 Grok-1 推理服务,复刻版若照抄请求体,会被服务端以 unsupported schema 拒掉。根因是 xAI 服务端从 2026 Q2 起强制要求 messages[].role 必须是 system|user|assistant|tool 之一,且 tool_calls 必须带 id。
解法:在 src/adapters/grok2.js 里重写 schema 转换层:
function toGrok2(messages) {
return messages.map(m => ({
role: m.role,
content: m.content,
...(m.tool_calls
? { tool_calls: m.tool_calls.map((t, i) => ({ ...t, id: t.id || `call_${i}` })) }
: {})
}));
}
export { toGrok2 };
问题四:模型 ID 漂移导致接口 404
0.18.0 写死了 grok-1.5-fast,但后端自 8 月初已下线该模型,迁移到 grok-2-mini。根因是 xAI 在加速模型迭代,硬编码必然踩坑。复刻版用 manifest.json + 启动时拉 /api/models 实时刷新:
{
"modelAlias": {
"fast": "grok-2-mini",
"smart": "grok-2"
}
}
启动钩子每 6 小时拉一次最新清单,404 自动降级到次级模型,避免单点失败。
问题五:插件签名校验怎么过
xAI 对官方 plugin 包做 RSA 签名,复刻版的扩展如果不签,会被 pluginLoader 拒绝加载。根因是签名链路在 node_modules/@xai/plugin-loader/lib/verify.js,硬编码公钥指向 xAI 自家 CA,外部证书一律拒绝。
解法是替换 verify.js 里的公钥到自签 CA。这一步只能本地用,作者在 issue #142 里特意警告过:把替换公钥的步骤自动化到 CI 会导致 plugin 拒绝任何加载请求,且明显违反 xAI 服务条款——这就是为什么仓库 README 把它单独标红。
Sources
- GitHub Trending 2026-08-26(b-nnett/grok-bot-0.18-reconstructed,#2487stars)
- r/LocalLLaMA 讨论串:“Reverse engineering closed AI clients”
- 项目 issue #142:公钥替换的安全边界提醒