Skip to content

Releases: xing-shuyin/pi-web-ui

v0.82.0

Choose a tag to compare

@github-actions github-actions released this 12 Sep 17:33

Added

  • page-picker 扩展:「发送什么」改成逐项多选(另配 6 个预设)——原来只有三档详细度(精简/标准/完整),要么一起多、要么一起少;实际用起来常是「这次只要源码位置」「这次只要样式,别的别发」。现在设置页可以逐项勾:页面上下文 / 定位信息(选择器+尺寸)/ XPath 与 DOM 路径 / 源码位置(React/Vue 文件:行号 + 组件链)/ 文本 / 命中的 CSS 规则 / 计算样式 / HTML 骨架(元素截图仍是单独一项)。没勾的在采集层就不采,不只是渲染时丢掉——生成 HTML 骨架、读 CSSOM 这些本身就有开销,顺手也把这点省掉。预设覆盖常见组合:精简 / 标准(默认)/ 完整 / 只要能改对地方(选择器+源码)/ 只排查样式(命中 CSS+计算样式)/ 只看文案结构(文本+骨架),一键勾好之后还可以手动增减(预设同时决定采集深浅:文本长度、骨架深度、选择器深度)。老设置(只有 detail)升级后按原档位预勾,行为不变。
    • 回归:sectionsForDepth/normalizeSections/presetForSections 单测、采集层「没勾就不采」单测(jsdom)、渲染层「只输出勾选项」单测、设置页多选 UI 单测(勾选真的落盘 / 预设联动 / 全不勾会提示并回落标准组合)、E2E 用自定义组合真投递一遍。

暂无其他未发布内容。

i18n

  • 本版无文案增量(相对 v0.81.2,已核查)。

v0.81.2

Choose a tag to compare

@github-actions github-actions released this 12 Sep 17:09

Fixed

  • page-picker 扩展:修「pi-web-ui 页面明明开着,却报『没找到打开的 pi-web-ui 页面』」——0.2.0 查找目标标签页时传的过滤条件是 ["<地址>/*", "<地址>"],而裸地址(没有路径的 origin)不是合法 match pattern:真 Chrome/Edge 的 chrome.tabs.query 会直接抛 Invalid url pattern 'http://localhost:8787',那个异常被 catch 成了「没找到页面」,于是拾取结果只能退化成「复制到剪贴板」(选项页「测试连接」里的同名查询也一并修)。现在查询只用 origin 级模式(http://localhost:8787/*),路径前缀仍由 tabMatchesBase 严格复核(子路径反代、前缀相似的站点都不受影响)。
    • 这个 bug 能活着发布,是因为单测/E2E 用的是假 chrome,它不校验 match pattern:现在假 chrome 也按真 Chrome 的规则校验入参(isValidMatchPattern),这类坑会直接挂在单测上。
    • 另加一条装真扩展的 E2E(tests/page-picker-edge-ext-test.mjs):实测 Edge(152,headless)仍接受 --load-extension,所以能在真 chrome.* 上把「拾取 → 投递 → Markdown 真的落进 pi-web-ui 输入框」跑一遍(没装 Edge 自动 SKIP)。
  • page-picker 扩展:修「在 pi-web-ui 页面上点图标没任何反应」——绑定浮条原来完全依赖 background 的 MAIN world 探测(__piWebUiHost / /api/health),那个注入一旦被 CSP/权限/环境挡住,就会静默回落到拾取器,用户看到的就是「新功能没出现」。现在:探测不可用时也照旧注入浮条,浮条自己再认一次页面(同源 /api/health + 标题/输入框 DOM 兵形),认出是 pi-web-ui 就正常问「要不要绑成服务地址」,不是就自己退场并请 worker 补注入拾取器——「点了图标什么都没发生」在三条路上都不可能发生;路由决策同时打进 service worker 控制台,方便排障。

暂无其他未发布内容。

i18n

  • 本版无文案增量(相对 v0.81.1,已核查)。

v0.81.1

Choose a tag to compare

@github-actions github-actions released this 12 Sep 16:31

Added

  • page-picker 扩展:在 pi-web-ui 页面上点一下图标就能绑定服务地址——远程/局域网部署时地址不固定,原来只能去选项页手打地址再点「授权该地址」。现在点扩展图标会先认当前页:页面上有宿主动作桥 __piWebUiHost 即认定,老版本则退一步探一次同源 /api/health{ok, piVersion} 才算数,所以任何「所有路径都回 200」的站点都不会被误认);认出是 pi-web-ui 就在页面底部弹浮条问「要不要把它设为拾取服务地址」,点一下即可(地址/端口/子路径全部按当前页面算,?token=、hash、尾斜杠都会归一掉),已经是当前地址时只说明现状不再多问,浮条上另有「在本页拾取元素」(开发 pi-web-ui 自己时用得上)。缺那一个 origin 的授权时,浮条会提示并给一个「打开设置页授权」按钮 —— chrome.permissions.request 必须在扩展自己的页面里点(网页上的按钮给不了浏览器要的手势),那个页面带 ?bind= 预填地址、一键授权 + 绑定。普通页面点图标的行为一点没变(仍是进入拾取模式),也绝不静默改地址(改前一定在页面上问一次)。回归:detectPiWebUi/bindView 单测 + service worker 分流单测 + ?bind= 面板单测(真 options.html)+ E2E(真 pi-web-ui 页 / 真夹具页各自认定 + 浮条绑定后照常投递)。

