# OpenAgent WorkBuddy 安装指引(REL) 本指南仅适用于 WorkBuddy。执行任何安装命令前,先确认当前会话实际所在的客户端,不要仅凭用户复制的安装提示词判断平台。如果当前客户端与本指南不一致,不得执行本文命令、注册 OAuth 客户端或修改配置;请先返回 [OpenAgent 安装汇总页](https://oasn-ow.haimawan.com/plugin),找到当前客户端对应的安装链接,改用该指南继续安装。如果无法确认客户端,或汇总页没有对应平台,停止安装并询问用户。 由 WorkBuddy Agent 执行,用户本人完成浏览器授权。第 4 步同次调用下载执行 rel 脚本;macOS 的设置与插件核验先在一次 Bash 完成,再由下一次 Bash 直接调用 rel 已发布的重启脚本。 ## 用户可见输出 实际执行下列步骤。开始只说“正在安装 OpenAgent…”,浏览器已打开且需要用户授权时只说“请在打开的页面中登录 OpenAgent…”。不重复提醒或逐步播报。 最终回复只按“完成报告”输出两行纯文本,无标题、列表、代码块或补充。返回值只供衔接验证;不复述协议版本、路径、权限、工具清单、scope、Token 有效期或刷新说明。宿主展示的工具调用和日志不受本文回复约束。 ## 准备 ```bash curl --version python3 --version ``` 需要 Python 3.9+ 和已运行过的 WorkBuddy。顺序执行,失败停止报告。前三步返回注册信息、PKCE 和授权码,第 4 步内部处理 Token;回复不复述授权码、VERIFIER 或 Token。 ## 1. 注册 OAuth 客户端(register) ```bash curl -s -X POST "https://oasn-pre.haimawan.com/owner-oauth/register" \ -H "Content-Type: application/json" \ -d '{ "client_name": "workbuddy", "redirect_uris": ["http://127.0.0.1:52961/callback"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "token_endpoint_auth_method": "none", "scope": "agent.discover agent.invoke artifact.read" }' ``` 响应必须包含非空 `client_id`,否则停止。将它填入授权步骤的 ``。`client_id` 是公开客户端标识,注册响应不含 Secret 或 Token。 ## 2. 生成 PKCE(pkce) ```bash python3 -c " import secrets, hashlib, base64 verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).rstrip(b'=').decode() challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b'=').decode() print(f'VERIFIER={verifier}') print(f'CHALLENGE={challenge}') " ``` 同组 `CHALLENGE` 用于授权,`VERIFIER` 用于换码;不混用新旧参数,回复不粘贴这些值。 ## 3. 浏览器授权(authorize) 填入 `` 和 `` 后执行。命令会打开浏览器,在本机 `52961` 端口接收回调并打印 `CODE`;用户本人登录并同意授权。 ```bash python3 -c " import http.server, socketserver, urllib.parse, webbrowser, secrets state = secrets.token_urlsafe(32) URL = 'https://oasn-pre.haimawan.com/owner-oauth/authorize?response_type=code&client_id=&code_challenge=&code_challenge_method=S256&redirect_uri=http://127.0.0.1:52961/callback&scope=agent.discover+agent.invoke+artifact.read&resource=https://oasn-pre.haimawan.com/mcp/v1/open-agent&state=' + state captured = {} class H(http.server.BaseHTTPRequestHandler): def do_GET(self): q = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) if 'code' in q or 'error' in q: valid = secrets.compare_digest(q.get('state', [''])[0], state) and 'error' not in q captured['code'] = q.get('code', [''])[0] if valid else '' self.send_response(200 if captured['code'] else 400) self.end_headers() self.wfile.write(b'OpenAgent authorized - you can close this tab.' if captured['code'] else b'Authorization failed - you can close this tab.') def log_message(*a): pass with socketserver.TCPServer(('127.0.0.1', 52961), H) as s: s.timeout = 1 webbrowser.open(URL) print('请在浏览器中登录并同意授权……') for _ in range(180): s.handle_request() if 'code' in captured: break if not captured.get('code'): raise SystemExit('授权取消、超时或 state 不符,停止') print('CODE=' + captured['code']) " ``` ## 4. 交换 Token、配置 MCP、验证连接并登记信任(exchange) 填入本次 `CLIENT_ID`、`CODE` 和同组 `VERIFIER`,保持 `mode='exchange'`,执行一次工具调用:curl 下载固定 rel 脚本,Python 内部换 Token、私有保存、合并 MCP、初始化并登记信任。不将 Token 返回给模型,不使用 Edit 或拆分调用;授权参数通过标准输入 JSON 传入,不放入脚本参数。下载或执行失败停止,不换源或回退旧安装器;退出时清理临时脚本。新脚本须先发布到 rel,此入口才能使用。 凭据与 MCP 分别保存到 `~/.workbuddy/openagent-rel-oauth.json`、`~/.workbuddy/mcp.json`,POSIX 权限为 `0600`。安装 Agent 不读取、打印凭据文件或 MCP Authorization。保留其他 MCP、顶层配置、自定义字段、请求头及禁用状态;损坏 JSON、非法类型、符号链接或同名其他来源在换码前停止。私有临时文件原子替换,原文件变化时停止,不覆盖外部修改。 只有输出 `MCP_VERIFIED` 和 `TRUST_VERIFIED` 才能继续安装 Skills。不输出 Token、错误正文或异常详情。正数值 `expires_in` 决定到期时间;省略时内部读取 JWT 的未来数值 `exp`,认证仍由 MCP 服务完成。非法或缺少有效到期信息时停止,不猜测有效期。配置、初始化或信任失败且已输出 `TOKEN_SAVED` 时,改为 `mode='resume'` 执行,使用已保存凭据,不再次换码;换码结果未知或保存失败时停止核对,不重放一次性授权码。原生宿主权限审批保持。 ```bash ( set -eu mode='exchange' exchange_dir="$(mktemp -d "${TMPDIR:-/tmp}/openagent-exchange.XXXXXX")" trap 'rm -f -- "$exchange_dir/exchange.py"; rmdir -- "$exchange_dir"' EXIT curl --fail --location --silent --show-error --proto '=https' --proto-redir '=https' \ 'https://gitee.com/hualia2009/workbuddy-plugin/raw/rel/scripts/openagent-workbuddy-exchange.py' \ -o "$exchange_dir/exchange.py" python3 "$exchange_dir/exchange.py" --mode "$mode" <<'JSON' {"client_id":"","code":"","verifier":""} JSON ) ``` `X-OASN-MCP-Legacy-SSE: enabled` 允许 WorkBuddy 代理降级时使用旧 HTTP+SSE;普通 HTTP POST 仍走现有协议。此标识不替代 Bearer 认证,也不影响 `text-compatible` 输出设置。服务端需先在全部 Access 节点部署兼容能力,再更新 WorkBuddy 配置。 脚本仅验证 `initialize` 的协议版本与能力,支持 JSON/SSE;信任及插件核验通过后按 restart_send 收尾,工具发现与验收由重启后的 WorkBuddy 新任务完成,不统计或展示工具总数。 ## 连接器信任已在第 4 步完成 第 4 步初始化成功后,以内存中已校验的固定来源合并 `~/.workbuddy/mcp-approvals.json`;不另执行 trust 或读取 MCP 正文。登记前后仅用设备、inode、大小、纳秒修改时间检测 MCP 变化,变化停止;不替代内容或认证验证。 信任键为 `SHA-256(URL.origin)::openagent`,固定来源 `https://oasn-pre.haimawan.com`,不含 Token、路径或请求头。保留其他记录、已有正整数时间戳及权限,新建为 `0600`;空白文件按空记录合并,损坏 JSON、非法字段或符号链接停止。原子写入后仅回读信任记录,成功输出 `TRUST_VERIFIED`;失败用 resume,不重复 OAuth。 此记录不替代浏览器 OAuth、宿主文件审批或连接器启用;不要求回复“已信任”。已有 disabled 保持;缓存加载须按文末重启后在新任务验证。 ## Token 过期时刷新(refresh) 如果 OpenAgent 已出现,但请求返回 `Unauthorized`,确认 Token 过期或认证失败后,将第 4 步下载执行命令的 `mode='exchange'` 改为 `mode='refresh'`,执行一次。程序内部读取私有凭据中的 `client_id` 和 `refresh_token`,刷新、保存最新凭据、更新 MCP 并验证连接;不需要模型填入或读取 Token,也不输出凭据。普通业务失败不刷新 Token。 刷新响应已成功保存、配置或验证失败时使用 `'resume'` 恢复,不再次刷新。刷新失败或结果未知时停止,不重复发送刷新请求。如果 Refresh Token 已失效,使用原公开 `client_id` 从第 2 步重新授权,再以 `'exchange'` 完成第 4 步。旧安装没有私有凭据文件时重新授权,不让模型从 MCP 配置读取旧 Token。 成功后同程序已核验信任记录,再按 restart_send 重启 WorkBuddy;工具加载与新任务验收要求不变。 ## 安装 Skills 并开始使用(settings) 五个 Skills 由原生插件获取;先用 `git --version` 确认 Git。macOS 不单独执行本节:restart_send 的 settings 阶段合并 `~/.workbuddy/settings.json` 中的市场和插件启用,同时在当前任务项目的 `.codebuddy/settings.local.json` 中将 `openagent-workbuddy-restart.sh` 追加到 `sandbox.excludedCommands`。优先使用宿主提供的绝对路径 `CODEBUDDY_PROJECT_DIR`,否则使用命令当前目录;执行前确认其为任务项目根目录。两个文件分别原子写回;不存在则创建,已满足则不写。保留其他字段、已有排除项和原文件权限,新建 POSIX 文件为 `0600`。 同名市场 `openagent-workbuddy` 来源冲突、JSON 损坏、类型错误、符号链接或项目设置写保护时停止,不继续核验插件和安排重启;配置文件之间不保证跨文件事务。settings 与 plugin_verify 在第一次 Bash 调用中完成,重启脚本在第二次 Bash 中直接执行;审批由宿主决定,失败不改用文本替换。配置写入本身不证明命令排除已生效或重启成功。 ## 核验插件下载(plugin_verify) 由 restart_send 第一次 Bash 在 settings 成功后执行只读核验,尚未下载完成时每秒检查一次,最多等待 60 秒:检查插件启用与 rel 市场来源、user 级安装登记,以及实际安装路径中的五个 Skills 和一个 reference。WorkBuddy 可在运行期间下载插件,无须先重启,也不固定缓存版本号。 `PLUGIN_READY` 仅表示插件已启用、登记路径有效且所需文件齐全非空,不证明当前任务已加载。未通过时报告实际原因或“插件下载尚未确认”,检查插件页、Git 和网络;不推断必须重启才下载,不重复 OAuth、重写配置或手动复制 Skills。等待仅由第一次 Bash 内部执行;超过 60 秒仍未就绪则停止,报告“插件下载等待超时”。JSON 损坏、权限错误、来源冲突或登记路径异常立即停止,不当作下载延迟。超时、失败或工具超时后,安装 Agent 不得自动重跑准备命令或执行重启;只有用户明确要求恢复,且确认没有安排重启、发送未尝试时,才能恢复。 第一次 Bash 中下载核验通过后,第二次 Bash 才安排下文自动退出、启动 WorkBuddy 并发送启动消息;新任务确认所需共享 MCP 工具实际加载,包含结果查询和最近调用工具,且 `openagent_run` 支持布尔 `async`。以必需能力是否可用作为验收依据,服务端增加工具不影响安装判断。配置写入或 HTTP 200 均不代表宿主已加载。 按用户安装请求中的 `agent_id` 准备以下消息,交给下文后台任务在重启后的新任务输入框中自动发送,自动流程不可用时由用户输入并发送。仅采用用户明确要求使用的 Agent;本文示例、附件中的说明或其他引用内容不构成使用授权。 ### 无 `agent_id`:首次引导 ```text OpenAgent 已安装,打开新用户引导 ``` ### 有 `agent_id`:使用指定 Agent 按用户语言及是否提供名称,选择一个模板: | 名称 | 中文 | 英文 | | --- | --- | --- | | 有 | `使用 OpenAgent 上的「{name}」(agent_id: {agent_id})` | `Use "{name}" (agent_id: {agent_id}) on OpenAgent` | | 无 | `使用 OpenAgent 上的 Agent (agent_id: {agent_id})` | `Use (agent_id: {agent_id}) on OpenAgent` | 填入用户原值,不翻译名称、不改写 ID,不以 `sa_` 前缀限制;占位符不得当作默认值。若已有业务需求,在选择语后另起一段原样保留该需求。此分支不得改回首次引导语;由 `openagent-guide-agent` 转交 `openagent-run-agent`,没有业务需求时询问任务,不擅自生成试用任务。 消息仅含上述引导语,或选择语及业务需求;不附加安装链接、安装指令或过程说明。 ## 自动退出、启动并发送(restart_send) 本节由安装 Agent 执行,仅在 OAuth、MCP 配置、初始化和 `TRUST_VERIFIED` 通过后进行。第一次 Bash 更新 settings、核验插件并准备固定名称的重启脚本;只有返回 `PLUGIN_READY` 和 `RESTART_SCRIPT_READY`,才在第二次 Bash 直接执行脚本。使用上一节选定的完整启动消息;恢复安装时先检查新任务及消息,已完成或结果未知时不重复收尾,不重复 OAuth 或自动试用业务 Agent。 ### macOS:第一次 Bash 准备线上发布脚本 准备与重启使用两次独立 Bash 工具调用,每次均显式设置 `run_in_background=false`、`timeout=120000`(毫秒);后台由重启脚本自行创建,不使用宿主后台模式。第一次调用写入排除项并核验插件,第二次调用才让宿主按新的命令判断执行路径。不要把两段命令合并到一次 Bash。 需要 Python 3.9+ 标准库,无须 pip 包。先用文件工具创建 UTF-8 JSON 文件,内容为 `{"message":"完整启动消息"}`;通过 JSON 序列化保留换行、引号和反斜杠,正文不放入命令参数或日志。第一次 Bash 设置该文件权限为 `0600`,不要额外执行 chmod 工具调用。 将消息占位符替换为该 JSON 的绝对路径,用原生前台 Bash 执行下方准备命令。无论读取本地 INSTALL.md 还是公开链接,都下载固定 rel 已发布的 `openagent-workbuddy-setup.py` 和 `openagent-workbuddy-restart.sh`,不执行工作区脚本。前者依次合并用户和当前项目 settings 并核验插件,通过后才下载后者到当前用户的 `~/.workbuddy/openagent-workbuddy-restart.sh`。下载或语法检查失败时停止,不换源重试。不设置 `run_in_background=true` 或 `dangerouslyDisableSandbox` 绕过授权,也不关闭安全设置重试。源脚本修改需随插件发布后才进入此线上下载入口。 ```bash ( set -eu message_file='<完整启动消息JSON绝对路径>' chmod 600 "$message_file" restart_dir="$(mktemp -d "$HOME/.workbuddy/.openagent-restart.XXXXXX")" trap 'rm -f -- "$restart_dir/setup.py" "$restart_dir/openagent-workbuddy-restart.sh"; rmdir -- "$restart_dir"' EXIT curl --fail --location --silent --show-error --proto '=https' --proto-redir '=https' \ 'https://gitee.com/hualia2009/workbuddy-plugin/raw/rel/scripts/openagent-workbuddy-setup.py' \ -o "$restart_dir/setup.py" python3 "$restart_dir/setup.py" # restart curl --fail --location --silent --show-error --proto '=https' --proto-redir '=https' \ 'https://gitee.com/hualia2009/workbuddy-plugin/raw/rel/scripts/openagent-workbuddy-restart.sh' \ -o "$restart_dir/openagent-workbuddy-restart.sh" sh -n "$restart_dir/openagent-workbuddy-restart.sh" chmod 700 "$restart_dir/openagent-workbuddy-restart.sh" restart_script="$HOME/.workbuddy/openagent-workbuddy-restart.sh" test ! -L "$restart_script" && test ! -d "$restart_script" mv -f "$restart_dir/openagent-workbuddy-restart.sh" "$restart_script" printf 'RESTART_SCRIPT_READY=%s\n' "$restart_script" ) ``` ### macOS:第二次 Bash 直接安排重启 仅在第一次调用成功输出 `PLUGIN_READY` 和 `RESTART_SCRIPT_READY` 后,将下方脚本占位符替换为本次输出的绝对路径,消息占位符替换为同一 JSON 的绝对路径。第二次 Bash 只执行这一条命令,不加 `sh`、复合命令或其他检查;脚本文件名必须保持 `openagent-workbuddy-restart.sh`,并由宿主按当前任务项目的排除配置重新判定。若宿主仍在沙箱内执行或要求原生审批,按实际结果处理,不强行绕过。`--require-existing-trust` 要求新版重启协议;旧发布脚本不识别时停止,不删除参数回退到会再次读取 MCP 的旧流程。 ```bash "" install --require-existing-trust --wait-for-turn --message-file "<完整启动消息JSON绝对路径>" ``` 后台行为与安装 Agent 的收尾要求: 1. 前台仅核验已有固定来源信任记录,不读取 MCP 正文、不改写信任;然后保存私有请求,以 `start_new_session=True` 创建独立 Python 后台、断开标准输入;不创建或注册 LaunchAgent,不使用 nohup 或后台 Shell。创建后台后前台返回,安装 Agent 按“完成报告”回复并结束当前任务,不轮询等待。 2. `--wait-for-turn` 绑定宿主 `CODEBUDDY_SESSION_ID`;没有上下文或只读数据库不可用时停止。后台每秒检查当前任务状态,无等待超时,仅 `completed` 放行;失败、终止、记录缺失或旧实例变化时停止并清理。放行后强制退出 WorkBuddy 相关进程,可能中断其他任务;`completed` 不证明最终回复已保存或渲染。 3. 确认旧实例退出后直接启动应用,设置 `WORKBUDDY_REMOTE_DEBUGGING_PORT=9222`,清除继承的 Electron/Node 脚本运行变量。等待 CDP 及含 `globalThis.wb` 的渲染页,启用 openagent 后进入首页;后台任务在重启后的新任务输入框中自动发送,通过 `wb.conversations.prepareInput()` 填充完整消息,核对唯一首页输入状态后调用一次 `store.api.send()`;不模拟键盘、鼠标或点击,接口失败时停止。捕获本次实际创建的会话 ID 后跳转并确认选中;结果未确认只记录日志,不按历史标题猜测或补发,不打开右侧浏览器。 后台完成或失败均删除本次请求 JSON,保留 `~/.workbuddy/wb-relaunch.py` 和 `~/.workbuddy/logs/wb-relaunch.log`。独立后台不解除宿主沙箱或文件策略;不要同时运行多次收尾。 ### 验收与失败处理 创建后台 PID 仅表示子进程已创建,不能证明重启或发送成功。实际验收须确认旧 PID 退出、新实例启动、新任务中只有一条完整启动消息,以及所需工具已加载。 - 文件策略拒绝(如 `Brokered host mkdir refused by file policy: prompt`)或脚本提示“权限不足”时按原生授权入口处理,不自动切换完全访问或改成前台重试。 - 已发送或结果未知时先检查是否已有消息并确认是否已提交,不再次粘贴、回车或执行 install。已重启时检查新任务及输入框,不要求再次重启。 - 自动流程不可用时,按实际状态恢复应用;确认消息未提交后,由用户完全退出、启动 WorkBuddy,新建任务并发送上一节的同一完整消息。已重启则直接检查新任务。 Windows 自动退出及发送未验证,使用上述手动方式,不执行 macOS Shell。Windows 设置安装按文末 PowerShell 下载方式获取同一固定 rel 的 `openagent-workbuddy-setup.py`,检查下载退出码后执行 `python3 <下载脚本路径>`,并在 `try/finally` 中清理本次脚本及临时目录;不执行 chmod 或重启部分。 ## 新任务排障 若新任务仍没有工具,检查 MCP 设置中的 HTTP `openagent` 是否启用、配置文件名是否为 `~/.workbuddy/mcp.json`(不是 `.mcp.json`),以及 URL 和兼容头是否与第 4 步一致;认证验证使用第 4 步 resume 模式,不让模型读取 Bearer。网络、权限或普通业务失败先处理对应原因,不重复 OAuth,也不为验证安装自动调用业务 Agent。 Windows PowerShell:使用 `curl.exe`,先设置 `$OutputEncoding = [System.Text.UTF8Encoding]::new($false)`。第 4 步将 Bash 外壳改为 PowerShell:在系统临时目录创建唯一子目录,下载同一固定 URL,检查 `$LASTEXITCODE`,再将 JSON 通过单引号 here-string 管道输入 `python3 <下载脚本路径> --mode exchange`(恢复/刷新替换模式);用 `try/finally` 删除本次脚本及临时目录,不执行 Bash 的 mktemp/trap。其余 Python heredoc 段将 `python3 - <<'PY'` 换为 `@'`、末行 `PY` 换为 `'@ | python3 -`;其他 Python 段将首行换为 `@'`、末行换为 `'@ | python3 -`。curl 各段的续行符换成反引号。每步检查退出码,失败停止。 ## 完成报告 仅 OAuth、MCP 合并与初始化、信任回读通过,且 plugin_verify 返回 `PLUGIN_READY` 确认下载并启用后,才报告配置完成;未知或前置失败用未完成模板。工具在重启后新任务核验,不能将配置完成报告成宿主已加载;自动收尾失败区分配置和发送状态。 安装配置完成且 macOS 脚本返回独立 Python 后台创建日志时,最终回复必须且只能输出以下两行纯文本,两行之间不留空行: ```text OpenAgent 安装配置已完成。 已安排当前任务完成后重启 WorkBuddy,并自动发送启动消息。 ``` 这只是已安排报告,不得提前宣称重启、发送或工具加载成功;实际验收见 restart_send。当前会话被重启取消时无需补写回复,也不为补报告再次投递消息。 安装配置已完成但自动流程不可用(含 Windows)且确认没有发送尝试时,使用手动模板: ```text OpenAgent 安装配置已完成。 {自动流程未执行的简短原因};请完全退出并重启 WorkBuddy,新建任务并发送:{启动消息} ``` `{启动消息}` 必须替换为前文选择的首次引导语或指定 Agent 选择语,不得原样输出占位符;名称和 ID 使用用户原值。已有业务需求时,仅在第二行末尾追加“;并附上你原先的业务需求”,不重复业务正文;后台自动发送或用户在新任务中发送的完整消息仍须按前文原样保留业务需求。 已重启时,第二行只提示检查新任务与输入框;发送结果未知时按 restart_send 检查,不要求再次重启或补发。 失败、用户取消、授权超时或其他待处理情况,最终回复也只输出两行,不套用成功文案: ```text OpenAgent 安装尚未完成:{简短原因}。 下一步:{当前可执行的操作}。 ``` 填入实际原因和操作;不输出敏感值、不隐瞒失败,两行后不追加清单、总结或注意事项。