Codex 跑 Chrome 扩展自动化任务:Key 用 TaoToken
2026/9/14 23:59:17 网站建设 项目流程

1. 先复现问题:Chrome 开关灰色,Codex 调度不了浏览器

在 Codex 桌面端里准备跑 Chrome 扩展自动化任务,最大的拦路虎不是任务本身,而是那个一直灰着的「Google Chrome」开关。由于应用商店区域不可达,扩展只能靠「开发者模式 → 加载已解压的扩展程序」装进去,Chrome 随手分配一个路径派生 ID,桌面端的 Native Messaging 握手直接失败。要修这个问题得走 CRX 离线包 + manifest key 注入;修好之后,Codex 还需要一把能调模型的 Key——打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建 Key,TaoToken 会给你一个统一的兼容通道,让模型请求从 Codex 顺畅发出去。

1.1 从「扩展已加载」到「开关灰色」只差一个 ID

第一次遇到这个问题的人,大概率和我一样先怀疑扩展本身。明明chrome://extensions里能看到扩展卡片,开关也打开了,甚至浏览器里已经出现了扩展的图标,但 Codex 桌面端设置里的「Google Chrome」开关就是灰色,点不动。边栏里那些「打开网页」「读取页面内容」「在页面上执行 JS」的浏览器任务按钮,点了也没有任何反应。

问题不在扩展能否弹出,而在桌面端根本认不出这个扩展。Codex 桌面端通过 Native Messaging 和 Chrome 扩展通信。Native Messaging host 在安装时会把一条通道注册到系统里,通道名称里写死了官方扩展 ID。浏览器侧加载的扩展如果 ID 对不上,桌面端向这条通道发消息时,握手会静默失败,于是界面就停留在「扩展未安装」的状态。

1.2 这条路绕不过官方扩展 ID

所以核心结论是:手动安装的关键不是把扩展文件塞进 Chrome,而是让加载后的扩展拥有和商店版一模一样的扩展 ID。Chrome 对「有没有 key 字段」的扩展,用了完全不同的 ID 派生方式。

带 key 的扩展,Chrome 用 key 里的公钥做 SHA-256,取前 16 字节,再按 0-9a-f 到 a-p 的映射表换成 32 个字母,得到稳定的扩展 ID。不带 key 的扩展,Chrome 直接对加载路径算哈希,路径一换 ID 就变。桌面端只认前者。明白了这一层,后面的 CRX 离线包 + 公钥注入方案就顺理成章了。

2. 修复思路:用官方 CRX 的公钥把扩展 ID 固定下来

既然要得到官方 ID,最干净的办法就是拿到官方签名的 CRX 包,从里面把开发者的公钥提取出来,写进manifest.jsonkey字段。这样 Chrome 加载解压目录时,会按公钥重新计算 ID,计算结果正好等于官方商店版的 ID。

2.1 两种扩展 ID 派生方式对照

应用商店版扩展下载时会携带开发者的公钥信息,Chrome 安装后按公钥推导出一个固定 ID。路径派生版扩展没有key字段,Chrome 只能根据当前文件夹的绝对路径做哈希,路径一变 ID 就变。

加载方式是否携带 keyID 稳定性桌面端能否识别
商店安装固定不变
开发者模式加载解压目录随路径变化不能
注入 key 后再加载解压目录固定为官方 ID

这也解释了为什么直接把manifest.json里的name改成官方名字没用。ID 由公钥算出,和显示名称没有关系。

2.2 修复扩展 ID 只是第一步,模型通道也得接上

扩展 ID 修好之后,Codex 桌面端的开关会亮起,但这只代表 Native Messaging 握手成功。真正跑一条「打开某网页并把内容存下来」的自动化任务时,Codex 还需要把任务拆解成步骤、生成要执行的指令,这一步要调用大模型。模型请求从哪里发出去,同样需要配置。

这时可以把 Key 换成 TaoToken 的:打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册并创建 API Key,把 Codex 的 Base URL 指向 https://taotoken.net/api。TaoToken 在这个场景里充当的是「统一接入」的兼容通道,Codex 负责调度浏览器自动化任务,模型请求走这条通道发出去,两边各管一摊。