i18n

  • 本版无文案增量(相对 v0.81.0,已核查)。

v0.81.0

Choose a tag to compare

@github-actions github-actions released this 12 Sep 15:42

Added

  • 宿主动作桥新增 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,两处各自注册自己那一半)。

  • 浏览器扩展「网页元素拾取」(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 复制到剪贴板并说明原因,绝不出现「点了添加什么都没发生」

    • 装法:下载 page-picker-extension.zip(打 tag 由 .github/workflows/extension-release.yml 自动出包,含 CRC 自校验;zip 打包器是自写的零依赖实现,Windows 上也能出同样的包)→ 解压 → chrome://extensions 开发者模式「加载已解压的扩展程序」。也可以从源码 npm run build:extension 后加载 plugins/page-picker/extension/。远程/局域网部署只需在选项页多点一下「授权该地址」。
  • pi-web-ui 命令行/插件市场不适用于浏览器扩展:那条通道装的是服务端插件<dataDir>/plugins/<id>/),装不了浏览器扩展 —— 这一点在根 README 与插件 README 里都写明了,免得有人对着 pi-web-ui install 找半天。

  • legado-web 插件:阅读页章末导航(读到底就能翻章)——阅读页原来只有顶部工具栏有「上一章 / 下一章」,正文读到页面底部什么也没有,这一章看完想接着读必须滚回顶部。现在正文末尾多一条「← 上一章 / 目录 / 下一章 →」(跟在正文下面,带《书名》· 第 n/总 章),换章后自动回到页面顶部;第一章「上一章」、最后一章「下一章」置灰并写明「已是最后一章」(顶栏同名按钮同规则,不再点了没反应),章末「目录」展开目录并回到顶部。回归:tests/unit/legado-chapnav.test.ts(禁用态与文案边界:首章/中间章/末章/单章/空目录)+ tests/legado-web-reader-test.mjs(真浏览器 + 3 章假书源,钉住导航条长在正文末尾、换章回顶、末章置灰、目录展开)。

Fixed

  • 输入框里自动折行的长草稿,按 会误触历史回溯、打断正在进行的编辑(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 次逐行上移且内容不变、 切回草稿、换行草稿与单行草稿的老边界行为不变、测量节点不残留草稿正文)。

  • MCP 桥把非文本内容块静默丢掉:截图 / 图像生成 / 图表类工具一律返回空串——server/mcp-bridge.tsMcpClient.call() 以前只拼 type === "text" 的块,imageresource 块被直接丢弃,模型既不报错也拿不到任何东西,工具形同虚设(同一 browser_screenshot 调用:桥内得到 "",桥外直连 stdio 是 22840 字符的 image/png)。现在按块类型保序映射:image 原样透传成 SDK 的 ImageContent{type,data,mimeType},进会话后由 SDK 的 normalizeToolResultImages 统一缩放,超大图不会再让 provider 整段报错);文本型 resourceresource.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 卡里显示。

  • 命令行 pi-web-ui install <插件> --force 之后插件一直「不存在」:CLI 装插件是先整目录删掉再拷新的(install --force 的 rm→cp 窗口),撞上这个窗口期的一次插件扫描会把插件当成「已卸载」反激活;而反激活时没把插件从 attempted 集合里摘掉,目录回来后永远不会再激活——插件的 HTTP 路由(如 legado-web 的 /plugins-api/legado-web/proxy)与 AI 工具在本进程内彻底消失,前端只报「代理请求失败 404 」,CLI 承诺的「服务运行中刷新浏览器即可加载」失效,必须重启服务才恢复。现在反激活会摘掉 attempted 并推进 epoch(重新 import 拿到磁盘上的新代码、浏览器也重拉插件 client bundle),刷新浏览器即自愈。回归:tests/unit/plugin-manager.test.ts(目录消失→回来必须重新激活且用新代码)+ tests/plugin-test.mjs(真实 HTTP 路由的 rm→cp 窗口自愈)。

