OpenCLI doubao 浏览器适配器实战指南:用命令行与 AI Agent 驱动豆包网页版对话
2026/9/19 21:17:53 网站建设 项目流程

OpenCLI doubao 浏览器适配器实战指南:用命令行与 AI Agent 驱动豆包网页版对话

【免费下载链接】OpenCLIMake Any Website into CLI & Use your logged-in browser by AI agent.项目地址: https://gitcode.com/gh_mirrors/ope/OpenCLI

豆包(Doubao Chat)官方并未提供面向开发者与 AI Agent 的稳定 CLI 接口,而 OpenCLI 的doubao浏览器适配器通过复用它已登录的 Chrome 会话,把豆包网页版(https://www.doubao.com/chat)封装成一组完整的命令行工具。本文以 docs/adapters/browser/doubao.md 为骨架,结合 clis/doubao 目录下的真实源码实现,讲解statusnewsendreadaskdetailhistorymeeting-summarymeeting-transcript九个命令的用法、会话机制与底层 DOM 自动化原理,读完后你可以直接用命令行驱动豆包完成对话问答、历史回放与会议纪要提取。

一、前置条件:浏览器桥接与登录态

在使用任何doubao命令之前,需要满足以下三个前提(原文档明确列出):

  1. Chrome 正在运行:适配器不启动新浏览器,而是接管已运行的 Chrome 实例;
  2. 已在 doubao.com 完成登录:登录态以 Cookie 形式存在;
  3. 已为 OpenCLI 安装并启用 Browser Bridge 扩展:这是命令与页面之间通信的桥梁。

关于登录态的判定,源码中有更精确的实现。在 clis/doubao/auth.js 中,hasDoubaoSessionCookie检查https://www.doubao.com域下是否存在名为passport_csrf_token的 Cookie;随后verifyDoubaoIdentity会在当前页面内通过 fetch 请求/passport/account/info/v2/接口,只有当响应中存在user_id_str时才判定为真正登录成功。值得注意的是,源码注释特别说明passport_csrf_token在匿名会话中也会被设置,因此认证流程不会仅凭 Cookie 存在就放行,而是以账户 API 返回的真实user_id为准,避免登录中途误判。

二、命令总览

原文档给出了完整的命令清单,下表在原文基础上补充了各命令的访问权限(read/write)与核心输出字段:

命令描述权限主要输出
opencli doubao status检查页面是否可达、豆包是否已登录readStatus / Login / Url / Title
opencli doubao new开始一个新的豆包对话readStatus / Action
opencli doubao send "..."向当前豆包对话发送一条消息writeStatus / SubmittedBy / InjectedText
opencli doubao read读取当前可见的豆包对话readRole / Text
opencli doubao ask "..."发送提示词并等待回复writeRole / Text
opencli doubao detail <id>对话详情readRole / Text
opencli doubao history历史对话列表readIndex / Id / Title / Url
opencli doubao meeting-summary <id>会议总结(可附加章节)readSection / Content
opencli doubao meeting-transcript <id>会议记录(文本或下载)readSection / Content

所有命令在 clis/doubao 目录中都有对应实现文件,例如status.jssend.jsask.js等。从源码看,每个命令都通过@jackwener/opencli/registrycli()注册,统一声明domain: 'www.doubao.com'strategy: Strategy.COOKIEbrowser: truesiteSession: 'persistent',说明整个适配器采用"复用浏览器 Cookie 会话"的策略,而非账号密码登录。

三、常用命令实操示例

原文档给出了以下可直接运行的示例:

opencli doubao status opencli doubao new opencli doubao send "帮我总结这段文档" opencli doubao read opencli doubao ask "请写一个 Python 快速排序示例" --timeout 90

各命令的细节与参数说明如下。

1. status:探测页面与登录态

status会跳转到豆包聊天页并读取页面状态。status.js 内部调用getDoubaoPageState,通过注入页面的getStateScript读取window._ROUTER_DATA?.loaderData?.chat_layout中的userSetting.data.is_login字段、当前 URL、页面标题和输入框 placeholder。返回结果中Login可能是Yes/No/Unknown(当页面数据尚未加载完成时为 Unknown),Status相应显示ConnectedLogin Required

2. new:开启新对话

new命令先尝试点击页面上的 "新对话 / New Chat" 按钮,找不到时再回退到新建会话路由。这个逻辑在 utils.js 的clickNewChatScript中实现:它遍历页面中所有button, a, [role="button"]元素,匹配['新对话', 'New Chat', '创建新对话']标签并点击;若全部失败,则通过page.goto(DOUBAO_NEW_CHAT_URL)https://www.doubao.com/chat/new-thread/create-by-msg)导航到新建会话路由。new.js 会把实际执行方式(点击了哪个按钮,还是回退导航)写入Action列返回。

3. send:发送消息

send只负责把消息送入输入框并提交,不等待回复。从 send.js 看,它调用sendDoubaoMessage后返回StatusSubmittedBy(通过按钮点击还是回车提交)与InjectedText三个字段。

sendDoubaoMessage是发送链路的核心,其完整流程(utils.js)为:

  1. 确保处于聊天页ensureDoubaoChatPage先检查当前 URL 是否包含doubao.com/chat,否则按评分(对话详情页 > 首页 > 活跃标签页)优先复用已存在的豆包标签页,最后才goto到聊天首页;
  2. 定位输入框buildDoubaoComposerLocatorScript维护了一组从强到弱的 CSS 选择器(textarea[data-testid="chat_input_input"][data-testid="chat_input"] textarea.chat-input[contenteditable="true"]等),并逐一过滤掉不可见元素;
  3. 优先原生键入:若浏览器桥提供page.nativeType,优先用原生输入模拟真实键盘事件,随后同步触发beforeinput/input/change事件让 React 状态感知输入;
  4. 回退到脚本填充:若原生输入后文本与预期不一致,改用fillComposerScript,通过HTMLTextAreaElement.prototype的 value setter 注入文本,或在 contenteditable 元素上用document.execCommand('insertText')填充;
  5. 提交消息:先尝试clickSendButtonScript智能点击发送按钮,失败则按 Enter 键。按钮识别采用评分制:优先匹配文案/aria-label/title 中含send|发送|提交|发消息的按钮,排除"新对话、视频生成、深入研究、图像生成、上传、麦克风"等干扰按钮,并结合按钮与输入框的几何距离、CSS 类名(如bg-dbx-text-highlight)加权打分,得分低于 200 视为未找到可靠按钮;
  6. 验证码检测:提交后运行detectDoubaoVerificationScript,若检测到 captcha iframe、验证码输入框,或对话框文案匹配人机验证|完成安全验证|异常访问|滑动验证|拖动滑块等模式,则抛出CommandExecutionError,提示用户手动完成验证。

4. read:读取当前对话

read读取当前页面可见的对话轮次(turns),输出Role(User / Assistant)与Text。其底层getTurnsScript(utils.js)实现了一套完整的角色识别逻辑:

  • 通过[data-testid="send_message"][class*="bg-g-send-msg-bubble"]等标记识别用户消息;
  • 通过[data-testid="receive_message"][class*="bg-g-receive-msg-bubble"]等标记识别助手消息;
  • 源码注释表明,2026 年 5 月豆包 DOM 重构后,助手消息不再带receive-message标记,改为通过[class*="inner-item-"]/[class*="top-item-"]外层容器配合.flow-markdown-body/.md-box-root内容容器、且不含发送气泡标记来推断 Assistant 角色;
  • 提取文本时对多个选择器依次尝试,去重合并,并附带过滤 48px 以下的小图标;消息按 DOM 文档顺序排序,最终以Role::Text为键去重。

如果页面中一个可见消息都没有,read.js 会返回No visible Doubao messages were found.

5. ask:一问一答的完整闭环

ask是自动化场景最常用的命令:发送提示词后轮询等待回复。ask.js 声明了两个参数:位置参数text(必填)与--timeout(可选,默认60 秒,必须是正整数)。

其执行流程(ask.js):

  1. 记录发送前已有的可见轮次与转录行;
  2. 调用sendDoubaoMessage发送消息;
  3. 调用waitForDoubaoResponse2 秒为间隔轮询页面,每次轮询都会先做验证码检测,然后找出"发送后新出现的 Assistant 轮次"作为候选回复;若可见轮次尚无内容,则对比发送前后的转录行增量,过滤掉提示词本身、内容由豆包 AI 生成在此处拖放文件window._SSR_DATA{"namedChunks"等 UI 噪音;
  4. 当同一候选内容连续2 次轮询保持不变(即内容稳定不再增长),或达到超时上限时,判定生成完成;
  5. 若超时仍未拿到回复,返回No response within {timeout}s. Doubao may still be generating.,此时可以调大--timeout重试。

由于回复依赖 DOM 轮询而非接口,超长生成任务需要更大的--timeout,这正是原文档 Notes 中特别提醒的一点。

6. history:历史对话列表

history从豆包侧边栏读取历史会话,可选参数--limit(默认 50)。utils.js 的getConversationListScript定位[data-testid="flow_chat_sidebar"]侧边栏,抓取其中所有a[data-testid="chat_list_thread_item"]链接,通过正则\/chat\/(\d{10,})提取会话 ID 与标题,输出Index / Id / Title / Url四列。history.js 在未登录或侧边栏为空时给出明确提示。

7. detail:按 ID 读取指定对话

detail <id>接受数字 ID 或完整 URL,parseDoubaoConversationId 会从输入中提取\d{10,}数字作为会话 ID。随后navigateToConversation跳转到https://www.doubao.com/chat/{id}并等待加载,getConversationDetailScript(utils.js)从[data-testid="message-list"]中提取union_message节点,按是否含send_message/receive_message标记区分角色,同时识别meeting-minutes-card会议卡片。detail.js 会把会议卡片信息以Role: Meeting的形式展示在消息列表之前。

8. meeting-summary:会议总结与章节

meeting-summary <id>用于提取豆包会议会话的总结,可选参数--chapters true一并输出 AI 章节。执行时(meeting-summary.js)先定位并点击[data-testid="meeting-minutes-card"]会议卡片打开右侧面板(canvas_panel_container),再从[data-testid="meeting-summary-todos"]读取总结;若请求章节,则切换到包含"章节"文字的 tab 读取[data-testid="meeting-ai-chapter"]内容。若对话中不存在会议卡片,返回No meeting card found in this conversation.

9. meeting-transcript:会议记录读取与下载

meeting-transcript <id>可选参数--download true。默认模式下(meeting-transcript.js)它会打开会议面板、切换到包含"文字"的 tab,然后对[data-testid="meeting-text-notes"]区域滚动到底并反复快照,最多 10 轮,直到连续 2 轮内容稳定;快照通过 mergeTranscriptSnapshots 做基于行重叠的去重合并(利用"最长重叠后缀 + 新内容追加"算法拼接滚动产生的分段文本)。--download true模式则改为点击下载图标与[data-testid="minutes-download-text-btn"]按钮,触发浏览器文件下载,提示用户去 Downloads 目录取文件。

四、会话模型:持久站点会话与一次性标签页

原文档 Notes 中强调了豆包适配器的会话特性:豆包命令默认使用持久站点会话(persistent site session),因此连续执行doubao ask/doubao read/doubao detail会在同一个豆包页面中继续,上下文得以保留。

若想每次命令使用一次性标签页、互不干扰,可以追加参数:

opencli doubao ask "..." --site-session ephemeral

--site-session ephemeral会让命令在一个临时标签页中执行、结束后关闭,适合需要隔离上下文的批处理场景;默认的persistent模式则适合连续的对话式操作。该行为与源码中每个命令的siteSession: 'persistent'声明一致(见 status.js、ask.js 等)。

五、底层原理与抗变化设计

结合源码,豆包适配器之所以能在前端频繁改版下保持可用,主要依赖以下几层设计:

  • 多级选择器兜底:无论是输入框定位(composer)、消息角色识别还是消息文本提取,都维护了一组从"精确 contenteditable="false">【免费下载链接】OpenCLIMake Any Website into CLI & Use your logged-in browser by AI agent.项目地址: https://gitcode.com/gh_mirrors/ope/OpenCLI

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询