pi-web-ui 0.80.1 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -0
- package/README.md +257 -76
- package/README.zh-CN.md +236 -51
- package/deploy/nginx-subpath.conf +85 -88
- package/dist/server/mcp-bridge.js +45 -7
- package/dist/server/plugins.js +23 -2
- package/package.json +5 -3
- package/plugins/catalog.json +18 -0
- package/web/dist/assets/{TerminalPanel-DrYGGZSV.js → TerminalPanel-GQZf9XvH.js} +1 -1
- package/web/dist/assets/index-72bjWuR-.css +10 -0
- package/web/dist/assets/index-CiRSpf3e.js +347 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-BFA8Pn_5.js +0 -347
- package/web/dist/assets/index-BduNm7_u.css +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,59 @@
|
|
|
12
12
|
|
|
13
13
|
暂无未发布内容。
|
|
14
14
|
|
|
15
|
+
## [0.81.0] — 2026-09-12
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **宿主动作桥新增 `compose()`:把内容放进输入框草稿(宿主 API v1 → v2)**——`startChat()` 是「新建对话并把一段话直接发出去」(脚本化,`prompt` 立刻发),但「元素拾取」这类场景需要的是**人在环中**:内容先落进输入框,用户补一句「这三处间距不一致」再自己发。现在 `window.__piWebUiHost.compose({ text?, attachments? })` 干这件事,与 `startChat` 的差别是**不要求连接就绪**(草稿是本地状态,断线也能先攒着)且输入框没挂载时明确拒收(返回 false,不静默丢)。合并语义复用「撤回消息放回输入框」的同一个纯函数(空则填入、非空追加、**绝不覆盖用户正在打的内容**);附件按 path+mode+行区间去重,与手动 attach 的口径一致。定义见 `web/src/plugin-host.ts` + `web/src/composer-bridge.ts`(草稿在 ChatInput、附件在 App,两处各自注册自己那一半)。
|
|
20
|
+
- **浏览器扩展「网页元素拾取」(`plugins/page-picker`)**:在开发中的网页上点选元素,整理成 AI 能直接动手的上下文,一键注入 pi-web-ui 输入框(`Alt+Shift+P` / 扩展图标 → hover 高亮 → 点击拾取,`Shift`+点击多选,`Esc` 退出,`Ctrl+Enter` 直接发送)。采集的不是截图而是**能让 AI 一次改对**的东西:React fiber 里的组件源码位置(`Card.tsx:18:5` + 调用链)、Vue SFC 文件、命中的 CSS 规则**源文件与行号**(Vite dev 的 `<style data-vite-dev-id>` 的 textContent 与源文件逐字对应,行号可精确反推)、计算样式里**只保留与默认值/继承值不同的项**(现场造同 tag 空元素当探针比对,一个真实卡片通常只剩 3~5 行而不是 300 个属性)、短且唯一的定位串(`#card` > `section.card` > 兜底全 `:nth-of-type`,兄弟冲突会在父级内补 `:nth-of-type` 收窄)、HTML 骨架、可选元素截图(走对话附件,不是把 base64 塞进正文)。详细度三档(精简/标准/完整)在**采集层**就生效。失败一律有兜底:没开 pi-web-ui 页面 / 版本过旧 / 输入框未就绪 / 截屏失败,都会把 Markdown 复制到剪贴板并说明原因,**绝不出现「点了添加什么都没发生」**。
|
|
21
|
+
- 装法:下载 [`page-picker-extension.zip`](https://github.com/xing-shuyin/pi-web-ui/releases/latest/download/page-picker-extension.zip)(打 tag 由 `.github/workflows/extension-release.yml` 自动出包,含 CRC 自校验;zip 打包器是自写的零依赖实现,Windows 上也能出同样的包)→ 解压 → `chrome://extensions` 开发者模式「加载已解压的扩展程序」。也可以从源码 `npm run build:extension` 后加载 `plugins/page-picker/extension/`。远程/局域网部署只需在选项页多点一下「授权该地址」。
|
|
22
|
+
- **`pi-web-ui` 命令行/插件市场不适用于浏览器扩展**:那条通道装的是**服务端插件**(`<dataDir>/plugins/<id>/`),装不了浏览器扩展 —— 这一点在根 README 与插件 README 里都写明了,免得有人对着 `pi-web-ui install` 找半天。
|
|
23
|
+
|
|
24
|
+
- **legado-web 插件:阅读页章末导航(读到底就能翻章)**——阅读页原来只有顶部工具栏有「上一章 / 下一章」,正文读到页面底部什么也没有,这一章看完想接着读必须滚回顶部。现在正文末尾多一条「← 上一章 / 目录 / 下一章 →」(跟在正文下面,带《书名》· 第 n/总 章),换章后自动回到页面顶部;第一章「上一章」、最后一章「下一章」置灰并写明「已是最后一章」(顶栏同名按钮同规则,不再点了没反应),章末「目录」展开目录并回到顶部。回归:`tests/unit/legado-chapnav.test.ts`(禁用态与文案边界:首章/中间章/末章/单章/空目录)+ `tests/legado-web-reader-test.mjs`(真浏览器 + 3 章假书源,钉住导航条长在正文末尾、换章回顶、末章置灰、目录展开)。
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **输入框里自动折行的长草稿,按 `↑` 会误触历史回溯、打断正在进行的编辑**(issue #127)——历史回溯的边界判定原先只看**逻辑行**(value 里有没有 `\n`),可输入框是按宽度自动折行的:一段没有换行符的长草稿在界面上明明是多行,却被当成「只有一行」,光标停在第三行按 `↑` 也直接切到上一条历史(`↓` 能切回来、草稿没丢,但编辑被打断,想改上一行只能动鼠标)。现在改按**视觉行**判定:新增 `web/src/caret-visual-line.ts`,把与折行相关的样式(字体 / 行高 / 字距 / `white-space` / `overflow-wrap`)拷到一个隐藏镜像 div 上,塞入「光标前的文本 + 一个零宽标记」,量标记的 `offsetTop` —— 与 textarea 自身的折行规则一致(`pre-wrap` + `break-word`),于是「光标上方 / 下方还有没有可见行」直接比像素:首视觉行 ⇔ 标记贴顶,末视觉行 ⇔ 与文末标记同高。拿不到布局的宿主(SSR / jsdom / 未挂载 / `display:none`)回落到旧的逻辑行判定,宁可少一次精确判定也不误判成「可以翻历史」;有选区、输入法组合中一律不碰历史。功能本身没退化:光标真的走到首 / 末视觉行后照旧翻历史,`Esc` / `↓` 仍能回到草稿。回归:`tests/unit/caret-visual-line.test.ts`(像素折算 + 无布局回落 + 选区 / 空输入框边界)+ `tests/composer-history-test.mjs`(真浏览器:折成 4 行的无换行草稿要按满 4 次 `↑` 才切历史、前 3 次逐行上移且内容不变、`↓` 切回草稿、换行草稿与单行草稿的老边界行为不变、测量节点不残留草稿正文)。
|
|
29
|
+
|
|
30
|
+
- **MCP 桥把非文本内容块静默丢掉:截图 / 图像生成 / 图表类工具一律返回空串**——`server/mcp-bridge.ts` 的 `McpClient.call()` 以前只拼 `type === "text"` 的块,`image` 与 `resource` 块被直接丢弃,模型既不报错也拿不到任何东西,工具形同虚设(同一 `browser_screenshot` 调用:桥内得到 `""`,桥外直连 stdio 是 22840 字符的 `image/png`)。现在按块类型保序映射:`image` 原样透传成 SDK 的 `ImageContent`(`{type,data,mimeType}`,进会话后由 SDK 的 `normalizeToolResultImages` 统一缩放,超大图不会再让 provider 整段报错);**文本型 `resource`(`resource.text`)当文本透传**——MCP 的 `EmbeddedResource` 分 TextResourceContents 与 BlobResourceContents 两种,前者是真实正文(filesystem 类 MCP 的 read_text_file 就走这条),退化成「已跳过」等于把文件内容吞掉;PDF 这类 blob 与 audio 退化为「mimeType + 约 N 字节,无法内联」的提示(SDK 内容联合只有 text/image/thinking/toolCall,没有 blob 载体);纯文本结果仍返回拼接字符串(老形状不变,不破坏既有调用方)。回归:`tests/unit/mcp-bridge.test.ts`(image 逐字保真 / 文本资源不丢正文 / blob 退化提示 / 混合保序)+ `tests/mcp-bridge-test.mjs`(e2e 握手 8 tools)。限定:Web UI 的工具卡按既有行为只渲染文本(工具结果里的图片在序列化时是 `[image result]`),图片会进**模型上下文**但不在 tool 卡里显示。
|
|
31
|
+
|
|
32
|
+
- **命令行 `pi-web-ui install <插件> --force` 之后插件一直「不存在」**:CLI 装插件是先整目录删掉再拷新的(`install --force` 的 rm→cp 窗口),撞上这个窗口期的一次插件扫描会把插件当成「已卸载」反激活;而反激活时没把插件从 `attempted` 集合里摘掉,目录回来后永远不会再激活——插件的 HTTP 路由(如 legado-web 的 `/plugins-api/legado-web/proxy`)与 AI 工具在本进程内彻底消失,前端只报「代理请求失败 404 <url>」,CLI 承诺的「服务运行中刷新浏览器即可加载」失效,必须重启服务才恢复。现在反激活会摘掉 `attempted` 并推进 epoch(重新 `import` 拿到磁盘上的新代码、浏览器也重拉插件 client bundle),刷新浏览器即自愈。回归:`tests/unit/plugin-manager.test.ts`(目录消失→回来必须重新激活且用新代码)+ `tests/plugin-test.mjs`(真实 HTTP 路由的 rm→cp 窗口自愈)。
|
|
33
|
+
|
|
34
|
+
<!-- auto-i18n:start -->
|
|
35
|
+
|
|
36
|
+
### i18n
|
|
37
|
+
|
|
38
|
+
- 本版无文案增量(相对 v0.80.2,已核查)。
|
|
39
|
+
|
|
40
|
+
<!-- auto-i18n:end -->
|
|
41
|
+
|
|
42
|
+
## [0.80.2] — 2026-09-12
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- **新官方插件 legado-web(📖 阅读)**:把 [Legado / 阅读](https://github.com/gedoor/legado) 的读书链路搬进 pi-web-ui——搜索 / 发现 / 详情 / 目录 / 正文,书源 JSON 与安卓版兼容,另带书源导入、废源检测与清理。插件自带内嵌前端需要的一切后端:跨域 + GBK 代理、本地存储(书源 / 书架 / 阅读进度只落数据目录 `<dataDir>/legado-web/`,不写浏览器 localStorage)、静态托管。安装 `pi-web-ui install xing-shuyin/pi-web-ui/plugins/legado-web`(插件市场里也可一键装),刷新后顶栏多一个 📖 tab。
|
|
47
|
+
- **顺带给 AI 配了修源接口**:四个 agent 工具 `legado_rules`(规则速查)/ `legado_book_sources`(读书源文件、只改坏掉的那几个字段)/ `legado_source_probe`(逐步跑链路,回报每步请求、HTTP 状态、用到的规则与失败明细)/ `legado_run_rule`(拿真实页体试一条规则再落盘);阅读页与书源页的「🤖 AI 修复源 / AI 新建书源」按钮把现场直接发给 AI 并开一个新对话(工作目录限定在插件数据目录)。规则引擎跑在 worker 里,同步 JS 规则(`java.ajax` 等)走 SharedArrayBuffer 桥。
|
|
48
|
+
- **插件 → 宿主动作桥 `window.__piWebUiHost`**:插件 client bundle 是裸 ESM,import 不到应用模块,之前只能往宿主发数据;现在也能让主应用**做事**——`setView("chat" | "terminal" | "git" | "plugin:<id>")` 切主视图,`startChat({ prompt, newChat?, cwd? })` 新建对话(可选切工作目录)并把 prompt 作为用户消息发出去。时序上 `startChat` 会串行等「cwd 切过去 → 对话换成新空白」才发 prompt(服务端 `new_chat` 是异步的,紧接着发会落到旧对话),每步都有超时,超时也发、不静默丢。定义见 `web/src/plugin-host.ts`。
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- **升级 SDK `@earendil-works/pi-coding-agent` 0.84.4 → 0.85.1**(上游带来 `@earendil-works/chord`、Anthropic SDK 0.123.0、esbuild 0.28 等);本仓库代码无需跟着改。
|
|
53
|
+
- **README 中英双版按当前实况重写**:功能清单补全(快捷键、Docker、队列撤回、消息构成、项目与会话、搜索与导航、文件树、终端与 Git、模型与设置、Agent 工具与内联标记、声音与通知、PWA、调优用环境变量等章节),中英两边同步并修掉失效锚点。
|
|
54
|
+
- 插件运行期数据 `plugins/*/storage/` 加入 `.gitignore`;legado-web 的上游前端源码与构建产物加入 `.prettierignore`(保持上游风格,不被格式化重排)。
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- nginx 子路径示例配置删掉 `favicon-streaming.svg` 的那条 `location`:该图标早已不存在,留着只会让人以为得额外补一个文件。
|
|
59
|
+
|
|
60
|
+
<!-- auto-i18n:start -->
|
|
61
|
+
|
|
62
|
+
### i18n
|
|
63
|
+
|
|
64
|
+
- 本版无文案增量(相对 v0.80.1,已核查)。
|
|
65
|
+
|
|
66
|
+
<!-- auto-i18n:end -->
|
|
67
|
+
|
|
15
68
|
## [0.80.1] — 2026-09-12
|
|
16
69
|
|
|
17
70
|
### Added
|
|
@@ -23,9 +76,12 @@
|
|
|
23
76
|
- **终端接管 bash 修复:没有尾部管道的命令不再报 `Cannot read properties of null (reading 'segment')`(issue #121)**:`date`、`ls | head -5` 这类命令没有「尾部限输出管道」,`detectTrailingLimiter()` 返回 `null`,而 #91 v2 的取值重构把原本的可选链写成了非空断言 `limiter!.segment` —— 结果几乎每条一次性 bash 命令都在取值处直接 TypeError(只有以 `| tail` / `| less` / `| more` / `| cat` 结尾的命令能跑)。现已改回可选链(这几个值只在真的拆掉管道时才被取用)。回归:`tests/unit/terminal-bash-limiter.test.ts`(桩终端钉住取值路径,CI 必跑);`tests/terminal-bash-test.mjs` 同步恢复可跑(动态导入走 `pathToFileURL`,Windows 上也跑得起来;提示文案断言钉死中文;一次性终端退出改为轮询而非固定等待)。
|
|
24
77
|
|
|
25
78
|
<!-- auto-i18n:start -->
|
|
79
|
+
|
|
26
80
|
### i18n
|
|
27
81
|
|
|
28
82
|
- 前端新增 key(3):`restartService`、`restartingService`、`restartServiceTip`
|
|
83
|
+
- 服务端新增 key(2):`terminals.headtail.omitted.below`、`terminals.headtail.omitted.above`
|
|
84
|
+
|
|
29
85
|
<!-- auto-i18n:end -->
|
|
30
86
|
|
|
31
87
|
## [0.80.0] — 2026-09-12
|
|
@@ -54,9 +110,11 @@
|
|
|
54
110
|
- `db-client` 插件跟随亮色主题:同上,文件树/主区/表头/弹窗输入框底色引用的 `--bg-elev0/1` 改走 `--bg/--bg-elev`(该插件无自绘深色组件,一次变量映射即完整跟随)。
|
|
55
111
|
|
|
56
112
|
<!-- auto-i18n:start -->
|
|
113
|
+
|
|
57
114
|
### i18n
|
|
58
115
|
|
|
59
116
|
- 前端新增 key(1):`queueRecallTip`
|
|
117
|
+
|
|
60
118
|
<!-- auto-i18n:end -->
|
|
61
119
|
|
|
62
120
|
## [0.78.0] — 2026-09-11
|
|
@@ -79,9 +137,11 @@
|
|
|
79
137
|
- `docs/architecture-attachments.md` 的文件预览协议补一节「HTML 渲染走目录映射的 HTTP」(沙箱策略与相对引用语义)。
|
|
80
138
|
|
|
81
139
|
<!-- auto-i18n:start -->
|
|
140
|
+
|
|
82
141
|
### i18n
|
|
83
142
|
|
|
84
143
|
- 前端新增 key(8):`showHtmlSource`、`showHtmlPreview`、`htmlJsOff`、`htmlJsOffTip`、`htmlJsOn`、`htmlJsOnTip`、`htmlEnableJs`、`htmlDisableJs`
|
|
144
|
+
|
|
85
145
|
<!-- auto-i18n:end -->
|
|
86
146
|
|
|
87
147
|
## [0.77.0] — 2026-09-11
|
|
@@ -109,10 +169,12 @@
|
|
|
109
169
|
- 问卷(`ask_user_question`)不再被工具挂死看门狗剁掉:以前它跟普通工具一样被算作「一个工具跑了 20 分钟」(`PI_WEB_TOOL_TIMEOUT_MS`),到点就 abort 整轮对话并弹「工具执行超过…已自动终止」——把还在思考的用户连对话一起终止。现在按工具名豁免:问卷等的是人类回答,不是挂死的工具,收场只走用户回答/取消与会话 dispose,**不限时**。同理,问卷挂着也不再算「失联」(stall 告警默认 180s 无 SDK 事件,对该对话跳过)。同时补上「刷新/重连后问卷对话框不再消失」:`question_pending` 是即时通道,只推给提问那一刻在线的连接,刷新页面/新标签页都拿不到那条历史消息,而服务端还在阻塞等人回答;现在待答问卷同时挂在快照(`UiState.pendingQuestion`,标准引擎只带当前对话的那张,切回原对话会重推快照)上,两个引擎(标准 pi / DSH)重连后都会把面板恢复出来,由快照恢复的面板也能被快照收起(另一标签页答完/服务端取消),但即时通道弹出的面板不会被在途旧快照闪掉,已答过的问卷也不会被在途旧快照重新弹出。回归 `tests/question-bridge-test.mjs`(零 token,本地假模型驱动整条链路)+ `tests/unit/pending-question.test.ts`。
|
|
110
170
|
|
|
111
171
|
<!-- auto-i18n:start -->
|
|
172
|
+
|
|
112
173
|
### i18n
|
|
113
174
|
|
|
114
175
|
- 前端新增 key(28):`placeholderStreamingQueued`、`steerTip`、`settingsTools`、`toolsSectionTerminal`、`toolsSectionSubagent`、`toolsSectionOther`、`toolsSubagentDepHint`、`delegateTaskEnabledDesc`、`delegateTaskOffHint`、`todoListEnabledDesc`、`todoListOffHint`、`toolDescSubagentSpawn`、`toolDescSubagentGetResult`、`toolDescSubagentSteer`、`toolDescSubagentList`、`toolDescSubagentStop`、`toolDescSubagentWaitAll`、`toolDescSubagentTemplates`、`skillFullTextLabel`、`skillFullTextDesc`、`skillFullTextShort`、`delegateOpenSubagent`、`delegateSecTask`、`delegateSecExpected`、`delegateSecTools`、`delegateSecMustDo`、`delegateSecMustNotDo`、`delegateSecContext`
|
|
115
176
|
- 服务端新增 key(3):`delegate.validate.agent`、`delegate.validate.short`、`delegate.started`
|
|
177
|
+
|
|
116
178
|
<!-- auto-i18n:end -->
|
|
117
179
|
|
|
118
180
|
## [0.76.0] — 2026-09-11
|
|
@@ -128,11 +190,13 @@
|
|
|
128
190
|
- 修掉「只有第一次弹、之后怎么都不弹」:通知带固定 `tag` 时,Windows 把同 tag 的新通知当成**替掉旧条目**,而且是静默的 —— 没有横幅、没有提示音,只要系统通知中心里还躺着一条 pi-web-ui 通知,后续每一条都会被无声替换(页面上看 `showNotification` 明明成功了)。现在干脆不用 tag(也不依赖 `renotify` —— 实测它在 Windows toast 这层不起作用),每条都是全新 toast;代价是通知中心里会累积几条。
|
|
129
191
|
|
|
130
192
|
<!-- auto-i18n:start -->
|
|
193
|
+
|
|
131
194
|
### i18n
|
|
132
195
|
|
|
133
196
|
- 前端新增 key(9):`notifyTest`、`notifyTestBody`、`notifyTestSent`、`notifyTestFailed`、`notifyTestState`、`notifyTestHeld`、`notifyTestDropped`、`notifyTestGateSuppressed`、`notifyTestGateOpen`
|
|
134
197
|
- 前端中文变更(1):`notifyEnableDesc`
|
|
135
198
|
- 前端英文变更(1):`notifyEnableDesc`
|
|
199
|
+
|
|
136
200
|
<!-- auto-i18n:end -->
|
|
137
201
|
|
|
138
202
|
## [0.75.0] — 2026-09-11
|
|
@@ -161,11 +225,13 @@
|
|
|
161
225
|
- 提示词模板选择器与编辑弹窗改为「头尾固定、中段滚动」:模板多、字段区高时标题与操作按钮不再被滚走。
|
|
162
226
|
|
|
163
227
|
<!-- auto-i18n:start -->
|
|
228
|
+
|
|
164
229
|
### i18n
|
|
165
230
|
|
|
166
231
|
- 前端新增 key(2):`notifyInsecure`、`notifyWindowsHint`
|
|
167
232
|
- 前端中文变更(2):`notifyEnableDesc`、`notifyDenied`
|
|
168
233
|
- 前端英文变更(2):`notifyEnableDesc`、`notifyDenied`
|
|
234
|
+
|
|
169
235
|
<!-- auto-i18n:end -->
|
|
170
236
|
|
|
171
237
|
## [0.74.0] — 2026-09-10
|
|
@@ -208,6 +274,7 @@
|
|
|
208
274
|
- 对话框内边距与粘性头(sticky)偏移微调。
|
|
209
275
|
|
|
210
276
|
<!-- auto-i18n:start -->
|
|
277
|
+
|
|
211
278
|
### i18n
|
|
212
279
|
|
|
213
280
|
- 前端新增 key(13):`dismissFinishedSubagents`、`dismissFinishedSubagentsScoped`、`dismissConversationWithSubagents`、`dismissConversationWithSubagentsMixed`、`dismissStreamingConfirm`、`dismissFinishedOnly`、`dismissForceAll`、`forceDismissTitle`、`forceDismissConversation`、`forceDismissConfirm`、`noFinishedSubagents`、`reloadModelsConfig`、`reloadModelsHint`
|
|
@@ -229,11 +296,13 @@
|
|
|
229
296
|
- 设置「消息显示」改名「对话」(中英 + 8 语言包同步)。
|
|
230
297
|
|
|
231
298
|
<!-- auto-i18n:start -->
|
|
299
|
+
|
|
232
300
|
### i18n
|
|
233
301
|
|
|
234
302
|
- 前端新增 key(4):`modelRetryAttempts`、`modelRetryHint`、`retryNow`、`retryLastTip`
|
|
235
303
|
- 前端中文变更(1):`settingsMessageDisplay`
|
|
236
304
|
- 前端英文变更(1):`settingsMessageDisplay`
|
|
305
|
+
|
|
237
306
|
<!-- auto-i18n:end -->
|
|
238
307
|
|
|
239
308
|
## [0.71.0] — 2026-09-09
|