i18n

  • 本版无文案增量(相对 v0.80.2,已核查)。

v0.80.2

Choose a tag to compare

@github-actions github-actions released this 12 Sep 11:44

Added

  • 新官方插件 legado-web(📖 阅读):把 Legado / 阅读 的读书链路搬进 pi-web-ui——搜索 / 发现 / 详情 / 目录 / 正文,书源 JSON 与安卓版兼容,另带书源导入、废源检测与清理。插件自带内嵌前端需要的一切后端:跨域 + GBK 代理、本地存储(书源 / 书架 / 阅读进度只落数据目录 <dataDir>/legado-web/,不写浏览器 localStorage)、静态托管。安装 pi-web-ui install xing-shuyin/pi-web-ui/plugins/legado-web(插件市场里也可一键装),刷新后顶栏多一个 📖 tab。
    • 顺带给 AI 配了修源接口:四个 agent 工具 legado_rules(规则速查)/ legado_book_sources(读书源文件、只改坏掉的那几个字段)/ legado_source_probe(逐步跑链路,回报每步请求、HTTP 状态、用到的规则与失败明细)/ legado_run_rule(拿真实页体试一条规则再落盘);阅读页与书源页的「🤖 AI 修复源 / AI 新建书源」按钮把现场直接发给 AI 并开一个新对话(工作目录限定在插件数据目录)。规则引擎跑在 worker 里,同步 JS 规则(java.ajax 等)走 SharedArrayBuffer 桥。
  • 插件 → 宿主动作桥 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