3. 准备材料:Python、Chrome SxS、TaoToken 的 API Key

动手之前把材料备齐,后面每一步才不会卡壳。以下是本文环境对应的清单,Windows 11 / Chrome SxS (Canary) / Codex 桌面端 / Python 3.13。

3.1 本机需要准备的软件清单

Python 3 用来解析 CRX3 文件、改写manifest.json。Chrome 浏览器用 SxS、Canary 或 Stable 都可以,本文以 SxS 为例,但后面会提到 Stable 在 Native Messaging 注册上更稳。Codex 桌面端需要提前安装并登录。另外下载 CRX 时,网络需要能访问到clients2.google.com这个 Google 官方扩展更新接口;如果下载失败,可以让能正常访问该接口的机器把codex.crx文件下载好再带回本机,后续解压、注入、加载这几个步骤都不需要再访问外网。

3.2 到 TaoToken 创建 API Key,分清官网和接口两个地址

准备材料里最重要的一步是拿到 API Key。打开 TaoToken,注册账号后在控制台创建 Key,创建好之后会得到一串形如sk-...的字符串,本文统一用YOUR_API_KEY占位。复制后立刻存好,关闭页面可能就看不到了。

这里要特别注意区分两个地址:在浏览器里打开官网页面、创建 Key、看模型广场,用的是https://taotoken.net/?utm_source=taotoken_aicg_blog_end;而填进 Codex 配置文件的 Base URL,是https://taotoken.net/api。后者末尾不带/v1,更不要带utm_source之类的追踪参数,那只是给人点链接用的。

4. 完整操作:从下载 CRX 到 Codex 走 TaoToken 的兼容通道

4.1 确认官方扩展 ID

先确认目标扩展的官方 ID,Codex 浏览器扩展的官方 ID 是hehggadaopoacecdllhhajmbjkdcmajg。你可以在 Codex 官方文档里找到对应链接确认,也可以直接看 Chrome 应用商店地址中/detail/后面那一段。这个 ID 稍后会在多个环节用到:下载 CRX 的请求参数、公钥算完后的校验值、以及最后chrome://extensions里核对扩展卡片。

4.2 用 curl.exe 从 Google 官方更新接口拉取 CRX

Google 的扩展更新接口是公开的,Chrome 浏览器自己更新扩展时走的就是这条通道。手动构造一个请求,就能拿到带官方签名的 CRX 安装包。Windows 11 自带curl.exe,在 PowerShell 里执行时最好写成curl.exe,避免和Invoke-WebRequest的别名冲突:

curl.exe -sSL -o codex.crx "https://clients2.google.com/service/update2/crx?response=redirect&prodversion=154.0.8016.0&acceptformat=crx3&x=id%3Dhehggadaopoacecdllhhajmbjkdcmajg%26uc"

参数说明:prodversion填你当前 Chrome 的版本号;acceptformat=crx3要求返回 CRX3 格式;x=id%3D...%26uc是扩展 ID 加uc标志。下载后可以用Format-Hex确认文件头是Cr24

Format-Hex -Path codex.crx | Select-Object -First 1

看到输出前四个字节是43 72 32 34,也就是 ASCII 的Cr24,说明文件结构正确。

4.3 用 Python 解压 CRX3

CRX3 文件的结构是:固定 12 字节文件头加上一段 protobuf 编码的 header,最后面跟着一个标准 ZIP 包。先写一个解析函数把 ZIP payload 取出来:

import struct import zipfile import io from pathlib import Path def unpack_crx_payload(crx_path: str, out_dir: str): data = Path(crx_path).read_bytes() magic, version, header_len = struct.unpack("<4sII", data[:12]) assert magic == b"Cr24", "不是预期 CRX 文件" assert version == 3, "当前只处理 CRX3 格式" zip_start = 12 + header_len with zipfile.ZipFile(io.BytesIO(data[zip_start:])) as zf: zf.extractall(out_dir) print("解压完成,输出目录:", out_dir) unpack_crx_payload("codex.crx", "codex-chrome-extension")

