| Files | Last commit | Last update |
|---|---|---|
| 2 months ago | ||
chore(build): drop ELECTRON_BUILDER_CACHE so the wine toolchain cache stays in the volume, not the workspace | 2 months ago | |
feat(gui): 插件面板补齐安装/编辑/删除,on_disk 报告页面 桌面版插件面板此前只有启用/禁用,装不了新插件、读不回源码、删不掉坏的 插件——而 WebUI 有完整能力。两边不一致,且缺失的那三个恰好是出问题时唯一 能用的三个操作。 补齐(复用后端已有契约,未新增端点): - POST /api/plugins 安装并保存源码。保存走安装路径是有意的:它会校验 名称、编译并热重载,而 PUT /{name} 只切 enabled 开关,指过去会静默 什么都没存。 - GET /api/plugins/{name} 读源码(读的是磁盘上的源,与写回可往返)。 - DELETE /api/plugins/{name} 删除。内置插件不显示删除按钮。 - 内置插件的"编辑"改为"查看源码"并置只读:它的文件在二进制里,给一个 保存后被丢弃的文本框比直接说明更糟。 - 三个弹窗复用既有的 overlay / overlay-card,不新造一套弹窗体系。 后端补 DiskEntry.Pages:GUI 读的是 on_disk 而非 List,pages 只在 List 里,所以面板里那行"页面:…"永远不显示。新增 pageNames() 复刻加载期的 合并规则(page + pages,去重保序)。判据覆盖 pages 与单页 ui.page 两种 写法,并断言 JSON 里带 pages——GUI 读的是 HTTP body,不是 Go 结构体。 变异去掉赋值后两条判据都失败。 CDP 实测 10 项全部通过:安装带页面的插件、源码往返一致、禁用/启用、 热重载后版本号变化、坏插件在列表可见并带错误信息、非法名拦截、语法错误 被后端拒绝而非静默写入、路径穿越被 IPC 代理拦截。 Co-Authored-By: ModelRouter <noreply@modelrouter.dev> | 1 month ago | |
fix(build): run Windows NSIS packaging inside docker; add artifact size gate The Windows installer has been broken since 1.3.0: electron-builder's NSIS step needs wine to generate the uninstaller, but the host's wine was amd64-only (no i386 runtime -> empty syswow64 -> error c0000135), so electron-builder silently wrote a 264 KB installer shell with no payload. No check caught it and the broken exe shipped. 1.4.0 reproduced the same failure this session. Two fixes: 1. win-builder image gains node + wine32/wine64 (+ i386 arch). dist-win-docker.sh now runs BOTH the core cross-build and npx electron-builder --win nsis inside docker (USE_SYSTEM_WINE=true -> the image's wine). The wine prefix is initialized on first run in the shared cache volume, so syswow64/ntdll.dll exists - the exact thing the host lacked. The host needs no mingw/wine/node. 2. packaging/verify-dist.sh: a size-floor gate for GUI artifacts (exe >= 5 MB, deb/rpm/nsis.7z >= 10 MB). Wired into make gui-dist and make gui-win-docker and the dist-win-docker script, so a degenerate installer fails the build instead of reaching a Release. Verified: it rejects the 264 KB exe and passes the healthy artifacts. | 2 months ago | |
| 2 months ago | ||
fix(gui): 桌面版真正加载渠道插件 + 外链一律交给默认浏览器 ## ① 桌面版此前**完全没有插件系统**(渠道页根本不存在) GUI 内嵌内核的 config.yaml 由 main.js 生成,唯独漏了 plugin_dir —— 而内核刻意不给它默认值(运维显式开启)。后果:桌面版 plugin_dir: "", /api/plugins 返回空列表,channels 插件(多平台账号登录、凭据保管、自动 领取)在桌面端**完全不可见**。实测复现:同一份配置去掉 plugin_dir 就是 plugins: [],加上就有 billing/channels/quota/usage 四个。 修法: - 新 profile 直接写 plugin_dir: <profile>/plugins; - **老 profile 回填**(用户已有 config.yaml,不写就只有老用户永远没有插件)—— 新增 ensurePluginDirConfigured(),只在缺少该键时追加,其余内容不动; - 插件树由内核 SeedBundled 播种(按文件补齐,用户改过的副本优先保留)。 ## ② 升级后渠道修复**下发不到桌面用户** 内核播种规则是「文件缺失才写」,所以桌面用户升级 GUI 后 channels.lua 仍是旧版 —— 我们发的渠道修复对桌面用户静默失效。桌面版必须自己处理: 按 app 版本打戳(.plugin-seed-version),版本变化时删掉 4 个内置插件文件 让新内核重新播种,旧副本留 .prev-<旧版本> 可人工恢复;用户自建插件不碰。 逻辑抽到 cmd/gui/plugin-sync.js(无 Electron 依赖),配 6 条 node 单测。 ## ③ 登录一律拉起默认浏览器(三条路径都覆盖) 桌面版的内容区是加载内核 WebUI 的 iframe,渠道登录链接是 target=_blank。 此前只处理了 setWindowOpenHandler,另两条路径仍会把 Electron 窗口带到 第三方页面。现在三条路径统一外抛: 1. window.open / target=_blank → setWindowOpenHandler 2. 顶层同标签跳转 → will-navigate 3. iframe 内导航 → will-frame-navigate **loopback 例外必须保留**:channels 的服务端浏览器(noVNC)就在 127.0.0.1:<port> 的 iframe 里,拦掉它会让 VNC 登录失效。 实测(打包后的 GUI + Xvfb + CDP 驱动真实窗口): [gui] open in default browser: https://example.com/mr-windowopen-probe [gui] open in default browser: https://example.com/mr-navigate-probe [gui] open in default browser: https://example.com/mr-frame-probe [gui] open in default browser: https://xiaohuanxiong.com/login?code=…(真实商汤登录链接) 顶层 URL 保持在内核页面(跳转被拦下),loopback iframe 正常加载。 ## ④ 顺手 - GUI 版本号 1.9.7 → 2.0.42(与内核同版本发版;package-lock 里还是 1.9.3, 一并同步); - make gui-test 跑桌面壳单测。 验证:打包后的 GUI 启动即 /api/plugins 列出 channels(ui.page=channels), 插件目录播种 4 个内置插件;外链四类实测均走默认浏览器。 (cherry picked from commit 411503aea5eb3b78360c1929a45cf97daa2ce833) | 18 days ago | |
chore(gui): 版本号 2.0.46(与内核同版本) (cherry picked from commit 02c01582f14cefaab6fefa8d9c959c9c42e07be0) | 18 days ago | |
chore(gui): 版本号 2.0.46(与内核同版本) (cherry picked from commit 02c01582f14cefaab6fefa8d9c959c9c42e07be0) | 18 days ago | |
fix(gui): 桌面版真正加载渠道插件 + 外链一律交给默认浏览器 ## ① 桌面版此前**完全没有插件系统**(渠道页根本不存在) GUI 内嵌内核的 config.yaml 由 main.js 生成,唯独漏了 plugin_dir —— 而内核刻意不给它默认值(运维显式开启)。后果:桌面版 plugin_dir: "", /api/plugins 返回空列表,channels 插件(多平台账号登录、凭据保管、自动 领取)在桌面端**完全不可见**。实测复现:同一份配置去掉 plugin_dir 就是 plugins: [],加上就有 billing/channels/quota/usage 四个。 修法: - 新 profile 直接写 plugin_dir: <profile>/plugins; - **老 profile 回填**(用户已有 config.yaml,不写就只有老用户永远没有插件)—— 新增 ensurePluginDirConfigured(),只在缺少该键时追加,其余内容不动; - 插件树由内核 SeedBundled 播种(按文件补齐,用户改过的副本优先保留)。 ## ② 升级后渠道修复**下发不到桌面用户** 内核播种规则是「文件缺失才写」,所以桌面用户升级 GUI 后 channels.lua 仍是旧版 —— 我们发的渠道修复对桌面用户静默失效。桌面版必须自己处理: 按 app 版本打戳(.plugin-seed-version),版本变化时删掉 4 个内置插件文件 让新内核重新播种,旧副本留 .prev-<旧版本> 可人工恢复;用户自建插件不碰。 逻辑抽到 cmd/gui/plugin-sync.js(无 Electron 依赖),配 6 条 node 单测。 ## ③ 登录一律拉起默认浏览器(三条路径都覆盖) 桌面版的内容区是加载内核 WebUI 的 iframe,渠道登录链接是 target=_blank。 此前只处理了 setWindowOpenHandler,另两条路径仍会把 Electron 窗口带到 第三方页面。现在三条路径统一外抛: 1. window.open / target=_blank → setWindowOpenHandler 2. 顶层同标签跳转 → will-navigate 3. iframe 内导航 → will-frame-navigate **loopback 例外必须保留**:channels 的服务端浏览器(noVNC)就在 127.0.0.1:<port> 的 iframe 里,拦掉它会让 VNC 登录失效。 实测(打包后的 GUI + Xvfb + CDP 驱动真实窗口): [gui] open in default browser: https://example.com/mr-windowopen-probe [gui] open in default browser: https://example.com/mr-navigate-probe [gui] open in default browser: https://example.com/mr-frame-probe [gui] open in default browser: https://xiaohuanxiong.com/login?code=…(真实商汤登录链接) 顶层 URL 保持在内核页面(跳转被拦下),loopback iframe 正常加载。 ## ④ 顺手 - GUI 版本号 1.9.7 → 2.0.42(与内核同版本发版;package-lock 里还是 1.9.3, 一并同步); - make gui-test 跑桌面壳单测。 验证:打包后的 GUI 启动即 /api/plugins 列出 channels(ui.page=channels), 插件目录播种 4 个内置插件;外链四类实测均走默认浏览器。 (cherry picked from commit 411503aea5eb3b78360c1929a45cf97daa2ce833) | 18 days ago | |
fix(gui): 桌面版真正加载渠道插件 + 外链一律交给默认浏览器 ## ① 桌面版此前**完全没有插件系统**(渠道页根本不存在) GUI 内嵌内核的 config.yaml 由 main.js 生成,唯独漏了 plugin_dir —— 而内核刻意不给它默认值(运维显式开启)。后果:桌面版 plugin_dir: "", /api/plugins 返回空列表,channels 插件(多平台账号登录、凭据保管、自动 领取)在桌面端**完全不可见**。实测复现:同一份配置去掉 plugin_dir 就是 plugins: [],加上就有 billing/channels/quota/usage 四个。 修法: - 新 profile 直接写 plugin_dir: <profile>/plugins; - **老 profile 回填**(用户已有 config.yaml,不写就只有老用户永远没有插件)—— 新增 ensurePluginDirConfigured(),只在缺少该键时追加,其余内容不动; - 插件树由内核 SeedBundled 播种(按文件补齐,用户改过的副本优先保留)。 ## ② 升级后渠道修复**下发不到桌面用户** 内核播种规则是「文件缺失才写」,所以桌面用户升级 GUI 后 channels.lua 仍是旧版 —— 我们发的渠道修复对桌面用户静默失效。桌面版必须自己处理: 按 app 版本打戳(.plugin-seed-version),版本变化时删掉 4 个内置插件文件 让新内核重新播种,旧副本留 .prev-<旧版本> 可人工恢复;用户自建插件不碰。 逻辑抽到 cmd/gui/plugin-sync.js(无 Electron 依赖),配 6 条 node 单测。 ## ③ 登录一律拉起默认浏览器(三条路径都覆盖) 桌面版的内容区是加载内核 WebUI 的 iframe,渠道登录链接是 target=_blank。 此前只处理了 setWindowOpenHandler,另两条路径仍会把 Electron 窗口带到 第三方页面。现在三条路径统一外抛: 1. window.open / target=_blank → setWindowOpenHandler 2. 顶层同标签跳转 → will-navigate 3. iframe 内导航 → will-frame-navigate **loopback 例外必须保留**:channels 的服务端浏览器(noVNC)就在 127.0.0.1:<port> 的 iframe 里,拦掉它会让 VNC 登录失效。 实测(打包后的 GUI + Xvfb + CDP 驱动真实窗口): [gui] open in default browser: https://example.com/mr-windowopen-probe [gui] open in default browser: https://example.com/mr-navigate-probe [gui] open in default browser: https://example.com/mr-frame-probe [gui] open in default browser: https://xiaohuanxiong.com/login?code=…(真实商汤登录链接) 顶层 URL 保持在内核页面(跳转被拦下),loopback iframe 正常加载。 ## ④ 顺手 - GUI 版本号 1.9.7 → 2.0.42(与内核同版本发版;package-lock 里还是 1.9.3, 一并同步); - make gui-test 跑桌面壳单测。 验证:打包后的 GUI 启动即 /api/plugins 列出 channels(ui.page=channels), 插件目录播种 4 个内置插件;外链四类实测均走默认浏览器。 (cherry picked from commit 411503aea5eb3b78360c1929a45cf97daa2ce833) | 18 days ago | |
feat(gui): WebUI 与 Electron 壳的插件安装/删除/禁用/编辑 ## WebUI:新增「插件」页 - 列表来自 on_disk(不是 loaded 集合)——**加载失败的插件也必须显示并带错误**, 否则一个语法错误看起来和"插件没装"完全一样 - 启用/禁用(PUT {"enabled":bool})、删除、编辑源码、安装/覆盖 - 显示 hook_errors:插件抛异常在别处毫无痕迹,没有这一栏的症状就是 "功能就是不work" - 插到 dropzone 与代码编辑器都做了泛型化(bindDropzone / openCodeModal), 适配器与插件共用一份,而不是复制第二份只改 4 个 id 的函数 ## TABS 收敛为单一常量 tab 清单原本是字面量散在三处:goTab、refresh()、admin-only 隐藏列表。 加一个 tab 意味着三处都要记得改,漏一处就是"路由认得但界面不显示"—— 和今天早些时候 chain_step 漏报同一类静默缺口。现在只有 const TABS。 ## Electron 壳:设置面板里的插件管理 渲染进程不能直连内嵌核心(没有 key、不知道端口),所以走 IPC: renderer → plugins:proxy → main → HTTP /api/plugins 代理是 (method, path, body) 透传而不是固定命令表:固定表每加一个端点就要扩, 而"按钮存在但什么都不做"比"没有这个按钮"更糟。透传让渲染层能调用核心将来 新增的任何 /api/plugins 路由,路径在主进程校验。 ## ★ GUI 此前零测试,而本次改动就引入了三类"看起来没事"的问题 1. 引用了不存在的 CSS 类(.tag / .sm)——渲染成无样式文本 2. 引用了不存在的 helper(esc / escAttr)——那是 WebUI 的,renderer/app.js 是独立文档,点击时 ReferenceError 3. .ghost/.primary 只在 .form .actions 作用域内生效,插件按钮在 .pl-acts 里 于是是无样式裸按钮 补 4 个静态判据(不启动 Electron,守卫的正是"打开应用才看得见"那一类): TestGUICSSClassesExist 用到的类必须在样式表里定义 TestGUIHelperFunctionsAreDefined 被调用的函数必须有定义 TestGUIPluginPanelIsReachable 面板在 overlay 内、按钮已绑定、打开设置会加载 TestGUIIPCPathIsConstrained 代理必须限定 /api/plugins 前缀并拒绝路径穿越 写第一个判据时我错了三次:CSS 解析器先丢最后一个 selector、再把变量块当 selector、最后漏掉复合选择器(.tb-btn.tb-close)。两次"判据自己坏了"的 教训和本项目一贯一致——**判据出错的信号是它报了一个假问题**。现在改用宽松的 token 提取 + 显式的 guiKnownUnstyled 豁免表(blob/tgl/rail 是既有无样式类, 不是本次引入,失败它们只会让判据对新工作失去意义)。 ## 变异验证 改坏唯一的 CSS 定义(.pl-empty)→ TestGUICSSClassesExist 红 改坏 helper 名 → TestGUIHelperFunctionsAreDefined 红 ★ 第一次变异我改了 .pl-broken,判据**正确地没报**——因为它还被另一条规则定义。 这是变异选错目标,不是判据有洞;换 .pl-empty 后如期变红。 363 个测试全绿。 | 1 month ago |
| Files | Last commit | Last update |
|---|---|---|
| 2 months ago | ||
| 2 months ago | ||
| 1 month ago | ||
| 2 months ago | ||
| 2 months ago | ||
| 18 days ago | ||
| 18 days ago | ||
| 18 days ago | ||
| 18 days ago | ||
| 18 days ago | ||
| 1 month ago |