问题概述
从 #28 的排查经历暴露的宿主侧可观测性缺口:扩展在回调里抛出的异常不会出现在 Percho 主进程日志里,宿主对扩展崩溃完全无感知。
#28 的现场:用户日志文件 538 行,grep mcp|gitnexus|theme.fg|setStatus 零命中——因为异常发生在扩展自己的代码里:
adapter 调 ui.theme.fg(...) ← 宿主注入的 theme 缺方法,抛 TypeError
↓
adapter 自己的 try/catch 捕获 ← pi-mcp-adapter proxy-modes.ts:795-803
↓
catch 块把异常转成「连接失败」业务结果 ← 所有 MCP 服务器从此 100% 永久 not-connected
宿主(main 进程日志)全程无线索,用户只能逐个读第三方包源码定位。#28 已修复 theme 契约本身,但这类问题以后还会以别的形式出现:任何扩展在任何 ctx.ui.* 回调里抛错(API 契约违约、扩展自身 bug),都只表现为「功能莫名不工作」。
复现步骤
- 安装任意会调用
ctx.ui.setStatus(...) / setWidget(...) 并使用 theme 样式的扩展(如 pi-mcp-adapter + 任意 MCP 服务器)
- 制造一个宿主侧契约违约(例如注入的 uiContext 成员抛错/缺方法)
- 查看主进程日志
%APPDATA%\@percho\desktop\logs\main-*.log:异常零记录
建议方向
- bridge 层防御性日志:
makeUiContext(packages/backend/src/session/ui-context.ts)返回的对象用 Proxy 或逐方法 try/catch 包一层——扩展调用 ctx.ui.* 抛异常时统一 log.error("extension ui call failed", method, err) 后照常重抛(记录但不吞,不改变扩展可见的失败语义)
- 需要评估 Proxy 对 25 个成员的性能影响与语义(也可只在方法入口/出口做轻量 try/catch 模板)
- 可选:
bindExtensions 后扩展 init() 阶段的错误上报路径也值得核实(SDK 是否已有事件可转发)
关联
问题概述
从 #28 的排查经历暴露的宿主侧可观测性缺口:扩展在回调里抛出的异常不会出现在 Percho 主进程日志里,宿主对扩展崩溃完全无感知。
#28 的现场:用户日志文件 538 行,grep
mcp|gitnexus|theme.fg|setStatus零命中——因为异常发生在扩展自己的代码里:宿主(main 进程日志)全程无线索,用户只能逐个读第三方包源码定位。#28 已修复 theme 契约本身,但这类问题以后还会以别的形式出现:任何扩展在任何
ctx.ui.*回调里抛错(API 契约违约、扩展自身 bug),都只表现为「功能莫名不工作」。复现步骤
ctx.ui.setStatus(...)/setWidget(...)并使用 theme 样式的扩展(如pi-mcp-adapter+ 任意 MCP 服务器)%APPDATA%\@percho\desktop\logs\main-*.log:异常零记录建议方向
makeUiContext(packages/backend/src/session/ui-context.ts)返回的对象用 Proxy 或逐方法 try/catch 包一层——扩展调用ctx.ui.*抛异常时统一log.error("extension ui call failed", method, err)后照常重抛(记录但不吞,不改变扩展可见的失败语义)bindExtensions后扩展init()阶段的错误上报路径也值得核实(SDK 是否已有事件可转发)关联
ui.theme是字符串而非 Theme 对象,导致所有 MCP 服务器永久无法连接 #28(已修复 theme 契约本身,本 issue 是其暴露的可观测性缺口)