feat: add managed SSH execution spaces
Add managed SSH Hosts and projects with signed side-by-side GoodBuddy Agent and OpenCode Runtime installation, Ask and Execute workspace access, a Main-owned model bridge, detached Agent lifecycle, durable ACP output recovery, and project activation UI. Use protocol v2 with bounded FIFO frames over SSH instead of custom credit, priority, batching, or model-message chunking. Mismatched Host Agents now upgrade automatically, an exactly verified Node runtime is reused on-host, and local Portable builds can embed strictly verified Agent artifacts. Release note: 新增托管 SSH 远程项目,可自动安装或升级签名 Agent/OpenCode Runtime,并在 SSH 断线后继续 Agent 工作和同步未确认输出。
This commit is contained in:
@@ -34,6 +34,7 @@ GoodBuddy 文档按“文档类型 → 功能域”组织。新增文档应先
|
||||
- [全双工实时语音交互设计](./architecture/full-duplex-voice-design.md)
|
||||
- [DeepSeek Harness Runtime 设计](./architecture/deepseek-harness-runtime-design.md)
|
||||
- [应用内反馈系统设计与对接](./architecture/in-app-feedback-integration-design.md)
|
||||
- [SSH 远程主机与 GoodBuddy Agent 稳定终态设计](./architecture/remote-host-and-goodbuddy-agent-design.md)
|
||||
- [跨平台助手产品设计](./design/cross-platform-assistant-product-design.md)
|
||||
- [长期助手路线图](./roadmap/long-term-assistant-roadmap.md)
|
||||
- [电脑控制实施状态](./status/computer-control-implementation-status.md)
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
# SSH 远程主机与 GoodBuddy Agent 实现说明
|
||||
|
||||
## 状态
|
||||
|
||||
本文记录当前代码实现,不定义额外的信任框架。Windows 到 Linux x64 的安装、Main-only 模型桥、断线恢复、输出重放、同一 OpenCode Session 续接、终态清理,以及 metadata-only Portable 对已安装 production 签名 Agent/Runtime 的验证复用已经在真实 Host 上完成 provider-free 验证。远程 OpenCode 功能仍处于发布前验证阶段;production 公钥 registry 已供应,正式发布前仍需提供并校验 Linux x64 与 Linux arm64 的当前签名 Agent/Runtime 工件完整矩阵,并完成一次经明确授权的有界真实模型调用。
|
||||
|
||||
## 产品语义
|
||||
|
||||
远程项目只有两种工作模式:
|
||||
|
||||
- **Ask**:Runtime 在操作系统边界以只读方式访问项目 Workspace。
|
||||
- **Execute**:用户已授权使用所选 SSH 账号的完整权限。Runtime 可以使用该账号可访问的文件、进程、网络和工具,不再要求额外 trust tier、consent checklist、逐工具审批或“受控执行”授权。
|
||||
|
||||
Execute 不获得 root 或 SSH 账号本身没有的权限。模型 API Key 与 Provider 认证仍保留在 Electron Main,不传给远端 Runtime。
|
||||
|
||||
## 组件
|
||||
|
||||
```text
|
||||
Renderer
|
||||
-> 窄 Preload / Main IPC
|
||||
Main
|
||||
-> SSH Host 与 Host Key 管理
|
||||
-> SSH connection pool
|
||||
-> 签名 Agent / Runtime 安装
|
||||
-> 远程项目验证与 SQLite 事务
|
||||
-> Main-owned model bridge
|
||||
SSH attach
|
||||
-> 远端私有 Unix socket
|
||||
Detached GoodBuddy Agent
|
||||
-> Workspace / Git 协议
|
||||
-> OpenCode ACP channel
|
||||
-> 直接拥有的 Runtime 进程
|
||||
```
|
||||
|
||||
不提供把远端路径交给本机 Runtime 的伪本地模式,也不提供 SSH stdio Runtime fallback。
|
||||
|
||||
## SSH Host
|
||||
|
||||
- Renderer 只管理脱敏 Host 快照,不接触密码、密文、SSH Client 或任意命令接口。
|
||||
- Main 在认证前取得 Host Key,展示算法与 SHA-256 指纹,并保存完整 key blob。
|
||||
- 首次连接需要用户确认。Host Key 变化展示旧/新值并要求显式替换。
|
||||
- 密码使用 Electron `safeStorage`;系统 SSH Agent 认证不启用 Agent forwarding。
|
||||
- Host 地址、用户或 Host Key generation 变化时关闭旧连接,并定向退役依赖旧 Host identity 的 Workspace 和 Runtime 会话。保存开始后,所有引用该 Host 的项目保持“需要重新激活”状态;当前项目立即执行完整激活并原子刷新 Host revision 等验证结果,其他项目在下次选择时刷新。激活失败或取消不会恢复发送能力,Composer 和来自 Main 持久队列的用户消息都要等待后续成功激活;排队消息会退回原队列,并在成功后通过既有 queue-ready 流程继续。用户重新选择当前 SSH 项目也会显式触发相同验证,而不是复用旧项目快照。
|
||||
|
||||
## Agent 安装与生命周期
|
||||
|
||||
- Agent bundle 通过 manifest、Ed25519 签名、payload digest、平台和架构校验。
|
||||
- 安装使用当前 SSH 用户目录中的 GoodBuddy-owned 路径和 side-by-side digest 目录。
|
||||
- Agent 代码与固定 Node Runtime 是独立 payload。升级时如果当前 Host Agent 的签名
|
||||
manifest、registry identity、owner/mode/size 和 Node digest 都可验证,且候选
|
||||
manifest 声明完全相同的 Node,安装器直接在新的 side-by-side 目录中复用该 Node;
|
||||
否则正常上传候选 Node。Agent 不匹配不会阻止升级,也不会覆盖旧安装。
|
||||
- 桌面版本携带所需的签名 Agent 与 Runtime。Agent 和 Runtime 各自维护组件版本,签名摘要标识对应版本的精确工件。应用重启固定进入第一个普通本地项目,不自动连接上次远程项目;用户主动切换并首次打开托管 SSH 项目时,Main 才从当前桌面资源选择目标架构工件,Host 尚未安装该 identity 时自动上传并启动。相同 Renderer 对同一项目的并发激活共享一个 Main 操作。
|
||||
- Agent、Workspace 和 Runtime 全部验证成功后,Main 才在同一 SQLite 事务中刷新项目保存的 Agent/Runtime evidence,然后把项目设为当前项目。上传、启动、验证或事务失败时,项目继续绑定旧 identity,不能用未提交的新 identity 绕过持久化绑定校验。
|
||||
- SSH 连接先尝试 attach;Agent 不存在或未运行时执行幂等 bootstrap,然后重新 attach。
|
||||
- Agent 是按需启动的 detached process,不注册开机服务,不依赖 systemd、D-Bus 或 Linger。
|
||||
- Agent 监听当前用户拥有的私有 Unix socket。SSH 中断只关闭 relay,不拥有 Agent 和活动 Runtime 的生命周期。
|
||||
- SSH Host 设置通过固定探针和有界 SFTP 只读显示 Host 已登记的 Agent/OpenCode 版本,并与当前 GoodBuddy 所需版本比较;打开设置不安装或切换远端组件。
|
||||
- 显式 stop、升级、身份冲突或进程退出时清理 GoodBuddy 自己的 socket、状态和子进程;不得删除或覆盖无关 Host 文件。
|
||||
|
||||
## Workspace
|
||||
|
||||
Main 传入已规范化的绝对 POSIX root。Agent 返回 Workspace identity、访问模式、Git 状态和有界能力。
|
||||
|
||||
- 创建项目时,用户可以直接输入远端工作目录,或通过输入框右侧的文件夹按钮浏览并选择目录。
|
||||
- 项目保存前的目录浏览使用 Main 管理的只读、有界 SFTP,只返回目录;每次请求重新解析并校验当前 Host revision 与 Host Key generation,不安装 Agent、不暴露任意 shell/SFTP 接口。
|
||||
- 浏览从 SSH 账号 Home 或当前有效绝对路径开始,限制扫描次数、返回条目和总时限;取消、Host 变化、超时或连接失败时关闭 SFTP 并保留用户原先输入。
|
||||
- 选择目录只更新项目草稿,仍需通过正常的 Agent、Workspace、Runtime 验证和项目保存事务才会持久化。
|
||||
- Ask Workspace handle 不暴露写入方法。
|
||||
- Execute Workspace handle 可读写,但这不是 Execute 的唯一权限面;Execute Runtime 本身使用 SSH 账号的正常权限。
|
||||
- 文件预览、搜索、Git diff、目录项和显式文件传输保持字节、条目数和路径长度上限。
|
||||
|
||||
## Runtime
|
||||
|
||||
首个远程 Runtime 固定为签名 OpenCode ACP bundle。
|
||||
|
||||
### Ask
|
||||
|
||||
Ask 使用系统 `bwrap`:
|
||||
|
||||
- Workspace 和 Runtime bundle 只读 bind;
|
||||
- 独立可写 scratch HOME、TMPDIR 和 XDG 目录;
|
||||
- 固定环境名和固定 Runtime argv;
|
||||
- 通过只读边界阻止 Workspace 修改。
|
||||
|
||||
Host 缺少 `bwrap` 时 Ask 不可用。
|
||||
|
||||
### Execute
|
||||
|
||||
Execute 不经过 Ask 的 bubblewrap profile:
|
||||
|
||||
- 直接启动已签名 Runtime entrypoint;
|
||||
- 使用 Main-only 模型桥时,签名 Agent launcher 会 `exec` 候选 manifest 锁定的
|
||||
Node Runtime;完全相同且已验证的 Node 可在 Agent 版本间复用。进程 owner 校验
|
||||
最终 Node executable,而不是已经被替换的 shell launcher 路径;
|
||||
- `cwd` 为项目 Workspace;
|
||||
- 继承 SSH 账号的正常环境、文件系统、进程和网络能力;
|
||||
- 不进行 T2/T3、confinement attestation、approval bridge 或逐工具批准。
|
||||
|
||||
两种模式都保留请求 deadline、输入/输出字节上限、取消和进程组清理。
|
||||
|
||||
## ACP 与断线
|
||||
|
||||
- 管控面只负责有界 JSON-RPC:连接、查询、启动、取消、关闭和重连。数据面只负责
|
||||
ACP/blob 数据与 Agent 本机 journal。二者共享同一个经过 Host Key 校验和认证的
|
||||
SSH attach 字节流,但不共享生命周期:管控连接关闭不会隐式取消 Agent 已接受的
|
||||
Runtime 动作。
|
||||
- 帧只保留连接 identity、channel identity、单调 sequence、类型和长度。Main 与
|
||||
Agent 都按调用顺序 FIFO 写入,输入队列达到固定字节或条目上限时暂停 SSH stream。
|
||||
顺序、可靠传输、分包和网络背压全部交给 SSH;协议不实现 credit/window、优先级
|
||||
调度、跨 channel 超车、批发送或第二套拥塞控制。
|
||||
- Agent 在把 Main 输入交给 Runtime 前、以及把 Runtime 输出交给 Main 前,先把 ACP frame 写入本机 journal。ACK 只推进 cursor 并裁剪已确认 frame,不表示 channel 已终止。
|
||||
- Main 持久化 binding identity 和单调 cursor;保留中的 connection lease 即使处于 offline/reconnecting,也可以先把新 cursor 落盘。重连提交不能覆盖 resume 过程中并发落盘的更新。
|
||||
- 同一 detached Agent 存活时,短暂 SSH 断线依次执行 `controller/resume`、`runtime/resumeAcpChannel` 和 `runtime/replayAcpChannel`,从 Main 已确认的 cursor 后只重放 Agent 到 Main 的已记录输出。重复 frame 会被确认但不会再次交给上层。
|
||||
- Main 到 Runtime 的 ACP 输入、模型请求、工具请求和 blob 不自动重放。
|
||||
- 无法确认外部 Provider 是否已处理的模型调用保持结果未知,避免重复计费或重复副作用。
|
||||
- 只有远端返回 identity 匹配且 `closed: true` 时,Main 才删除持久化 binding;传输失败或未确认 close 会保留 recovery identity。
|
||||
- 终态 close 由 Agent 在一个事务中为两个方向记录 sequence high-water tombstone,删除剩余 frame 和 active channel,并归零对应 journal quota。tombstone 用于拒绝迟到的旧 epoch frame,因此当前不会按时间自动裁剪。
|
||||
- 断线不主动终止正在运行的 Runtime。用户取消、deadline、显式关闭或 Agent shutdown 才触发停止。
|
||||
- Agent 失联期间继续把 Runtime 输出写入本机 journal;重新连接只校验 controller
|
||||
identity、恢复 binding,并从 Main 最后确认的 cursor 后同步缺失数据。已接受的
|
||||
指令和结果不确定的 Provider 请求都不自动重放。
|
||||
|
||||
## 模型桥
|
||||
|
||||
- Provider URL、API Key 和认证头只存在于 Main。
|
||||
- 远端 OpenCode 通过 GoodBuddy Agent helper 和每次 Prompt 的私有 Unix socket 使用模型桥。
|
||||
- Main 校验固定模型 profile、协议、请求路径和有界传输格式,并记录 Provider
|
||||
返回的实际 usage;不限制 Prompt 内的模型调用轮数、工具调用次数、累计 Token
|
||||
或单次模型输出 Token。取消、Runtime deadline、请求/响应字节上限和结果不确定时
|
||||
禁止自动重放仍然保留。
|
||||
- OpenCode 同一 Prompt 内的标题请求和主请求可以并发到达本机 helper;helper 在
|
||||
单一稳定模型桥上按到达顺序等待并交付,不返回本地 `bridge-busy`,每个响应只有在
|
||||
HTTP 完整 flush 后才发送 delivery ACK。
|
||||
- 一条模型桥消息编码为一个 canonical JSON blob frame;blob frame 最大 2 MiB,
|
||||
Provider 请求与响应 body 仍各自限制为 768 KiB。每条模型消息只调用一次 SSH
|
||||
write,不再二次分片、等待逐帧 credit 或合并多个协议帧。凭据不进入 Renderer、
|
||||
SSH 命令参数或远端环境。
|
||||
|
||||
## 项目保存
|
||||
|
||||
远程项目持久化稳定配置和当前验证结果:
|
||||
|
||||
- Host ID、Host revision 与 Host Key generation;
|
||||
- 远端工作目录和 Workspace identity;
|
||||
- Agent installation identity;
|
||||
- Runtime selection、bundle digest、adapter digest;
|
||||
- `ask | execute`。
|
||||
|
||||
打开托管 SSH 项目会从这些已保存字段重建验证输入,不接受 Renderer 回传的旧项目草稿。这样桌面更新后的第一次打开可以自动安装对应 Agent/Runtime,并原子刷新以上字段,同时保留项目名称、说明、Host、远端工作目录、Runtime selection 和默认工作模式。
|
||||
|
||||
Renderer 在用户主动打开托管 SSH 项目时订阅同一次 Main 保存操作的进度,依次显示
|
||||
Host、Agent、Workspace、Runtime 和 Saving。操作完成、失败或取消后会清除阻塞进度;
|
||||
进行中可显式取消,并禁用会产生冲突的项目切换、创建和设置入口。远端 RPC 拒绝只向
|
||||
Renderer 暴露固定方法名、数字 RPC code 和有界 service code,不转发 Host 私有错误详情。
|
||||
`runtime/preparePrompt` 在远端明确拒绝且尚未接受 Prompt 时会关闭对应 Main binding,
|
||||
不会把确定性失败错误保留为 `outcome-unknown`。
|
||||
|
||||
不持久化 T2/T3、consent、approval bridge 或 confinement 证明。数据库迁移可以保留旧列以安全读取历史数据库,但新 domain object 不再暴露这些字段。
|
||||
|
||||
## 资源与发布
|
||||
|
||||
- 普通 `build` 和 `dist*` 携带
|
||||
`agent-runtime-lock.json`、`remote-runtime-lock.json` 与公开的
|
||||
`agent-release-keys.json`,但不嵌入可安装的 Linux Agent/Runtime bundle。本地
|
||||
`portable` 会自动完整校验并嵌入已存在的 `.agent-resources` Agent 工件,也可通过
|
||||
`GOODBUDDY_PORTABLE_REQUIRE_AGENT_ARCHS` 强制要求指定架构。若包内没有工件而 Host
|
||||
已有与 lock 匹配的当前组件,Main 会验证签名 manifest、安装与
|
||||
registry identity、owner/mode/size 和 Agent 关键 payload,并要求签名 Agent 在
|
||||
lifecycle/Runtime activation 边界完整复验 payload 后才复用;缺失或不匹配时不会
|
||||
降级信任或尝试无 bundle 安装。
|
||||
- `agent:build`、`agent:import`、`agent:verify` 管理 Agent 工件。
|
||||
- 远程 Runtime 使用 `remote-runtime-lock.json` 和一个当前 manifest 格式。
|
||||
- `release:package` 在 Electron Builder 前后校验 Linux x64 与 arm64 的签名 Agent/Runtime 完整矩阵;任一架构缺失或无效时失败。
|
||||
|
||||
## 发布前验证
|
||||
|
||||
1. `npm test`
|
||||
2. `npm run typecheck`
|
||||
3. `npm run lint`
|
||||
4. `npm run build`
|
||||
5. 校验并导入双架构签名资源。
|
||||
6. 在已固定 Host Key 的 Linux x64 测试 Host 上验证 attach-or-bootstrap。
|
||||
7. 在 GoodBuddy 专用测试目录验证 Ask 无法修改文件。
|
||||
8. 验证 Execute 可以写文件、启动进程和访问网络,同时不触碰无关 Host 文件。
|
||||
9. 运行一次有界的真实模型调用,确认凭据只由 Main 使用。
|
||||
10. 中断并恢复 SSH,确认活动 Runtime 不被网络抖动终止。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,10 @@
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 设计中 |
|
||||
| 版本 | 0.4 |
|
||||
| 日期 | 2026-08-22 |
|
||||
| 版本 | 0.5 |
|
||||
| 日期 | 2026-08-21 |
|
||||
| 适用产品 | GoodBuddy 桌面端 |
|
||||
| 相关设计 | [统一界面设计系统](../../../UI-DESIGN.md) |
|
||||
| 相关设计 | [统一界面设计系统](../../../UI-DESIGN.md)、[SSH 远程主机与 GoodBuddy Agent 稳定终态设计](../../architecture/remote-host-and-goodbuddy-agent-design.md) |
|
||||
| 相关能力 | [会话监督](../supervision/conversation-supervision-prd.md)、[自动化平台](../../architecture/automation-platform-architecture.md)、[长期助手路线图](../../roadmap/long-term-assistant-roadmap.md) |
|
||||
|
||||
## 1. 背景
|
||||
@@ -52,7 +52,7 @@ Runtime 统一抽象为“执行空间”。
|
||||
执行空间描述工作区、终端、受管进程和 Agent Runtime 实际运行的位置:
|
||||
|
||||
```ts
|
||||
type ExecutionSpace =
|
||||
type ExecutionSpaceSelection =
|
||||
| {
|
||||
kind: 'local'
|
||||
rootPath?: string
|
||||
@@ -65,7 +65,9 @@ type ExecutionSpace =
|
||||
```
|
||||
|
||||
执行空间可以来自当前项目,也可以由用户在工作栏中临时选择。临时选择不会静默修改项目
|
||||
设置,只有用户显式保存时才成为项目默认值。
|
||||
设置,也不直接授予文件、终端或 Runtime 能力。Main 必须先把选择草稿验证为绑定窗口、
|
||||
controller、Host/Workspace identity、信任 revision、能力和 lease 的 opaque 临时 Grant;
|
||||
后续 IPC 只引用 Grant ID。只有用户显式保存并重新通过 Project 候选验证时才成为项目默认值。
|
||||
|
||||
## 3. 核心产品原则
|
||||
|
||||
@@ -132,7 +134,8 @@ Runtime
|
||||
- 当前 Runtime 不支持后台 Job 时,Runtime 能力仍可发现;打开后说明当前可监督的内容。
|
||||
- 当前执行空间没有 Git 仓库时,工作区文件功能仍可使用,Git 区域显示不可用原因。
|
||||
- 没有活动进程时,进程面板提供创建终端或启动 Runtime 的入口。
|
||||
- 没有项目时,终端和工作区允许用户选择本机目录或远程主机。
|
||||
- 没有项目时,终端和工作区允许用户选择本机目录或远程主机,但必须先取得有界临时
|
||||
Execution Space Grant,不能把可选路径直接传给文件、Git、Process 或 Runtime。
|
||||
- 监督未启用时,监督面板提供目标、模式和“开始监督”,而不是隐藏能力。
|
||||
|
||||
不得渲染成排没有解释的禁用按钮,也不得把“进程连通”描述为已经支持完整原生监督。
|
||||
@@ -175,8 +178,8 @@ Runtime
|
||||
- 不允许 Agent 未经现有 Runtime 边界直接向用户终端注入输入。
|
||||
- 不自动执行 HTML 中的脚本或访问网络。
|
||||
- 不让监督器自动替用户发言、批准工具、扩大范围或修改安全策略。
|
||||
- 不在首期承诺网络断开后远程任务一定可恢复。
|
||||
- 不在首期支持任意 ProxyCommand、任意端口转发或 SSH Agent Forwarding。
|
||||
- 不提供以 SSH 连接为生命周期的临时远程 Agent;远程执行必须由用户级常驻 Daemon 承载。
|
||||
- 不支持任意 ProxyCommand、任意端口转发或 SSH Agent Forwarding。
|
||||
- 不要求所有 Runtime 提供相同的 Subagent、Job、Hook 或会话能力。
|
||||
|
||||
## 6. 信息架构
|
||||
@@ -285,6 +288,8 @@ Conversation,默认 Execute,并持续显示 Runtime、Project、工作目录
|
||||
|
||||
Runtime 能力统一监督直连模型、OpenCode、Continue、DeepSeek Harness 和后续 Runtime。
|
||||
能力在目录中稳定可发现,打开的面板实例依据所选 Runtime 的真实能力显示状态。
|
||||
远程实现先只交付 OpenCode 官方 ACP 闭环;Continue 与 DeepSeek Harness 后续复用同一
|
||||
面板和通道契约。产品不为并行建设多套后端而增加用户可见模式或临时入口。
|
||||
|
||||
共同区域:
|
||||
|
||||
@@ -322,7 +327,7 @@ Runtime 能力统一监督直连模型、OpenCode、Continue、DeepSeek Harness
|
||||
进程面板只展示 GoodBuddy 创建、托管或明确接管的进程:
|
||||
|
||||
- 用户终端 Shell。
|
||||
- Runtime Host、Server、Utility 和远程 Helper。
|
||||
- Runtime Host、Server、Utility 和远程 GoodBuddy Agent。
|
||||
- Runtime 后台 Job。
|
||||
- 用户通过工作栏显式启动的长运行命令。
|
||||
- 浏览器或自动化中属于 GoodBuddy 的受管子进程摘要。
|
||||
@@ -354,7 +359,7 @@ Renderer 不接收任意系统 PID 控制能力。控制动作引用 Main 签发
|
||||
- 显式打开、下载副本或在终端中打开。
|
||||
- HTML 文件的源码与安全预览。
|
||||
|
||||
本机和远程访问都必须由 Main 或远程 Helper 在对应文件系统上执行路径规范化、相对路径和
|
||||
本机和远程访问都必须由 Main 或远程 GoodBuddy Agent 在对应文件系统上执行路径规范化、相对路径和
|
||||
符号链接边界检查。Renderer 只能提交受约束的相对路径和已授权范围 ID。
|
||||
|
||||
### 7.7 浏览器
|
||||
@@ -463,6 +468,11 @@ type WorkbarPanelInstance = {
|
||||
|
||||
## 9. 主机管理与远程执行空间
|
||||
|
||||
本节定义产品入口和用户行为。Host Key、凭据、远程 Agent 协议、模型请求代理、签名更新、
|
||||
断线和 Runtime 适配的技术边界以
|
||||
[SSH 远程主机与 GoodBuddy Agent 稳定终态设计](../../architecture/remote-host-and-goodbuddy-agent-design.md)
|
||||
为准。
|
||||
|
||||
### 9.1 设置入口
|
||||
|
||||
设置中心增加“主机与远程执行”分类,管理:
|
||||
@@ -470,45 +480,97 @@ type WorkbarPanelInstance = {
|
||||
- 主机名称、地址、端口和用户名。
|
||||
- 认证方式和凭据配置状态。
|
||||
- Host Key 算法与 SHA-256 指纹。
|
||||
- 连接测试、远程系统和架构。
|
||||
- Helper、Runtime 和能力状态。
|
||||
- 引导式身份/认证验证、远程系统和架构。
|
||||
- GoodBuddy Agent、Runtime 和能力状态。
|
||||
- 删除、重新验证或更新 Host Key。
|
||||
|
||||
主机配置是全局资源。项目或工作栏只引用主机 ID,不能复制凭据。
|
||||
|
||||
当前实施状态:设置中心已经实现主机 CRUD 和模态验证向导。新增或目标/认证编辑依次完成
|
||||
连接信息、认证前 Host Key 核对、密码/系统 SSH Agent 认证和平台/架构/Shell/Home 有界
|
||||
探针,全部成功后才原子保存主机、加密凭据和完整 Host Key。认证失败可在弹窗内修改凭据
|
||||
重试;取消或失败不保留新主机。Key 变化显示旧/新指纹并要求显式高风险确认。项目创建和
|
||||
设置现可选择托管 SSH、已保存 Host、远端工作目录、OpenCode 和 Ask/Execute,不要求
|
||||
额外 trust tier 或 consent checklist。候选完成签名 Agent/Runtime、Workspace、ACP、模型桥
|
||||
和文本模型 profile 验证后原子提交。私钥导入仍未开放。旧流程已保存但
|
||||
没有成功探针记录的主机继续读取,但在完成新向导前显示为“需要重新验证”。
|
||||
|
||||
应用重启后固定进入项目列表中的第一个普通本地项目,不自动激活上次远程项目。用户主动
|
||||
打开已有托管 SSH 项目时,Main 会用数据库中的项目字段重新执行同一套
|
||||
Host/Agent/Workspace/Runtime 验证。桌面版本携带的 Agent 或 Runtime identity 已变化时,
|
||||
先 side-by-side 安装新候选,全部成功后再原子刷新项目 evidence 并切换当前项目;失败保留
|
||||
此前项目和安装绑定,不由 Renderer 用旧草稿重建更新请求。同一 Renderer 对同一项目的
|
||||
重复激活共享一个操作,不会并行启动第二次保存。
|
||||
主动打开期间,项目切换器在原位置展示 Host、Agent、Workspace、Runtime、Saving
|
||||
五个阶段及原生 `progressbar` 语义;用户可以取消,项目切换、创建和设置入口在操作结束前
|
||||
保持禁用。成功后才提交项目选择,失败或取消继续保留此前项目。
|
||||
|
||||
已保存 Host 的地址、用户或固定 Host Key 变化后,Main 关闭旧连接并定向退役该 Host 的
|
||||
Runtime 缓存。当前项目引用该 Host 时,设置保存成功会立即运行上述完整激活流程并刷新
|
||||
项目验证;其他项目在下次选择时刷新。用户再次选择当前 SSH 项目也会执行完整激活,
|
||||
不能因为项目已经选中而跳过验证。从 Host 保存到项目成功激活之间,项目持续保持需要
|
||||
重新连接状态;失败或取消不会重新开放 Composer。已由 Main 派发的用户排队消息退回原
|
||||
持久队列,不生成失败消息、不丢失附件,并在成功激活后的 queue-ready 通知中继续派发。
|
||||
|
||||
新建托管 SSH 项目时,远端工作目录既可手工输入,也可通过文件夹按钮打开 Main 管理的
|
||||
只读、有界 SFTP 目录选择器。选择器从 SSH 账号 Home 或当前有效绝对路径开始,只返回目录,
|
||||
支持上级、刷新、取消和选择当前目录;Host 变化、连接错误或取消都保留草稿,选择结果不会
|
||||
绕过正常项目验证与保存事务。
|
||||
|
||||
### 9.2 凭据和主机验证
|
||||
|
||||
- 优先支持系统 SSH Agent 或 OpenSSH 证书。
|
||||
- 导入私钥或密码时使用 Electron `safeStorage` 加密。
|
||||
- 凭据绑定主机 ID、地址、端口、用户名和认证类型。
|
||||
- Renderer 只接收 `credentialConfigured`、来源和错误状态。
|
||||
- 首次连接展示 Host Key 算法和 SHA-256 指纹,必须由用户显式接受。
|
||||
- Host Key 检查使用 Main 内五分钟有效、目标绑定的临时候选,检查阶段不接收认证凭据;
|
||||
认证和系统探针成功前不持久化新增主机,取消或失败不留下主机或密码。
|
||||
- 首次连接必须在发送密码、私钥签名或 SSH Agent 签名前取得并展示 Host Key 算法和
|
||||
SHA-256 指纹,由用户显式接受;持久化完整 Host Key 或可信 Host CA,不能只保存展示指纹。
|
||||
- Host Key 变化硬失败,并通过独立高风险流程替换。
|
||||
- 禁止 `StrictHostKeyChecking=no` 和默认 SSH Agent Forwarding。
|
||||
- 命令参数、URL、日志、SQLite 和 IPC 中不得出现私钥或密码。
|
||||
- 命令参数、URL、日志、SQLite 明文和 IPC 响应中不得出现私钥或密码;用户在受信任表单
|
||||
输入的密码只通过严格校验的单用途 IPC 请求交给 Main,Renderer 不得读取已保存密码。
|
||||
|
||||
### 9.3 远程 Helper
|
||||
### 9.3 远程 GoodBuddy Agent
|
||||
|
||||
远程能力通过版本化 GoodBuddy Helper 提供:
|
||||
远程能力通过版本化 GoodBuddy Agent 提供:
|
||||
|
||||
- 使用 SSH exec 或受控通道启动,不依赖字符串拼接 Shell 命令。
|
||||
- 安装到远程用户级受管目录,不要求 root。
|
||||
- 上传内容使用固定版本、大小和 SHA-256 校验,临时写入后原子替换。
|
||||
- 握手报告协议版本、系统、架构和能力。
|
||||
- 安装到远程当前用户的 GoodBuddy-owned 目录,不要求 root。首次连接先 attach,Agent
|
||||
不存在或未运行时幂等 bootstrap 为 detached process,再重新 attach;不注册开机服务,
|
||||
不依赖 systemd、D-Bus 或 `Linger=yes`。
|
||||
- SSH 负责 Host Key、认证、SFTP 安装和固定 `goodbuddy-agent attach` 中继;attach 只连接
|
||||
用户私有 Unix socket。SSH relay 断开不终止 Agent 或活动 Runtime。
|
||||
- 上传内容使用应用内置公钥验证的签名 manifest,并校验组件版本、协议、平台、架构、大小
|
||||
和 SHA-256。Agent 与 Runtime 各自维护版本,签名摘要标识精确工件;使用 side-by-side
|
||||
安装、自检和健康切换,失败时不改变当前项目绑定。
|
||||
- 握手报告 installation、Daemon boot identity、协议、系统、架构、用户监督器和能力。
|
||||
- 在远程执行路径规范化、Git、文件、PTY、进程组和 Runtime 管理。
|
||||
- 对事件、日志、文件、帧、超时、并发和总传输量设置上限。
|
||||
- 断开或租约过期后终止孤儿进程。
|
||||
- 持久化有界 Agent 到 Main 输出;SSH 断开后 Agent 继续运行,同一 Agent 重连时只恢复
|
||||
可确认的输出。Main 到 Runtime 的输入、工具、模型和 blob 请求不自动重放。
|
||||
- 对有副作用的请求使用稳定 operation ID 和 payload digest 去重;结果无法证明时进入
|
||||
`outcome-unknown`,禁止自动重放。
|
||||
- 对事件、日志、journal、文件、帧、超时、并发、缓存和总传输量设置硬上限。
|
||||
- Daemon、Runtime、受管进程和用户终端分别具有明确 lease、取消、drain 和回收语义。
|
||||
- Agent 不可用或身份不匹配时远程执行失败,不退化为 SSH stdio Runtime。
|
||||
|
||||
首期断线后把活动运行标记为 `interrupted`,撤销短期能力并要求用户重试;在事件序列、租约、
|
||||
重放和幂等附加完成前,不宣称可以无损恢复。
|
||||
Host Key、远端用户或目标变化会关闭旧连接,并使绑定旧 Host identity 的 Workspace 和
|
||||
Runtime 会话失效。产品不维护 T1/T2/T3 等附加信任层级。
|
||||
|
||||
### 9.4 远程 Runtime
|
||||
|
||||
- Runtime 在远程执行空间内运行,不能让本机 Runtime 对远程路径进行伪本地操作。
|
||||
- Main 保持可信控制面,远程 Helper 只接受有范围、有期限的请求。
|
||||
- Ask 的只读限制在远程 Helper 和 Runtime 适配层共同强制。
|
||||
- Execute 继续经过 Runtime 工具策略、审批、取消、超时和审计。
|
||||
- 模型凭据优先留在 Main,通过仅绑定远程回环的 SSH 隧道和请求级代理提供。
|
||||
- Main 保持可信控制面,远程 GoodBuddy Agent 只接受有范围、有期限的请求。
|
||||
- GoodBuddy 控制协议负责 Agent、Workspace、Git、Process、Blob 和 Runtime supervision;
|
||||
Runtime Session、stream、tool、permission、usage 和取消优先复用 ACP。
|
||||
- Ask 的只读限制在远程 GoodBuddy Agent 和 Runtime 适配层共同强制。
|
||||
- Execute 是用户对所选 SSH 账号完整权限的授权,直接以该账号可用的文件、进程、网络和
|
||||
工具能力运行,不要求逐工具审批或第二个“受控执行”模式。取消、超时、输出上限和活动
|
||||
记录继续保留。
|
||||
- GoodBuddy 模型凭据和 Provider URL 必须留在 Main。远程 Runtime 只获得不含凭据的模型
|
||||
policy、私有 Unix socket、隔离 loopback endpoint 和 Prompt-bound blob channel;
|
||||
Main 按 durable round、profile digest、调用次数、最坏输出 token 预留和最终 delivery ACK
|
||||
代发,不得把原始 API Key 或认证头发送到远端。
|
||||
- 不向远程 Runtime 暴露通用本机 MCP、浏览器、文件系统或其他未分配能力。
|
||||
|
||||
## 10. Runtime 与进程统一生命周期
|
||||
@@ -521,11 +583,13 @@ type ManagedLifecycleState =
|
||||
| 'running'
|
||||
| 'waiting_approval'
|
||||
| 'paused'
|
||||
| 'reconciling'
|
||||
| 'stopping'
|
||||
| 'completed'
|
||||
| 'failed'
|
||||
| 'cancelled'
|
||||
| 'interrupted'
|
||||
| 'outcome_unknown'
|
||||
```
|
||||
|
||||
每个 Runtime 会话、Task 级执行、终端或受管进程公开:
|
||||
@@ -586,13 +650,16 @@ terminal_sessions
|
||||
managed_processes
|
||||
runtime_sessions
|
||||
runtime_jobs
|
||||
remote_agent_installations
|
||||
remote_operations
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
- 工作栏偏好只保存能力目录顺序、面板实例、停靠布局、尺寸和目标引用。
|
||||
- 主机表只保存非敏感元数据和加密凭据引用。
|
||||
- 活动终端和进程在应用重启时标记为中断,除非对应远程租约可验证恢复。
|
||||
- 应用重启后先通过远程 Daemon 的 journal、lease、boot identity 和 event cursor 核对活动
|
||||
终端、进程与 Runtime;无法确认时标记 `interrupted` 或 `outcome_unknown`。
|
||||
- 日志使用有界环形缓冲或分页持久化,不能无限写入 SQLite。
|
||||
- Artifact 继续作为成果的权威实体,不把完整成果复制进工作栏状态。
|
||||
- 当前 Renderer `localStorage` 活动记录不能作为 Runtime、监督或进程的权威来源。
|
||||
@@ -602,7 +669,7 @@ runtime_jobs
|
||||
Renderer 只通过显式方法访问:
|
||||
|
||||
- 工作栏偏好和目标绑定。
|
||||
- 主机 CRUD、测试和 Host Key 确认。
|
||||
- 主机 CRUD、临时 Host Key 检查、验证并原子保存。
|
||||
- 终端创建、输入、调整大小、关闭和有界输出订阅。
|
||||
- 受管进程列表、日志和允许的控制动作。
|
||||
- Runtime Inspector 快照、事件和允许的控制动作。
|
||||
@@ -653,7 +720,9 @@ Electron、ChildProcess、PTY、SSH Client、Socket 或文件句柄。
|
||||
- HTML、文件、目录、浏览器画面和远程传输沿用或收紧现有大小限制。
|
||||
- Runtime Snapshot 与事件流分离,重新打开时先取权威快照,再接增量事件。
|
||||
- 监督使用独立低优先级并发池和预算,不延迟前台回答。
|
||||
- 应用退出时停止新操作,取消订阅,关闭终端、隧道和 Helper,并在期限内标记未完成对象。
|
||||
- 应用退出时停止新操作并让用户选择取消、等待或 detach;关闭 SSH attach 不卸载或终止
|
||||
用户级 GoodBuddy Agent Daemon。依赖 Main 模型网关、审批或本机工具的 Run 不能被描述为
|
||||
可以无人值守继续。
|
||||
|
||||
## 15. 无障碍与响应式
|
||||
|
||||
@@ -668,6 +737,10 @@ Electron、ChildProcess、PTY、SSH Client、Socket 或文件句柄。
|
||||
|
||||
## 16. 分阶段实施
|
||||
|
||||
本节只表示内部依赖顺序,不表示可以发布临时架构。SSH 远程执行只使用用户级 Daemon,
|
||||
不发布连接期 stdio Agent。OpenCode Ask、OpenCode Execute 和后续 Runtime 分别通过自身的
|
||||
安装、权限、取消和重连门槛后开放,未完成的能力继续显示不可用。
|
||||
|
||||
### 阶段 0:应用级工作栏壳层
|
||||
|
||||
- 将当前聊天专属右栏提升为应用级壳层。
|
||||
@@ -703,15 +776,22 @@ Electron、ChildProcess、PTY、SSH Client、Socket 或文件句柄。
|
||||
|
||||
### 阶段 4:SSH 主机与远程执行空间
|
||||
|
||||
- 主机管理、加密凭据和 Host Key 固定。
|
||||
- Linux x64/arm64 Helper 安装与握手。
|
||||
- [x] 引导式主机管理、先验证后保存、密码安全存储、系统 SSH Agent、Host Key 固定和
|
||||
有界系统探针。
|
||||
- [ ] 私钥与受限 OpenSSH config 导入。
|
||||
- 签名、side-by-side GoodBuddy Agent 安装和按需 detached Daemon。
|
||||
- SSH connection pool、固定 attach relay、Agent 控制协议、Agent 本地 ACP 日志和断线重连同步。
|
||||
- 远程工作区、Git、终端和受管进程。
|
||||
- 远程 Runtime 执行、取消、超时和审计。
|
||||
- 首期断线明确标记中断,不承诺恢复。
|
||||
- 先完成签名 OpenCode bundle、Ask bubblewrap、Execute 直接进程、官方 ACP channel、
|
||||
Main 模型网关、取消、超时和活动记录。
|
||||
- OpenCode 闭环稳定后,Continue 与 DeepSeek Harness 复用相同面板和通道契约逐个接入。
|
||||
- 一次远程项目保存请求完成 Host/Agent/Workspace/Runtime 全量验证和 SQLite 原子提交。
|
||||
- 桌面更新后,用户主动首次打开远程项目时自动安装当前签名 Agent/Runtime,并在成功后原子刷新项目绑定;应用启动本身不连接远程项目。
|
||||
- SSH、Main、Daemon、Runtime 和远端重启后的核对、恢复与 `outcome_unknown`。
|
||||
- 支持平台的安装、Ask、Execute、取消和重连冒烟测试通过后开放对应 OpenCode 能力。
|
||||
|
||||
### 阶段 5:恢复与扩展
|
||||
### 阶段 5:开放后的扩展
|
||||
|
||||
- 远程租约、事件重放和幂等重连。
|
||||
- 更多远程系统和架构。
|
||||
- PDF、Office 和数据成果预览。
|
||||
- Conversation、Task 和实验的完整监督。
|
||||
@@ -747,11 +827,16 @@ Electron、ChildProcess、PTY、SSH Client、Socket 或文件句柄。
|
||||
- [ ] Supervisor 不能自动发送消息、批准工具、切换工作模式或扩大范围。
|
||||
- [ ] SSH 首次连接和 Host Key 变化均经过明确验证流程。
|
||||
- [ ] 凭据不进入 Renderer、日志、SQLite 明文或命令参数。
|
||||
- [ ] Host 地址、用户或 Host Key 变化会关闭旧连接,并使旧 Workspace 和 Runtime 会话失效。
|
||||
|
||||
### 17.4 生命周期与恢复
|
||||
|
||||
- [ ] Runtime、终端、Task 级执行和进程具有权威 Main 快照和有序增量事件。
|
||||
- [ ] 取消、终止、失败、断线和应用退出都有确定终态。
|
||||
- [ ] 远程执行只通过按需 detached Daemon 提供,SSH attach 断开不销毁 Daemon 状态。
|
||||
- [ ] 重连先恢复 event cursor 并查询 operation;有副作用操作不会自动重放,无法确认的
|
||||
结果显示为 `outcome_unknown`。
|
||||
- [ ] Agent side-by-side 更新支持所需签名版本的健康切换,失败时保留旧项目绑定。
|
||||
- [ ] 切换跟随目标后不显示上一对象的过期状态。
|
||||
- [ ] 固定目标的订阅在页面切换后保持,关闭时正确释放。
|
||||
- [ ] 日志、终端、文件、成果和远程传输均有明确上限和背压。
|
||||
|
||||
@@ -19,7 +19,7 @@ GoodBuddy 已将企业微信、钉钉和微信 ClawBot 远程消息通道纳入
|
||||
3. 远程执行任务使用哪个工作目录。
|
||||
4. 执行请求、处理后端、工具调用和结果归属于哪个范围。
|
||||
|
||||
腾讯官方微信 ClawBot 使用扫码授权,不使用 App ID 或 Secret,并由本机独立 Sidecar 持续运行通信服务。文字、图片和文件收发、只读对话与受控执行已经实现;真实微信账号的认证媒体端到端联调仍作为发布前手动验收。
|
||||
腾讯官方微信 ClawBot 使用扫码授权,不使用 App ID 或 Secret,并由本机独立 Sidecar 持续运行通信服务。文字、图片和文件收发、Ask 只读对话与 Execute 完整授权已经实现;真实微信账号的认证媒体端到端联调仍作为发布前手动验收。
|
||||
|
||||
为避免把通道来源、发送者身份和执行范围混在一起,本功能使用“通道项目 + 远程会话”的两级结构:
|
||||
|
||||
@@ -51,7 +51,7 @@ GoodBuddy 已将企业微信、钉钉和微信 ClawBot 远程消息通道纳入
|
||||
- 在项目切换器中一眼识别微信、企业微信和钉钉来源。
|
||||
- 在通道项目中区分不同发送者和群聊。
|
||||
- 在设置卡片中完成连接、启停、处理后端、模式和工作目录配置。
|
||||
- 通过微信进行只读问答或发起受控执行任务。
|
||||
- 通过微信进行 Ask 只读问答或发起 Execute 任务。
|
||||
- 选择可信的执行后端,并查看完整执行记录。
|
||||
- 保留通道关闭前后的历史上下文和审计记录。
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ GoodBuddy 应能够:
|
||||
|
||||
1. 持续组织项目、会话、任务、成果和记忆,而不是只保存聊天记录。
|
||||
2. 在明确授权下理解文件、知识库、截图、应用窗口和浏览器上下文。
|
||||
3. 以只读问答、计划审查和受控执行三种模式完成工作。
|
||||
3. 以 Ask 只读问答和 Execute 完整授权两种模式完成工作;计划审查是 Ask 中的交互方式,不是第三种权限模式。
|
||||
4. 在应用级助手工作栏中持续提供任务中心、监督、Runtime、终端、进程、工作区、浏览器和成果。
|
||||
5. 支持后台任务、定时任务、失败恢复和桌面通知。
|
||||
6. 让所有记忆、权限、上下文和远程传输可见、可审查、可撤销。
|
||||
|
||||
Reference in New Issue
Block a user