Changed

  • 升级 SDK @earendil-works/pi-coding-agent 0.84.4 → 0.85.1(上游带来 @earendil-works/chord、Anthropic SDK 0.123.0、esbuild 0.28 等);本仓库代码无需跟着改。
  • README 中英双版按当前实况重写:功能清单补全(快捷键、Docker、队列撤回、消息构成、项目与会话、搜索与导航、文件树、终端与 Git、模型与设置、Agent 工具与内联标记、声音与通知、PWA、调优用环境变量等章节),中英两边同步并修掉失效锚点。
  • 插件运行期数据 plugins/*/storage/ 加入 .gitignore;legado-web 的上游前端源码与构建产物加入 .prettierignore(保持上游风格,不被格式化重排)。

Fixed

  • nginx 子路径示例配置删掉 favicon-streaming.svg 的那条 location:该图标早已不存在,留着只会让人以为得额外补一个文件。

i18n

  • 本版无文案增量(相对 v0.80.1,已核查)。

v0.80.1

Choose a tag to compare

@github-actions github-actions released this 12 Sep 05:51

Added

  • 更新面板新增「重启服务」:由 pi-web-ui server start|install 起的实例,更新面板底部多一个按钮,点一下服务就重启(等价于 pi-web-ui server restart)——更新完立即生效,不用回终端。服务端 server/launch-origin.ts 判定本实例是不是被平台服务托管(launchd / systemd / Windows watchdog),判定结果随 ready.service 下发,pi-web-ui server status 也会显示启动方式;认不出来(前台 pi-web-uinpm run dev、Docker)就不画按钮、也拒绝 restart_service——那里没有 supervisor,退出就真的停了。已装好的服务不用重装(运行时靠 XPC_SERVICE_NAME / INVOCATION_ID / %APPDATA%\pi-web-ui\<name>.pid 对比 process.ppid 识别),新装的另外烘焙 PI_WEB_LAUNCHED_BY=service / PI_WEB_SERVICE_NAME。回归:tests/restart-service-test.mjs

Fixed

  • 终端接管 bash 修复:没有尾部管道的命令不再报 Cannot read properties of null (reading 'segment')(issue #121datels | 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 上也跑得起来;提示文案断言钉死中文;一次性终端退出改为轮询而非固定等待)。

i18n

  • 前端新增 key(3):restartServicerestartingServicerestartServiceTip
  • 服务端新增 key(2):terminals.headtail.omitted.belowterminals.headtail.omitted.above

v0.79.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 15:51

Added

  • 聊天消息支持渲染 LaTeX 公式(issue #116):$...$ 行内、$$...$$ 独立行块走 KaTeX 渲染(remark-math + rehype-katex,字体随包离线可用);代码围栏/行内 code 不受影响,公式写坏了只显示红色源码不打断整条消息。
  • 排队/插队气泡新增「撤回」按钮 ↩(#118):点一下把该条消息从队列取回、文字落回输入框(输入框非空时追加到末尾,绝不覆盖正在打的字),改完直接重发;连续撤回多条按序追加。队列里只存文本,撤回只回文字(附件不恢复)。
  • 新增 paper(暖纸)/ mist(雾蓝灰)/ sakura(樱粉)三套浅色主题:主题切换器与 make-light-theme.mjs 生成器同步增强,终端配色跟随主题;vscode-editor / db-client 插件同步跟随亮色(见下 Fixed)。

Fixed

  • vscode-editor 插件跟随亮色主题:之前文件树/标签栏/弹窗底色引用了主应用不存在的 --bg-elev0/1 变量,亮色下永远回退到深色硬编码值;编辑器(CodeMirror oneDark)与底部 SSH 终端配色也是写死的深色。现在底色改走 --bg/--bg-elev,编辑器亮色用跟随 --bg/--text/--accent 的浅色壳(暗色仍是 oneDark,Compartment 热切换),终端读 --term-* 调色板;主应用切换主题时(pi-web-ui:theme-change)已打开的编辑器与存活终端一起换肤,无需重载。
  • db-client 插件跟随亮色主题:同上,文件树/主区/表头/弹窗输入框底色引用的 --bg-elev0/1 改走 --bg/--bg-elev(该插件无自绘深色组件,一次变量映射即完整跟随)。

i18n

  • 前端新增 key(1):queueRecallTip

v0.78.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 13:29

Added

  • 文件预览支持渲染 HTML(README.html 这类文件不再只看到源码):打开 .html / .htm / .xhtml 默认是渲染视图,工具栏的 👁/</> 与 Markdown 一样一键切源码,进编辑态自动落到源码。渲染走沙箱 iframe,页面里的 JavaScript 默认不执行(工具条显示「🛡 脚本已禁用(静态预览)」),要跑脚本得对当前这个文件点「启用脚本」显式放开(切文件即复位、不持久化、不写进任何配置);无论开关如何,iframe 一律不带 allow-same-origin —— 页面拿不到本应用的同源/DOM/cookie/存储,表单提交与顶层跳转同样被挡(脚本开时工具条换成「⚠ 脚本已启用」并说明后果)。渲染地址是新增的目录映射路由,页面里的相对引用<link href="../web/src/styles.css">./app.js、图片…)按浏览器正常语义解析加载:
    • /api/preview/<工作区相对路径>(机器浏览的绝对路径用 __abs__/ 前缀),各路径段 URI 编码;.html 文档下发 Content-Security-Policy: sandbox?allowJs=1sandbox allow-scripts永不allow-same-origin)与 X-Content-Type-Options: nosniff,其余子资源按真实 content-type 直送;.. 越界由 workspacePath() 拒绝(400 path outside workspace)。
    • /api/file 直出的 HTML 也带上 sandbox CSP——把预览地址单独在新标签页打开,一样拿不到应用源。

Fixed

  • 重试与提示词模板「直发」补记模型使用次数:这两个入口都是「沿用当前模型再发一轮」,之前不计入 model-usage,模型下拉的「按使用次数排序」会漏掉这部分(现在与正常发送一致;模板直发记的是当前模型)。
  • vscode-editor 插件中止上传时临时文件可能残留(Windows):abortUploadEntry 旧写法是 void fh.close() 后立刻 unlink 并把错误吞掉,而 close 是异步的 —— 句柄还没关就删会 EBUSY/EPERM,目标目录里就留下 .vsc-upload-*.part。现在改成 await close()await unlink(),且 upload_abort 等清理完再回响应(客户端随后就会去核验目录);定时清扫与 deactivate 两条路径改为不等(void)。

Changed

  • 排队/插队消息改成和正式用户消息同一套气泡MessageList.tsxQueuedMessage 复用 .msg-user 结构):Markdown 渲染(代码块/列表/链接等不再是一坨纯文本)、角色行显示「你」、状态 tag(插队/排队)与移除 ✕ 排在同一行;未发送仍用虚线边框 + 0.75 透明度区分,服务端真正下发后直接变成正常消息气泡(外观不再跳变)。styles.css 里旧的 .queued-bubble / .queued-text / .queued-remove 一套样式一并删除。
  • 官方插件做手机竖屏(≤640px)适配,桌面端表现不变:db-client(连接侧栏变左滑抽屉、库表树变可折叠面板、结果表格在容器内横滑、Redis 键列表改上下排、触摸目标加大、输入框提到 16px 防 iOS 聚焦缩放)、vscode-editor(文件树变抽屉 + 顶栏 ☰、选中文件自动收起)、run-trace(三段改上下堆叠、时间轴压到 200px、回放条允许换行、触屏色块热区加大)、webmaildemo-mailbox
  • docs/architecture-attachments.md 的文件预览协议补一节「HTML 渲染走目录映射的 HTTP」(沙箱策略与相对引用语义)。

i18n

  • 前端新增 key(8):showHtmlSourceshowHtmlPreviewhtmlJsOffhtmlJsOffTiphtmlJsOnhtmlJsOnTiphtmlEnableJshtmlDisableJs

v0.77.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 12:08

Added

  • 结构化派单工具 delegate_task:六段式派单(agent + TASK / EXPECTED OUTCOME / REQUIRED TOOLS / MUST DO / MUST NOT DO / CONTEXT,有最小长度)+ 服务端校验——模板不可用、缺段、太短直接报错打回,模型补全后重试。执行体复用子代理 spawn 通道(真会话、白名单、模型优先级、左栏徽标、等待/改向/停止)。前端派单卡片:卡头 ◈ agent 芯片 + 「查看子代理」一键跳转,六段式正文(脏参数不抛错)。
  • 7 个 specialist 子代理模板(移植自 oh-my-pi 内置 agents,改写为真子代理提示词):oracle(只读架构/难 bug 顾问)、librarian(外部文档调研)、explore(代码库侦察)、metis(计划前澄清)、momus(计划评审)、multimodal-looker(PDF/图片/图表解读)、sisyphus-junior(单点执行)。subagent_spawn(template=) 直接选用;老用户已有模板文件时一次性自动补齐(sidecar 记录已播种名单,此后删除不再复活)。
  • skill 全文注入(设置 → 技能页,按技能单独勾选“全文”):勾选的技能 {{skills}} 展开为正文(oh-my-pi 式 ### Skill: / 引用描述 / 全文格式;单文件 8KB、总量 32KB 封顶,超限回落名录),不勾选的仍为名录由模型按需读取。改动下一轮即生效,随预设保存/应用。
  • Agent 工具统一开关:设置新增「工具」tab,18 个工具(持久终端 7+子代理 7+edit_soft/delegate_task/ask_user_question/markers_list)逐个开关,标记管理(总开关+分组+查询工具)也并入该 tab(原标记页移除),后端收成 tool-manager.ts 单一出入口(setAgentToolEnabled/applyAgentToolsGating),改动 live 生效无需 reload,随预设保存/应用;旧的终端/编辑/问卷开关自动迁移,旧客户端照常用。

Fixed

  • 排队气泡的 ✕ 只删一条(#113):removeFirstOccurrence(list, text)server/queue-utils.ts,纯函数可单测)只移除第一处匹配,removeQueued 的两条队列(插队 / 排队)都改用它。旧实现重建队列时用值过滤(filter((t) => t !== text)),同一条文本被排队两次时点一次 ✕ 会把两条一起删掉,而气泡只消失一条(要等下一次 queue_update 才对齐);现在与气泡 UI、本地显示镜像、DSH 引擎的「删第一条」语义一致。回归 tests/unit/queue-utils.test.ts(6 例)。
  • 手机端聊天内容贴边(列内缩被算成 0):两个原因都堵上了。① --chat-pad 回调到 14px(= 改前 .msg 自带的 14px 内边距)——中央列收敛成一条 token 时手机上取了 10px,消息文字/卡片比原来贴边 4px,输入框也跟着从 10px 调到 14px,两边仍齐平。② --msgs-gutter 不再只信首帧前的探针:.messages 挂载后改用真实元素实测并覆盖,窗口尺寸变化(含手机横竖屏)时再校一次——个别浏览器/设备上探针与真实滚动容器的 gutter 对不上,会把消息列多缩/少缩一条 gutter。另外 .messages 的左右内缩改成 max(0px, calc(--chat-inset - --msgs-gutter))、上下留白改用 padding-block 独立声明:相减出负值时旧写法会让整条 padding 声明失效(连上下留白一起丢,内容直接贴边),现在最坏只是不扣那一条 gutter。回归 tests/chat-column-align-test.mjs 增加「消息列不贴边」断言(内缩不得小于列留白)。
  • 输入框底部工具条在窄屏下重叠:428px 左右「思考」chip 会压到右侧的 发送/停止(流式时右侧最宽)。两处修正:① 工具条里的 chip(含外层 .dropdown 锚点)补上 min-width: 0 / flex-shrink: 1,模型名与思考等级先收缩、再省略号截断,不再溢出到右侧按钮上(桌面窗口窄到主列放不下时同样有用);② 纯图标阈值从 420px 提到 560px:窄屏直接隐藏 模型名/思考等级/下拉箭头,chip 放大到 34×30,只留图标(文字交给 title 悬浮)。回归 tests/composer-overlap-test.mjs(320–1200px 扫描,注入流式时的「排队|插队」对半胶囊,断言左侧不压右侧、胶囊 78px 且两半等宽、≤560px chip 只剩图标)。

Changed

  • 新增全局运行态 web/src/app-globals.ts(模块级 store + useSyncExternalStoreuseAppGlobals() / useIsDsh() / useIsManaged()):enginemanagedtabsappVersionserverVersion 这些「整棵树都要知道、整个连接内只变一次」的信息不再从 App 逐层传 props —— GoalBar / SettingsModal / PiSetupModal / TopBar / FooterBar / ChatInput 改读全局(DSH 的四处 gating、受管实例的更新/插件入口都不再依赖“谁记得传这个 prop”)。写入点只有一处:use-chat.ts 收到 ready 时(同步于 dispatch 之前,不会闪一帧 pi)。顺带修正 DSH 下「插队」名不副实:DSH 无 mid-run steering(prompt 一律 followUp),运行中只渲染「排队」半段(收成 38px 圆),placeholder 也换成 placeholderStreamingQueued(回车与点排队都是本轮结束后才发)。回归 tests/unit/app-globals.test.ts
  • WebSocket 发送器也收进全局:appSendweb/src/app-globals.ts 下半部分,use-chatsetAppSend 装配)—— 19 个组件的 send prop 全部删除,App.tsx 少 19 处逐层传参(对话框/弹窗/面板/插件视图/终端/SCM/底栏全部自己取),ClientMessage 依赖也随之从这些文件消失;测试(dsh-question-dialog.test.ts)改用 setAppSend 注入并记录发出的消息,组件仍可测。两个例外是故意的:LeftPanel / RightPanel 的 prop 改名为 panelSend(它们拿的是 App 的包装函数,带「顺手关手机抽屉」的副作用,不能换成全局发送器);装配写在 render 期间而非 effect —— 子组件 effect 先于父组件跑,放 effect 里装配会让「挂载即发请求」的弹窗在 appSend 还是空的时候静默丢包。
  • 全局运行态再扩三项:ready / status / cwdLeftPanel(三个都收)、RightPanel(cwd)、ChatInput(ready)、GlobalSearchModal(cwd)不再要这些 prop,改从 useAppField(key) 单字段订阅 —— cwd 是低频字段,单字段订阅让「切项目」的通知只到真正读 cwd 的组件,不会连带重渲染只读 engine 的组件。写入点:use-chat.ts 里一个 effect 把 reducer 的真值镜像过去(单一来源,最多晚一帧;默认值只会是「未就绪 / 未连接 / 空目录」,看不出来)。本来就吃整个 ChatState 的 App / TopBar / FooterBar 仍直读 chat.*(自己就持有数据,不必绕一圈)。
  • 运行中发送位改成「排队|插队」对半胶囊:空闲态那颗发送圆钮在流式中原地变形为 78×38 的蓝胶囊,两半各 38px、中间一条 1px 半透明白线——左半「排队」(列表图标,加入队列,整轮跑完才发)、右半「插队」(↑,回车语义,本回合立刻响应,与 Enter 同一条路径)。原文字版「排队」药丸及其 ≤560px「收成图标」的兜底一并删除(窄屏右侧最宽从文字药丸降到固定 78px);空输入时整颗胶囊变暗、两半禁用(尺寸位置不动,工具条不跳),有文字或纯附件时解锁。停止语义与它们相反,仍是右侧独立的蓝圆,不并入胶囊。tests/supplement-test.mjs 同步改为点左半,并断言「空输入两半禁用 → 输入后解锁」。文案变更:前端新增 key steerTip
  • 设置面板减负:常驻列表里的静态解释全部收进标题/开关旁的「?」悬浮提示(含 7 个「已关闭」后果说明、重试次数、子代理默认模型、全文注入说明等);行内只保留计数、空状态、报错与动态状态(如当前转写模型)。文案 key 无增减。
  • 问卷(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

i18n

  • 前端新增 key(28):placeholderStreamingQueuedsteerTipsettingsToolstoolsSectionTerminaltoolsSectionSubagenttoolsSectionOthertoolsSubagentDepHintdelegateTaskEnabledDescdelegateTaskOffHinttodoListEnabledDesctodoListOffHinttoolDescSubagentSpawntoolDescSubagentGetResulttoolDescSubagentSteertoolDescSubagentListtoolDescSubagentStoptoolDescSubagentWaitAlltoolDescSubagentTemplatesskillFullTextLabelskillFullTextDescskillFullTextShortdelegateOpenSubagentdelegateSecTaskdelegateSecExpecteddelegateSecToolsdelegateSecMustDodelegateSecMustNotDodelegateSecContext
  • 服务端新增 key(3):delegate.validate.agentdelegate.validate.shortdelegate.started

v0.76.0

Choose a tag to compare

@github-actions github-actions released this 10 Sep 16:57

Added

  • 桌面通知的诊断能力(默认不显示在界面上):sendTestNotification() 会立刻发一条系统通知(不受「页面不在眼前」抑制影响,且带 requireInteraction 不会自己滑走),并汇报走的是 service worker 还是页面通知、失败原因、浏览器到底有没有留下这条通知getNotifications(),区分「系统层面被压住」与「浏览器直接丢了」)与判定依据(焦点 / 可见性 / 是否最小化 / 空闲秒数)。界面在 web/src/components/NotifyToggle.tsxSHOW_NOTIFY_TEST_PANEL 常量后面,排障时改成 true

Fixed

  • Windows 上窗口最小化后依然收不到任何桌面通知(v0.75.0 只修了一半):Win11 实测,窗口最小化后 document.hasFocus() 仍是 truevisibilityState 仍是 "visible",连 blur/visibilitychange 都不发 —— 「只看焦点」和「焦点 可见」两种条件都在这个场景下把通知全部静默掉。现在改用只有最小化会变的那组信号判定(原生窗口矩形:screenX/screenY 跳到屏幕外的「最小化坐标」,outerWidth/Height 塌成标题栏;isCollapsedWindow,有单测),并且在 Windows 上额外要求「最近 2 分钟内有过页面交互」才背静默 —— 这个平台的焦点/可见性都不可信,宁可多提醒一次也不漏。非 Windows 平台行为不变(其焦点/可见性可信)。
  • 通知发送路径不再因 service worker 抛错而彻底静默:注册存在但还没 active(首次加载 / 刚更新后)时 showNotification 会失败,现在会退回页面通知,两者都失败也会把原因带出来(诊断按钮里看得到)。
  • 修掉「只有第一次弹、之后怎么都不弹」:通知带固定 tag 时,Windows 把同 tag 的新通知当成替掉旧条目,而且是静默的 —— 没有横幅、没有提示音,只要系统通知中心里还躺着一条 pi-web-ui 通知,后续每一条都会被无声替换(页面上看 showNotification 明明成功了)。现在干脆不用 tag(也不依赖 renotify —— 实测它在 Windows toast 这层不起作用),每条都是全新 toast;代价是通知中心里会累积几条。

i18n

  • 前端新增 key(9):notifyTestnotifyTestBodynotifyTestSentnotifyTestFailednotifyTestStatenotifyTestHeldnotifyTestDroppednotifyTestGateSuppressednotifyTestGateOpen
  • 前端中文变更(1):notifyEnableDesc
  • 前端英文变更(1):notifyEnableDesc