
treeView 点击不同节点时webView 里的 iframe 地址不跟着变这是我做 VS Code 插件开发教程第六、七节时卡得最久的一个点。第六节解决的是 VS Code 往 html 传 label第七节是 iframe 里的按钮把参数一路传回 VS Code。两条链路本质都是 postMessage但第一次接触很容易漏掉「webviewPanel 只有 undefined 时才会重建 html」这个细节。这次我用 TaoToken 给 Codex 开了条兼容通道https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end让它直接对着 WebView.ts 和 getIframeHtml 补全断点逻辑省了不少试错时间。1. 准备环境TaoToken 拿 KeyCodex 填 Base URL1.1 从 TaoToken 创建 API Key我在原教程里卡住的时候最烦的不是 postMessage 本身而是一边查文档一边还要担心模型额度。这次我先打开 TaoToken 注册并创建 API Key。官网右侧控制台里有 API Keys 页面点创建之后会生成一串 YOUR_API_KEY 格式的密钥复制下来备用。TaoToken 在这里只做一件事让 Codex 能稳定走通模型请求。它不参与插件逻辑也不碰你的 VS Code 工程。换句话说后面写的webviewPanel.webview.postMessage、window.addEventListener、acquireVsCodeApi都是插件自己的事TaoToken 只保证你发给 Codex 的提示词有模型响应。1.2 Codex 配置文件里加 model_provider拿到 Key 后修改~/.codex/config.toml。不要动系统里其他全局配置只新增一个 provider# ~/.codex/config.toml model MODEL_ID_FROM_TAOTOKEN model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEYMODEL_ID_FROM_TAOTOKEN不是固定值以 TaoToken 模型广场 当时列表为准。注意这里的 Base URL 是https://taotoken.net/api末尾不要加v1也不要拼路径。然后设置环境变量export TAOTOKEN_API_KEYYOUR_API_KEY重启终端后在任意项目目录跑一句codex exec ping之类的最简命令能正常返回就说明通道通了。后面所有让 Codex 改代码的操作它都会通过这个 Base URL 走 TaoToken。2. 数据断点一VS Code - html 的 label 传递2.1 为什么 iframe 的 src 永远停在第一次选中项原教程第六节的项目里createWebView接收到 treeView 的 label 后会调用getIframeHtml(label)生成页面。第一次打开 webView 时webviewPanel还是undefined所以会走if分支把初始 label 拼进 iframe srcwebviewPanel.webview.html getIframeHtml(label);当你再点 treeView 的其他节点时webviewPanel已经不是undefined代码会走else分支。如果这个分支里什么都不做那么 html 还是第一次生成的那份iframe 的 src 自然一动不动。2.2 用 postMessage 把 label 推进 html正确的做法是走原教程里提到的postMessage方法。webviewPanel.webview.postMessage({ label })可以在不重建 html 的情况下把新的 label 作为消息发给 webview 的内容。在else分支里补上这句if (webviewPanel undefined) { webviewPanel window.createWebviewPanel( pigView, label, viewColumn, { enableScripts: true } ); webviewPanel.webview.html getIframeHtml(label); } else { webviewPanel.title label; webviewPanel.webview.postMessage({ label: label }); webviewPanel.reveal(); }对应的getIframeHtml里的 script 要加一个message监听器。原来的 HTML 里直接写死了http://localhost:8000/#/pig1现在改成读取事件数据script window.addEventListener(message, (e) { if (e.data.label) { document.getElementById(iframe1).src http://localhost:8000/#/ e.data.label /; } }); /script这一步改完treeView 选到 pig2else 分支就会把{ label: pig2 }发进 html页面里的 iframe src 跟着变成http://localhost:8000/#/pig2/。2.3 让 Codex 照着这个思路补代码如果你不想手敲可以在插件目录下让 Codex 直接改这两个文件。给它的提示词大概是项目是 VS Code 插件treeView 点击不同节点触发 createWebView(label)。 现在 webviewPanel 存在时iframe 的 src 不会随 label 变化。 请在 WebView.ts 的 else 分支补 webviewPanel.webview.postMessage({label}) 并在 getIframeHtml 的 script 里加 window.addEventListener(message) 根据 e.data.label 更新 iframe src。不要改动插件其他逻辑。Codex 返回的 diff 里核心代码就是我上面写的postMessage和addEventListener。插件逻辑不经过 TaoTokenCodex 只是帮你把这两段代码定位并补全。3. 数据断点二iframe 按钮数据回传 VS Code3.1 iframe 里向父页面发消息第七节要解决的是反向链路。iframe 里的 React 页面点按钮后要把pig1这个值一路传给 VS Code。第一步是在 iframe 的按钮事件里调用window.parent.postMessageconst btnClick () { window.parent.postMessage({ ifarmeLabel: pig1 }, *); }; return ( div h2this is pig1/h2 Button onClick{btnClick}showMessage:pig1/Button /div );*表示不限制目标页面路径。真实项目里可以换成父页面具体地址不是必须。3.2 html 里用 acquireVsCodeApi 转发iframe 把消息发给父窗口后父窗口也就是 webView 的 html 要接住。这里必须用acquireVsCodeApi()拿到 VS Code 消息对象再用vscode.postMessage转发const vscode acquireVsCodeApi(); window.addEventListener(message, (e) { if (e.data.label) { document.getElementById(iframe1).src http://localhost:8000/#/ e.data.label /; } if (e.data.ifarmeLabel) { vscode.postMessage({ command: ifarmeLabel, text: e.data.ifarmeLabel }); } });注意acquireVsCodeApi只能在 webview 的 html 里调用iframe 内部用不了。所以转发动作必须放在父页面的 script 里。3.3 VS Code 侧用 onDidReceiveMessage 接收最后回到WebView.ts在创建 webviewPanel 的位置注册onDidReceiveMessage监听。这个方法专门用来接收 html 里vscode.postMessage发来的内容webviewPanel.webview.onDidReceiveMessage((message) { switch (message.command) { case ifarmeLabel: window.showInformationMessage(message.text); break; } });完整链路是iframe 按钮window.parent.postMessage- 父页面acquireVsCodeApi().postMessage- VS CodeonDidReceiveMessage。只要每一步的监听器写对点击 pig1 页面里的按钮VS Code 右下角就会弹出pig1的通知。同样可以让 Codex 帮忙排查这一段。如果点了按钮没反应我会把代码里 iframe 的 Button 和 WebView.ts 的 onDidReceiveMessage 都贴给它让它先检查command标识是否一致再检查 html 里有没有拿到acquireVsCodeApi。4. 跑通后的验证和排障4.1 验证数据链路是否完整打开插件后按下面顺序检查treeView 里选 pig1再选 pig2观察 iframe 地址是否从http://localhost:8000/#/pig1/变成#/pig2/。在 iframe 页面点击showMessage:pig1按钮看 VS Code 右下角是否弹出pig1提示。打开开发人员工具在控制台确认event.data的内容没有 undefined。如果第 1 步失败多半是postMessage没写在else分支里或者addEventListener没挂在window上。如果第 2 步失败先打开 iframe 所在页面的控制台看window.parent.postMessage有没有报错再看父页面有没有执行acquireVsCodeApi()。4.2 配置层面的报错与处理这次接入 TaoToken 后我遇到的报错整理成一张表现象原因处理方式Codex 返回 401TAOTOKEN_API_KEY环境变量没生效或 Key 复制错重新 export确认 Key 来自 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endCodex 报 model not foundconfig.toml里model写成不存在的 ID去模型广场复制当前可用的模型 ID请求超时Base URL 多写了/v1改成https://taotoken.net/api插件无响应webview 里enableScripts没开创建 webviewPanel 时加{ enableScripts: true }注意最后一条是插件本身的问题和 TaoToken 无关。enableScripts不开的话html 里的addEventListener不会执行postMessage 收不到。4.3 回控制台看这次调用验证没问题后回到 TaoToken 控制台 的用量页面能看到刚才 Codex 请求的记录。这里只展示模型调用看不到你的 VS Code 插件代码TaoToken 不读取也不存储插件工程内容。5. 文末从插件 demo 转向日常开发这次跑通的 demo 虽然只有 treeView 和 webView 两条链路但 postMessage 是 VS Code 插件里 webview 通信的基础。后面如果做侧边栏配置面板、内嵌文档预览、或者类似 iframe 嵌套外部系统的功能都会用到同样的postMessageonDidReceiveMessage组合。如果你也想用 Codex 辅助改插件代码先到 TaoToken 模型对话 里用同一把 Key 发一条测试消息确认模型 ID 和 Base URL 都没问题再回到 Codex 里继续干。需要长期写代码的话可以在 Coding Plan 里看套餐是否够用Key 不够用就去 控制台 API Keys 再加。插件通信这条路本质上就是三句话VS Code 用postMessage发数据给 htmlhtml 用addEventListener接收iframe 用window.parent.postMessage往父页面抛数据父页面用acquireVsCodeApi转发给 VS CodeVS Code 用onDidReceiveMessage收结果。把这三句话对应到代码里分步验证每个断点比一次性写完整个链路要靠谱得多。