The Skills catalog exposed nine product-marketing recipes as independent capabilities and enabled every marketing package for every Runtime by default. It now keeps five top-level Skills, loads the nine recipes on demand through the product-marketing package, and leaves the three marketing Skills disabled until users enable them. Existing saved Skill settings remain authoritative. Release note: 内置 Skills 已从 14 个顶层入口精简为 5 个;去 AI 味和长文工具默认启用,产品营销类默认停用,已保存的用户设置保持不变。
17 KiB
工具执行环境功能逻辑设计
文档信息
| 项目 | 内容 |
|---|---|
| 状态 | 计划 |
| 版本 | 0.1 |
| 日期 | 2026-09-01 |
| 关联 PRD | 工具执行环境 PRD |
| 关联场景 | 工具执行环境 User Stories |
本文是本功能业务规则、状态转换、决策表和跨场景一致性的权威来源。它不定义组件视觉,也 不规定代码模块如何实现。
1. 逻辑目标
- 同一用户操作在不同本机 Runtime 和 stdio MCP 中得到一致的解释器选择。
- 系统不通过隐式回退掩盖配置错误。
- 工具可执行、配套命令可执行和具体能力依赖可用是三个可区分事实。
- 已运行进程使用稳定环境,不被设置变化中途改写。
- 安装、更新、取消、失败和删除都有唯一、可恢复的结果。
- 本机环境和远程 Host 环境没有隐式传播。
2. 核心不变量
INV-1 单一明确来源
Node.js 和 Python 各自恰好保存一个来源:managed 或 custom。不存在 auto、候选优先级
列表或运行时动态选择。
INV-2 禁止静默回退
当前来源不可用时,该工具明确不可用。即使发现另一套系统解释器,也不会自动切换。
INV-3 配套命令同源
node、npm、npx必须属于同一 Node 来源。python、python3、pip必须属于同一 Python 来源。pip等价于当前 Python 的-m pip,不能解析到其他解释器。
INV-4 三层状态独立
- 解释器状态:Node 或 Python 本身能否执行。
- 工具组合状态:npm/npx 或 pip/venv/SSL 是否完整。
- 能力依赖状态:具体 SKILL/MCP 的入口和第三方依赖是否通过验证。
任一上层成功都不能推导下一层成功。
INV-5 进程环境不可变
每个 Runtime/MCP 进程在启动时取得一份环境快照。设置变化只影响之后启动的进程,不改写 已运行进程的 PATH 或解释器。
INV-6 绝对命令优先
stdio MCP 配置的绝对 command 表达用户对该 MCP 的明确覆盖,原样执行,不经过全局工具 命令替换。
INV-7 本机与远程隔离
本机工具选择、shim、Python 包、SKILL 包和 stdio MCP 配置不上传到远程 Host。
INV-8 不推断能力依赖已就绪
能力没有专属实际诊断时,状态只能是“未验证”,不能根据解释器版本或文件存在推断“已就绪”。
INV-9 受管工具工件来源明确且冻结
每个受管工具外部工件同时声明固定原生地址和 OSS Target。用户选择一个下载源后,任务 启动时冻结该来源;失败不回退。OSS 必须是原生工件的字节级副本。
INV-10 设置导航不改变业务状态
“能力与工具”的三个水平 Tab 只组织界面,不改变 Skill、MCP 或工具环境设置。切换 Tab 不得提交、丢弃或重置当前设置面板会话中的编辑状态;关闭后不持久化外层 Tab。
分阶段交付期间,未实现的“工具执行环境”不进入 Tab 状态集合。第一阶段状态集合只有
skills | mcp,后续实现完成后才扩展为 skills | mcp | tool-environment。
INV-11 内置 Skill 默认值不覆盖用户状态
只有状态存储中没有对应 Skill 记录时才使用产品默认值。通用文档工具
deai-writing、longdoc-docx 默认启用;产品营销类 product-evidence、
product-marketing、product-presentation 默认停用。用户显式保存的启停状态和
Runtime 分配优先,升级不得重置。
九种产品营销文档配方属于 product-marketing 包内工作流,不是独立能力状态维度,
不进入顶层 Skill 目录,也不单独注入 Runtime。
3. 状态维度
3.1 来源选择
managed
custom(executablePath)
这是唯一持久状态。
3.2 托管 Python 安装状态
not-installed
downloading
verifying
installing
testing
ready
update-available
error
error 同时携带“是否仍有旧版可用”。若旧版可用,实际工具状态仍基于旧版诊断。
托管 Node 随 GoodBuddy 存在,不使用下载安装状态,但仍可能因打包损坏进入诊断失败。
3.3 工具诊断状态
unknown
testing
ready
partial
unavailable
ready:解释器和本功能承诺的配套命令全部通过。partial:解释器通过,至少一个配套命令失败。unavailable:解释器本身不能使用。
3.4 能力依赖状态
unknown
checking
ready
missing
incompatible
error
unknown在 UI 中显示“依赖未验证”。missing表示明确缺少包或入口。incompatible表示解释器版本、架构或 ABI 不满足已声明要求。error表示诊断本身没有得出有效结论。
3.5 工具下载源
native
oss
这是独立于 Node/Python 环境来源的持久设置。全新用户默认 native。
4. 来源解析决策表
| 保存来源 | 当前事实 | 解析结果 | 是否回退 |
|---|---|---|---|
| 托管 Node | 完整诊断通过 | 使用 Electron Node 与锁定 npm/npx | 否 |
| 托管 Node | Node 通过,npm/npx 失败 | Node 部分可用,显示失败项 | 否 |
| 托管 Node | Node 失败 | Node 不可用,提示修复/重装 GoodBuddy | 否 |
| 托管 Python | 未安装 | Python 不可用,提供安装 | 否 |
| 托管 Python | 已安装且诊断通过 | 使用托管 Python | 否 |
| 托管 Python | 更新失败但旧版健康 | 继续使用旧版并显示更新失败 | 否 |
| 托管 Python | 安装损坏 | Python 不可用,提供重新安装/删除 | 否 |
| 自定义 | 路径及诊断通过 | 使用该绝对路径 | 否 |
| 自定义 | 路径失效 | 保持选择并显示路径不可用 | 否 |
| 自定义 | 解释器通过、配套命令失败 | 部分可用并显示失败项 | 否 |
| 任意 | 发现其他有效解释器 | 只作为候选展示 | 不自动使用 |
5. 命令解析决策表
| 调用形式 | 结果 |
|---|---|
node ... |
当前 Node |
npm ... |
当前 Node 配套 npm |
npx ... |
当前 Node 配套 npx |
python ... |
当前 Python |
python3 ... |
当前 Python |
pip ... |
当前 Python -m pip |
#!/usr/bin/env node |
从进程工具 PATH 解析当前 Node |
#!/usr/bin/env python3 |
从进程工具 PATH 解析当前 Python |
| stdio MCP 绝对 command | 原样执行 |
未托管裸命令,例如 uvx |
按原筛选 PATH 处理;找不到则明确失败 |
| HTTP/SSE MCP | 不参与本机命令解析 |
绝对 command 的子进程若自行调用裸 node 或 python,仍会看到该 MCP 进程启动时的工具
PATH。这不改变绝对 command 本身。
6. 首次使用和迁移
6.1 全新安装
| 工具 | 默认选择 | 首次状态 |
|---|---|---|
| Node.js | GoodBuddy 托管 | 立即真实诊断 |
| Python | GoodBuddy 托管 | 未安装,展示安装入口 |
系统候选可以展示,但不会改变默认选择。
6.2 旧版本升级
- 设置中没有工具环境字段时执行一次迁移。
- 分别按旧版本实际 PATH 解析 Node 和 Python 3。
- 有效解释器固化为
custom + 绝对真实路径。 - 无有效解释器时选择
managed。 - 持久化后不再因 PATH 变化迁移。
迁移中 Node 和 Python 独立决策,不要求二者使用同一种来源。
7. 托管 Python 生命周期
7.1 首次安装
not-installed
→ downloading
→ verifying
→ installing
→ testing
→ ready
任一步失败:
→ 删除本次暂存
→ error(没有活动版本)
→ 用户可重试
7.2 取消
| 取消阶段 | 结果 |
|---|---|
| 下载 | 终止下载、删除暂存、回到安装前状态 |
| 校验 | 终止校验、删除暂存、回到安装前状态 |
| 解压/安装 | 完成本次有界清理、回到安装前状态 |
| 测试 | 停止诊断、删除未发布候选、回到安装前状态 |
取消不发布候选版本,不把取消显示为安装失败。
7.3 更新
- 下载和验证候选时,旧版继续服务现有进程。
- 应用候选前,页面说明需要停止依赖托管 Python 的本机 Runtime/MCP。
- 用户确认后通过现有生命周期取消/停止相关进程。
- 无法确认停止时不替换当前版本。
- 候选完整诊断通过后才发布。
- 失败继续使用旧版,并显示更新失败。
首期不让两个托管 Python 版本长期并存。候选暂存只服务本次更新。
7.4 删除
| 条件 | 行为 |
|---|---|
| 没有使用中进程 | 确认后删除托管目录 |
| 有使用中进程 | 说明影响,用户确认后停止相关进程再删除 |
| 进程停止失败 | 不删除,保留当前环境 |
| 当前选择为自定义 | 删除托管包不改变自定义来源 |
| 当前选择为托管 | 删除后保持托管选择,状态变为未安装 |
8. 设置保存与进程生效
8.1 保存时
- 验证待保存来源。
- 自定义路径必须在保存前通过解释器诊断;配套命令可以形成
partial。 - 保存成功后标记本机 Runtime 环境配置已变化。
- 不直接修改任何运行中进程。
8.2 后续进程
- 没有活动请求的缓存 Runtime 在下次使用前按现有重建入口重建。
- 有活动请求的 Runtime 完成或被用户停止前保持原环境。
- 已启动 stdio MCP 保持原环境,正常关闭、重连或显式测试后使用新环境。
- 新启动的 Runtime/MCP 立即使用新环境。
每个工具调用的活动记录应归属于实际承载它的进程,不根据最新设置追改历史来源。
8.3 设置导航
| 入口或操作 | 打开的外层 Tab | 数据行为 |
|---|---|---|
| 普通“能力与工具”入口 | Skills | 不修改业务数据 |
| 用户点击 Skills | Skills | 不修改业务数据 |
| 用户点击 MCP | MCP | 不修改业务数据 |
| 未来的定向入口 | 指定 Tab | 不修改业务数据 |
| 同一设置面板会话中切换 Tab | 用户选择的 Tab | 保留三个面板的会话内状态 |
| 关闭后重新打开普通入口 | Skills | 不恢复上次外层 Tab |
MCP 内层页签状态属于 MCP 面板,不与外层 Tab 合并。外层 Tab 的默认值或定向入口不能改写 MCP 的连接、凭据、启用或 Runtime 分配状态。
9. 能力依赖逻辑
9.1 诊断输入
能力可以声明:
- 需要 Node 或 Python。
- 最低/最高解释器版本。
- 可选依赖文件位置。
- 可选的无副作用诊断入口。
首期声明只用于显示、版本比较和显式诊断,不触发自动安装。
9.2 状态推导
| 工具状态 | 能力诊断 | 能力状态 |
|---|---|---|
| unavailable | 不执行 | missing 或 incompatible,附工具原因 |
| partial | 能力不依赖失败配套项且实际诊断成功 | ready |
| partial | 能力依赖失败配套项 | missing |
| ready | 没有能力诊断 | unknown |
| ready | 实际诊断成功 | ready |
| ready | 明确缺包 | missing |
| ready | 版本/ABI 不满足 | incompatible |
| 任意 | 诊断自身异常 | error |
“依赖未验证”不是错误,也不能显示为“已就绪”。
10. Ask、Execute 与 MCP
| 场景 | 解释器是否可见 | 是否允许执行 |
|---|---|---|
| 本机 Execute Runtime | 是 | 按现有 Execute 权限 |
| 本机 Ask Runtime | 可以存在于进程环境 | 仍由 Runtime Ask 边界决定,不能因此获得命令权限 |
| Main 启动的已启用 stdio MCP | 是 | 按当前 MCP 分配和模式规则 |
| HTTP/SSE MCP | 不适用 | 按当前网络 MCP 规则 |
| 远程 Runtime | 否 | 使用远程 Host 自身环境 |
工具环境不创建新的工具,不扩大 Runtime 当前允许的工具集合。
11. 网络受限与离线
11.1 托管 Node
随 GoodBuddy 提供,安装后可离线使用。
11.2 托管 Python
- Windows 原生 Target 固定到官方 NuGet 包;macOS/Linux 原生 Target 固定到 Astral
python-build-standalone。 - OSS Target 是对应原生工件的字节级副本。
- 下载源不可达时保持未安装或旧版可用状态,并显示准确原因。
- 首期不提供 Python 离线包导入,避免引入未经选型的包格式和导入流程。
- 完全离线用户可以选择已经离线安装的自定义 Python。
未来若加入离线导入,必须在 PRD、User Stories、逻辑状态和技术包校验中同时定义,不能只 增加一个文件按钮。
11.3 工具下载源决策
| 保存选择 | 目录事实 | 行为 |
|---|---|---|
| 原生地址 | 原生 Target 完整 | 请求固定上游 URL |
| 原生地址 | 原生 Target 缺失 | 工件不可下载,不请求 OSS |
| OSS 镜像 | OSS Target 完整 | 只请求固定 OSS URL |
| OSS 镜像 | OSS Target 缺失 | 工件不可下载,不请求原生地址 |
| 任意 | 下载后字节数/SHA-256 不符 | 删除暂存并失败 |
| 任意 | 设置在任务期间变化 | 当前任务不变,后续任务使用新选择 |
该选择只覆盖受管工具目录中的外部工件,不影响模型、应用更新、Agent、pip/npm 注册表或 用户 URL。
12. 冲突与一致性检查
| 可能冲突 | 唯一规则 |
|---|---|
| 全局工具选择 vs MCP 绝对 command | 绝对 command 优先 |
| 新设置 vs 运行中进程 | 运行中进程保留启动快照 |
| 新托管版本 vs 健康旧版本 | 候选完整通过后才发布 |
| 系统发现新版本 vs 已保存自定义路径 | 不自动切换 |
| 解释器成功 vs 缺少第三方包 | 工具 ready,能力 missing/unknown |
| Ask 环境包含解释器 vs Ask 只读 | Ask 权限边界优先 |
| 本机设置 vs 远程项目 | 远程隔离优先 |
| 镜像不可达 vs 其他来源可用 | 不在同一次操作中静默切换来源 |
| 工具下载源 vs 模型/更新下载源 | 各自独立,工具执行环境设置不覆盖其他功能 |
| OSS 对象 vs 原生工件 | 必须字节、大小和 SHA-256 相同 |
| 合并设置入口 vs 原有 Skills/MCP 数据 | 只重组导航,不迁移或重写业务数据 |
| 外层 Tab vs MCP 内层 Tab | 保持两个独立 tablist、标识和键盘焦点范围 |
13. 逻辑评估结论
13.1 完整性评估
| 评估维度 | 结论 | 依据 |
|---|---|---|
| 首次使用 | 通过 | 托管 Node 立即诊断,托管 Python 明确未安装 |
| 正常执行 | 通过 | SKILL 与 stdio MCP 共用同一命令解析 |
| 自定义环境 | 通过 | 明确路径、真实诊断、禁止静默回退 |
| 部分失败 | 通过 | 解释器、工具组合、能力依赖三层状态独立 |
| 安装生命周期 | 通过 | 安装、取消、失败、重试有唯一结果 |
| 更新生命周期 | 通过 | 候选通过后发布,失败保留健康旧版 |
| 删除生命周期 | 通过 | 使用中进程先停止,失败不删除 |
| 设置生效 | 通过 | 进程启动快照不可变,新进程使用新设置 |
| 升级兼容 | 通过 | 旧系统解释器一次性固化为自定义路径 |
| Ask/Execute | 通过 | 工具环境不扩大工具集合或权限 |
| 远程边界 | 通过 | 本机配置不进入 Host |
| 受限网络 | 通过 | 来源失败可见,不在同次操作静默切换 |
| 完全离线 | 有明确限制 | Node 可用;Python 首期要求已有自定义环境 |
| 受管工具工件来源 | 通过 | 原生/OSS 独立选择、任务冻结、禁止回退 |
| 设置导航 | 通过 | 单一一级入口、分阶段水平 Tab、业务数据不变 |
13.2 一致性评估
- “两种来源”与自定义候选探测不冲突:候选只是自定义来源的选值,不是第三种来源。
- “禁止回退”与升级迁移不冲突:迁移只发生一次,完成后按普通保存选择处理。
- “进程环境不可变”与 Runtime 重建不冲突:只有空闲或后续启动的进程使用新环境。
- “工具环境就绪”与“能力依赖就绪”不冲突:两者属于独立状态维度。
- “绝对 MCP command 优先”与 PATH 注入不冲突:command 不替换,但其子进程继承启动快照。
- “更新保留旧版”不要求长期多版本管理:旧版只在候选发布前保持当前,候选失败即删除。
13.3 当前未决项
没有未决的产品逻辑分支。以下属于实施前必须解决的技术选型,不改变业务规则:
- 六平台 CPython 独立发行包、固定版本、许可证和摘要。
- SKILL/MCP 运行要求声明的最小 schema 和无副作用诊断入口。
- 各 Runtime 当前缓存进程的精确空闲判定与既有重建入口接线。
若技术选型无法满足当前逻辑,例如目标 Python 工件不包含可用 pip/venv,必须回到 PRD 和 逻辑设计调整承诺,不能在实现中静默降级。
14. 需求追踪
| 逻辑范围 | PRD | User Stories |
|---|---|---|
| 首次使用默认状态 | FR-1、FR-2、FR-6 | US-A0 |
| 明确来源与禁止回退 | FR-3、FR-8 | US-C1、US-C2、US-D3 |
| 托管 Node | FR-1 | US-A1、US-B2 |
| 托管 Python 生命周期 | FR-2、FR-9 | US-A2、US-D2、US-D4、US-D5 |
| 三层状态 | FR-6 | US-A3、US-A4 |
| SKILL 命令解析 | FR-4 | US-A1、US-A3 |
| MCP 命令解析 | FR-5 | US-B1、US-B2、US-B3 |
| 生效时机 | FR-7 | US-C3、US-C4 |
| Ask/Execute | FR-10 | US-D6 |
| 远程隔离 | FR-7、FR-9 | US-D1 |
| 受限网络与离线 | FR-2、FR-11 | US-E1、US-E2、US-E3 |
| 统一设置入口 | FR-12 | US-F1、US-F2 |