这段代码只做解压,不影响原文件。执行后会在当前目录生成codex-chrome-extension文件夹,里面就是完整的扩展源码。

4.4 提取公钥并注入 manifest.json 的 key 字段

这是整个修复流程的关键一步。CRX3 的 header 里有一段 protobuf 结构,其中包含开发者的SubjectPublicKeyInfo(DER 格式)。要把这段二进制公钥提取出来,base64 编码后写进manifest.jsonkey字段,Chrome 就会据此重新计算扩展 ID。

import base64 import hashlib import json import struct from pathlib import Path EXPECTED_ID = "hehggadaopoacecdllhhajmbjkdcmajg" def read_varint(buf: bytes, pos: int): result = 0 shift = 0 while True: byte = buf[pos] result |= (byte & 0x7F) << shift pos += 1 if not (byte & 0x80): break shift += 7 return result, pos def walk_fields(buf: bytes): fields = {} pos = 0 end = len(buf) while pos < end: tag, pos = read_varint(buf, pos) field_no = tag >> 3 wire = tag & 0x7 if wire == 2: length, pos = read_varint(buf, pos) fields[field_no] = buf[pos:pos + length] pos += length elif wire == 0: _, pos = read_varint(buf, pos) elif wire == 1: pos += 8 elif wire == 5: pos += 4 else: raise ValueError(f"不支持的 wire type: {wire}") return fields def compute_id_from_pubkey(pubkey_der: bytes) -> str: digest = hashlib.sha256(pubkey_der).hexdigest()[:32] table = str.maketrans("0123456789abcdef", "abcdefghijklmnop") return digest.translate(table) data = Path("codex.crx").read_bytes() header_len = struct.unpack("<I", data[8:12])[0] header = data[12:12 + header_len] top_fields = walk_fields(header) proof = top_fields[2] proof_fields = walk_fields(proof) pubkey_der = proof_fields[1] computed_id = compute_id_from_pubkey(pubkey_der) assert computed_id == EXPECTED_ID, f"公钥算出的 ID 是 {computed_id},与预期不符" print("扩展 ID 校验通过:", computed_id) manifest_path = Path("codex-chrome-extension/manifest.json") manifest = json.loads(manifest_path.read_text(encoding="utf-8")) manifest = { "update_url": manifest.pop("update_url", "https://clients2.google.com/service/update2/crx"), "key": base64.b64encode(pubkey_der).decode("ascii"), **manifest, } manifest_path.write_text( json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", encoding="utf-8", ) print("manifest.json 已注入 key")

脚本最后一步做了断言:如果公钥算出来的 ID 和官方 ID 不一致,直接报错,避免把错误的扩展加载进浏览器。执行成功后,打开manifest.json能看到顶部多了key字段,值是一长串MIIBIjAN...开头的 base64 字符串。

4.5 在 Chrome 里侧载扩展并核对 ID

打开 Chrome,地址栏输入chrome://extensions,右上角开启「开发者模式」,点击「加载已解压的扩展程序」,选择codex-chrome-extension文件夹。加载后扩展卡片上会显示 ID,这时要核对它是不是hehggadaopoacecdllhhajmbjkdcmajg

如果 ID 不对,最大的嫌疑是key字段没写对。移除扩展,重新执行 4.4 步骤,确认公钥提取无误后再加载。ID 正确后,先不要急着跑任务,重启一次 Codex 桌面端,让 Native Messaging 通道重新初始化。

4.6 重启 Codex 后,把模型请求指向 TaoToken 的 Base URL

扩展侧修好,桌面端的「Google Chrome」开关应该已经亮了。此时 Codex 已经能操控浏览器,但它还需要一个模型后端来解析你的指令、编排自动化步骤。打开 Codex 的配置文件~/.codex/config.toml,把模型提供方切成 TaoToken:

# ~/.codex/config.toml model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"

然后在系统环境变量里配置 API Key。PowerShell 里运行(临时生效):

$env:TAOTOKEN_API_KEY = "YOUR_API_KEY"

想永久写入用户环境变量,用setx

setx TAOTOKEN_API_KEY "YOUR_API_KEY"

设置完环境变量后,完全退出并重启 Codex 桌面端。模型 ID 不要凭空猜,打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 的模型广场看当前列表,选一个对应模型 ID 填进 Codex 的model配置。base_url不要加/v1,也不要填官网首页地址,两处用途不同。

4.7 发一条浏览器自动化任务做冒烟测试

配置全部就位后,在 Codex 里发一条最简单的浏览器任务,例如:

打开 https://example.com ,把页面标题写到 D:\codex-browser-test.txt

正常路径下,Codex 会先调用模型理解任务,再通过 Native Messaging 指挥扩展打开指定网页,读取页面标题,最后在本地生成文件。观察两个位置:桌面端设置里的「Google Chrome」开关是否保持开启;边栏里的浏览器任务按钮是否从灰色变成可点击。两者都正常,就说明扩展 ID 修复和模型通道配置都成功了。

5. 踩坑对照:这几处最容易翻车

5.1 扩展 ID 明明对了,开关依然灰色

最常见的原因是 Native Messaging host 没有重新注册。修改扩展后,桌面端和浏览器之间旧握手状态可能还残留在内存里。Solution:关掉所有 Chrome 窗口,托盘里也完全退出 Codex,再重新打开两侧。另一个可能性是桌面端只在 Stable Chrome 的注册表路径下注册了 Native Messaging host,SxS 里扩展 ID 正确但通道不在注册表内,这时需要在 Stable Chrome 里也加载一次同一份解压目录。

5.2 SxS 能加载,Stable 反而没反应

部分桌面端对浏览器的检测只写死在 Stable 版 Chrome 的注册表位置。SxS 或 Canary 虽然能手动加载扩展,但 Native Messaging host 配置里没有对应的浏览器路径,握手仍会失败。最省事的做法是两个浏览器都加载一次解压目录,哪一个开关亮了就用哪一个。

5.3 开发者模式加载的扩展不会自动更新

通过 Load unpacked 加载的扩展不会走应用商店的自动更新通道。官方发布新版本后,你需要重新下载 CRX、重新解压、重新注入 key,然后在chrome://extensions里点「刷新」按钮。建议把原始codex.crx文件留档,每次更新时重复 4.2 到 4.4 的步骤即可。

5.4 模型请求报 401 或 404

Codex 配置好 TaoToken 后,如果任务在第一步就报401 Unauthorized,多半是TAOTOKEN_API_KEY环境变量没生效,或者 Key 复制时少了字符。如果报错接近路由不存在,检查base_url:正确的写法是https://taotoken.net/api,末尾没有/v1。模型 ID 也要和模型广场上的标识完全一致,别用文章里看到的过期名字。

6. 验证清单:从扩展 ID 到模型账单逐条对照

6.1 chrome://extensions 逐项核对

打开chrome://extensions,确认三件事:扩展 ID 是hehggadaopoacecdllhhajmbjkdcmajg;扩展版本和官方版本一致;「已加载」状态正常。任何一项不符合,回到第 4 步重新走一遍。

6.2 在 Codex 里跑通一条完整任务

冒烟测试的任务越简单越好,能覆盖「打开页面、读取内容、写文件」三个动作就可以。跑通后可以尝试稍微复杂的任务,比如打开一个带表单的页面、填写输入框、点击提交按钮,确认扩展的自动化能力是完整的。

6.3 回 TaoToken 控制台对一下这次调用

配置保存后,先在 TaoToken 模型对话 里用同一把 Key 发一条测试消息,确认模型 ID 和 Base URL 没填错。若要长期跑浏览器自动化任务,可以打开 Coding Plan 看套餐是否够用;Key 的创建和管理在 控制台 API Keys 里完成。跑完几轮任务后回控制台看用量记录,能查到对应调用,才算整条链路闭环。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询