Repository navigation
Releases
插件 2.3.6(Clash + Magpie)
插件 2.3.6(Clash + Magpie)
Clash 修 #50(看门狗黑窗口);Magpie 修一处悬空引用并追平上游到
v0.1.3596(2.3.5 是v0.1.3383)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
Clash 2.3.6 — 看门狗改为隐藏启动(#50)
2.3.5 修好参数名之后,看门狗第一次真正建起来,也第一次把 node.exe 直接交给任务计划。任务计划在交互式会话(LogonType=InteractiveToken)里启动控制台子系统程序时会新建一个可见的控制台窗口,Node 的 windowsHide 管不到任务计划服务拉起的进程;Dock 内置的 node.exe 正是 PE subsystem=3 (CONSOLE)。结果是开启系统代理的瞬间,桌面弹出一个标题为 node.exe 路径的黑色窗口,并且一直挂着——看门狗常驻最长 12 小时,任务还设了每 5 分钟重复。
本版把任务动作从 node.exe 换成 wscript.exe:
- 新增
plugins/clash/watchdog-launch.js(JScript),由wscript.exe //B //Nologo //E:JScript拉起,再用WScript.Shell.Run(cmd, 0, true)以SW_HIDE启动 node; wscript.exe是 GUI 子系统,自身不建控制台;node 的控制台窗口从创建起就是隐藏的;- 启动器等 node 退出,任务实例在
Running状态一直保持,-MultipleInstances IgnoreNew才真正挡住 5 分钟重复触发(若启动器立刻返回,每 5 分钟会再起一个看门狗); //B是批处理模式:脚本自身出错时不弹「Windows Script Host」对话框,失败写<租约>.log,与watchdog.mjs的失败日志同一份;- 系统禁用 Windows Script Host(找不到
wscript.exe)时start()明确返回ok:false并记日志,不退回直接启动 node.exe——那正是本 issue 的窗口来源。
watchdog-launch.js 必须保持纯 ASCII:WSH 按 ANSI 读取无 BOM 的 .js,UTF-8 中文注释会吞掉下一行(实测 'return' statement outside of function)。单测断言文件里没有 >0x7F 的字节。
生命周期不变:系统代理接管成功才建任务,恢复成功、插件停止/关闭都注销;看门狗恢复完仍用 schtasks /Delete 删掉自己的任务。
Magpie 2.3.6 — 供应商编辑器打不开(foldNeeded is not defined)
现象
2.3.5 上点开任一供应商,Providers 页底部弹一个红色胶囊 foldNeeded is not defined,编辑器永远打不开。模型区一画就抛异常,整个页面停在错误提示上。
根因:补丁重放漏搬了一个 hunk
foldNeeded 是上游 app.js 里「模型芯片折叠」的模块级状态。fish.30 的两个相邻 hunk 是配套的:
| hunk | 位置 | 内容 |
|---|---|---|
@@ -11141,8 +11162,6 @@ |
顶部声明区 | 删掉 const foldNeeded = {} |
@@ -11300,19 +11304,13 @@ |
drawFold() 内 |
把 measure() 改成 requestAnimationFrame(...),从此不再引用 foldNeeded |
fish.31 只搬了第一个,第二个整段丢了:声明没了,两处用法还在。node --check 只做语法分析(通过),git apply 干净应用(0 冲突),follow-upstream.ps1 只比对 hunk 数与树哈希(通过)——三重闸门都拦不住,直到运行时才 ReferenceError。
同一个缺口还漏了另一段:renderModels 里内联的 kindNow / KIND_NAMES(只有 Auto/Image/Video 三类)/ pickKind 没换成 kindNowOf / openModelKindMenu,于是 #42 的六类「Makes…」菜单在芯片右键上一直没生效(外层的六类表被内联的三类遮蔽)。
修法
drawFold()改成requestAnimationFrame+ 直接量scrollHeight,不再依赖foldNeeded(补丁里删掉声明与两处用法);renderModels的内联三件套换成kindNowOf/openModelKindMenu,六类标注菜单真正生效。
追平上游 v0.1.3596
基线从 v0.1.3383 走到 v0.1.3596(213 个 tag),补丁 magpie-v0.1.3596+fish.33.patch,158 文件 / 261 hunk,30 个冲突 hunk 逐条消化:
app.js7 处:passUserAgent改成真值语义、draftOf与保存体带上hiddenAudios/hiddenEmbeddings、编辑器补语音/向量/其他模型三节、更新页的「打开」走宿主受控入口、prefsKeep带speechModel/embedModel;plugins/routing/client.js3 处:「图片输入」三态imagesSaid进草稿与保存体;- 插件页:
pagebridge.js的magpie.call通道、pluginpages.js的call分支、pluginpage.go的pluginCallRoutes接线、plugin/page.go的PageCalls与callsKeeping(用上游的lazyre); providers.go的MarksServesKinds、settingsapi.go的模型与超时键、gateway.go的MaterialsMCPPath路由与apis清单、own_mcp.go的GenerateAudioTool、bun.go的 registry 覆盖、registry.go的sync/atomic、provider/group.go的Images指针深拷;- 两个
i18n.js的新词条按键补齐(已有键一律不动,译文用上游的); core_budget_test.go的预算按实测上调到app.js 1,318,466/ 核心脚本1,543,404;- Cline 的上游提示文案保留上游版本,不回退。
新增闸门:补丁「删了声明、还在引用」直接拒绝
plugins/magpie/tools/check-assets-refs.mjs 只看一件事:补丁的 - 行删掉了某个顶格声明,而补丁应用后的文件里还在引用这个名字。判据刻意收窄(不做作用域分析、跳过语言内建与宿主全局),误报接近零。
接在两处,任一处不过都不出包:
follow-upstream.ps1重放后检查,失败以退出码 3 停下并列出符号;build-magpie.ps1编译前检查,失败throw。
实测:拿 2.3.5 那棵树 + fish.31 跑,准确报出 internal/gui/assets/app.js: foldNeeded(2 处引用);换 fish.33 则放行。
验证
| 项 | 结果 |
|---|---|
clash.fish-plugin |
17,195,643 B,sha256 a50d8f0fe969505d6ec1f5241921af62b4a591f30daf5ddca24e830232bbb1bf;7z t 通过(29 文件) |
magpie.fish-plugin |
40,752,108 B,sha256 a969ee93cc48e944986fb73e20ddeccf6bc16fc115d85928d9a9ac64cecfc3e0;7z t 通过(65 文件) |
magpie.exe |
89,544,704 B,FileVersion 0.1.3596.33、ProductName magpie fish;包内 foldNeeded 0 次(2.3.5 是 2 次/0 声明) |
| 补丁可复现 | 干净 v0.1.3596 + fish.33 → git apply --check 通过 → go build ./... 通过 → 悬挂闸门通过 |
go test ./internal/gateway -run 'Speaker|Speech|Embedding|Video|Kind|Materials|Audio' |
通过 |
go test ./internal/gui -run 'TestCoreScriptBudget|TestSettingsSaveKeepsWhatItDoesNotSend' |
通过 |
node --test --test-isolation=none "plugins/clash/*.test.mjs" |
170 条,167 通过、0 失败、3 跳过(page.browser.test.mjs 需 Edge + playwright) |
tools/verify-release.mjs |
两个包的归档资源、页面依赖、清单摘要与 npm 字节一致 |
上游测试里 internal/gui / internal/plugin 的若干用例在本机失败(symlink ... A required privilege is not held、sh.exe ... couldn't create signal pipe、并发 rename Access is denied),在未打补丁的干净 v0.1.3383 基线上失败集完全相同,属本机权限与沙箱限制,不是本补丁引入;TestProxyCheckSaysAProxyPassedBy 在全量运行时偶发、单跑通过。
升级
在 Dock 的插件页更新即可。
- Clash:无需重装 TUN 服务(本版没有改服务 exe)。若仍看到黑窗口,先确认任务计划里
FISH Dock clash watchdog-<SID>的动作是wscript.exe——2.3.5 建下的旧任务会被Register-ScheduledTask -Force覆盖,但只有在下次开启系统代理时才会覆盖;想立刻生效,关闭再开启一次系统代理。 - Magpie:本版换了基线,
magpie.exe会以新的运行副本落盘(旧副本按既有规则保留一天再回收)。供应商编辑器恢复正常;芯片右键的「Makes…」菜单恢复六类(图像 / 视频 / 语音 / 转写 / 向量 / 重排)。
摘要见 SHA256SUMS.txt。
插件 2.3.5(Clash + Magpie)
插件 2.3.5(Clash + Magpie)
Clash 合入 PR #49 并补一处竞态;Magpie 修 #48,并追平上游到
v0.1.3383 + fish.31(2.3.4 是v0.1.3240 + fish.30)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
Clash 2.3.5 — 看门狗真正建起来,TUN 服务卸载后退休(#49)
- 看门狗计划任务从未建成。
New-ScheduledTaskSettingsSet没有-DisallowStartIfOnBatteries/-StopIfGoingOnBatteries这两个参数,参数绑定直接失败,任务一次也没注册上。改为真实存在的-AllowStartIfOnBatteries/-DontStopIfGoingOnBatteries,测试断言旧参数名不得再出现。 - TUN 服务随插件卸载退休。 插件卸载后,
%ProgramData%\FishDock\clash-tun里的服务不再常驻。 - 退休条件加固(本仓追加)。 PR 原实现读
job.ini判断内核是否空闲:文件写到一半时,会把启动中的内核当成空闲,还会在内核进程仍在接管流量时撤掉服务(删掉运行中的 exe 并不会结束进程)。现在只看内核进程句柄:内核 exe 不在、子进程也已退出,才退休。
已安装并点过「安装 TUN 服务」的用户:升级后请再点一次。 服务 exe 是安装时复制到 ProgramData 的,不重装就仍是旧逻辑。
Magpie 2.3.5 — 媒体模型的音频回退(#48)
generate_audio 用 NearToken 的语音模型时必定失败,报 404 expected /v1beta/models/{model}:generateContent。两个根因:
- 进程内直接调
s.gemini。 那条路径依赖请求路由里的{call}参数,进程内调用时为空,于是 magpie 自己回了 404。现在解析 provider 后直连它的 Gemini API。 - 媒体模型被当成聊天模型,走了流式请求。 走网关的转译路径时会请求
streamGenerateContent,NearToken 明确拒绝。现在音频工具发非流式generateContent,请求体带responseModalities: ["AUDIO"],模型名不再带neartoken/之类的 provider 前缀。
两条路都失败时,错误会同时带出 audio/speech、generateContent、chat 三处上游原文,不再只给一句「没有可用音频端点」。只支持 chat 的模型(如 suno/suno_music)仍走 /v1/chat/completions,不会去问 Gemini。
Magpie 追平上游 v0.1.3383
补丁从 v0.1.3240 重放到 v0.1.3383,11 个文件、21 处冲突手工合并。合并口径:上游已有 VideoGen,放弃我们旧的视频模型字段,只补语音、向量模型行及视频 / 语音 / 向量三类超时;路由组补「图片输入」三态。
Claude Desktop 网关窗口没有中文:不是本版能修的
上游 v0.1.3142 那条说明是记录问题,不是修复;v0.1.3383 同样没有中文。本仓核对了 Claude Desktop 4.23118.0:
- magpie 接入时,Desktop 运行在网关(3p)模式,界面是安装包自带的
ion-dist.asar,只有 11 种语言,没有中文;主进程的语言表也没有中文。 - 每次启动,这个窗口都会从这 11 种语言里重新挑一种,写回
Claude-3p/config.json。magpie 写进去的中文会被 Desktop 自己改回en-US。 - 有中文的是 Anthropic 账号登录的窗口。它在线加载 claude.ai 网页,对话只发往 claude.ai 自己的后端,不接受自定义网关;网关配置又只在 3p 模式下生效。
所以 magpie 无法让网关窗口显示中文。需要中文界面时,在 magpie 里断开 Claude Desktop,回到 Anthropic 账号登录;想用 magpie 的模型,可以接入 Claude Code 等客户端。magpie 的 Agents 页在 Claude Desktop 一行也会提示这一点。
其他
- Magpie 清理
tmp时不再删除宿主写在那里的目录说明与事务日志(FISH-Dock#86)。之前闲置一天后升级插件会在提交阶段报「缺少旧版本目录说明」;Dock 2.2.1 宿主侧也已改为缺失时重建。
安装
在 Dock 的插件页更新即可;摘要见 SHA256SUMS.txt。
插件 2.3.4:Clash 断网修复 + Magpie #47
插件 2.3.4(Clash + Magpie 同版)。
Clash 2.3.4 — 关掉它不再断网
- 停止顺序改成「先还系统代理、再收内核」,结尾不再重复恢复;宿主给停用的预算是 5 秒,排在后面的那一步等于没做。
- 启动失败(取消 / 拉起失败 / 控制器没就绪)统一收尾:收候选内核、清运行态、还代理,原错误码不被掩盖。
- 坏租约(schema 不符、缺 previous/owned、字段类型不对)一律丢弃并带 code;恢复不再被一条坏记录拖死。
- 探活与收尾共享 1.6 秒预算:控制器永不回时 stop() 1.6 秒返回,代理已恢复、内核状态报「未确认停止」。
- TUN:插件写 /host.json 宿主租约,服务侧 Tick 发现宿主消失(或 pid 被复用)就停内核并把 job.ini 置 0。
- 看门狗改由任务计划拉起(独立于宿主的 Job),只在系统代理被接管期间存在,恢复/停用即注销,恢复完自删任务。
已在用 TUN 的用户需要重新点一次「安装 TUN 服务」:服务 exe 是安装时复制到 ProgramData 的。
Magpie 2.3.4 — #47
插件宿主被替换(换代理、更新、崩溃重启)时,provider 不再被说成「You removed it from magpie.」:
- 仍在安装的插件 provider 被隐藏时报「插件重启中」(updating: true),且不给 provider 字段,前端不会出现「加回来」。
- keepUnloaded 的「已安装」判据改用磁盘真值,不再依赖本轮的插件列表——宿主刚接手的那一瞬间正是旧判据失效的地方。
- neartoken:relist 除放回 setAside,还会取消该 spec 下隐藏的记录。
安装
clash.fish-plugin / magpie.fish-plugin 可直接在 Dock 的插件页安装;摘要见 SHA256SUMS.txt。
Magpie 2.3.3 + Clash 2.3.3(生图超时行收尾、素材 MCP 中文化)
插件 2.3.3(Magpie + Clash)
2.3.2 的紧急补丁:只改 Magpie 管理页的两处界面问题,无行为变更。
Magpie 的magpie.exe重编到补丁v0.1.3240 + fish.29(2.3.2 是 fish.28)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
设置 › 图像:删掉重复的「生图超时」行
2.3.2 把生图 / 视频 / 语音 / 向量的超时做成了模型行右侧的胶囊(N 分钟 ▾),但上游原生的「Image generation timeout」整行没有删——页面上于是有两个入口:一个是中文标题配 5/10/15/30/60 的段选,另一个是胶囊。
本版删掉整行,生图超时只留胶囊,与另外三行一致。上游为那一行写的浏览器用例 image-timeout-setting.test.cjs 一并移除(该行已不存在)。
「素材 MCP 服务器」补上中文
「Materials MCP server」此前只有英文键,中文界面里直接露英文。本版补:
- zh:素材 MCP 服务器
- zh-TW:素材 MCP 伺服器
- ja:素材 MCP サーバー
- de:Material-MCP-Server
下方说明文案(generate_image / generate_video / generate_audio / generation_result 四个工具、图片与视频保留一小时的 URL、跨机访问的 Bearer 密钥)也一并翻译。
验证
| 项 | 结果 |
|---|---|
magpie.fish-plugin |
37,236,260 B,sha256 15da4f15…758b;7z t 通过(60 文件) |
clash.fish-plugin |
17,188,560 B,sha256 c9db5303…0e6f;7z t 通过(28 文件) |
magpie.exe |
83,672,064 B,v0.1.3240+fish.29 / FileVersion 0.1.3240.29 |
| 上游补丁 | magpie-v0.1.3240+fish.29.patch:150 文件 / 252 hunk,干净 v0.1.3240 上 git apply --check 通过 |
verify-release --dist |
通过(两包身份、版本、sha256、字节、文件数一致) |
node --check |
app.js、i18n.js 通过(构建脚本自带闸门) |
| Go | go build -buildvcs=false ./... 通过;TestCoreScriptBudget 通过(app.js 变小、i18n 变大,合计仍在预算内) |
| npm | @fish-under-sea/fish-dock-plugin-magpie@2.3.3、…-clash@2.3.3(双源 latest) |
已知边界
- 2.3.2 的已知边界继续适用:Usage 页只读实时日志(>128 MB 的旧明细在
usage.jsonl.1);NearToken 的 TTS/音乐仍缺站点侧音频渠道;#44 原始样本根因待现场复现。 - 本版只有界面文案与设置项改动,Clash 仅版本位跟随。
Magpie 2.3.2 + Clash 2.3.2(存储不再无界、代理恢复可诊断)
插件 2.3.2(Magpie + Clash 同版)
两个插件同时到 2.3.2;Magpie 的
magpie.exe重编到补丁v0.1.3240 + fish.28(上一版是v0.1.3207 + fish.26)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
Magpie:追平上游 v0.1.3240
- 基线 v0.1.3207 → v0.1.3240(33 个 tag);
- 两处冲突手工消化:
providers.go的MarksServesKinds初始化字段、docs/subsystems/gateway-routing.md的 #42 段落按上游新文重写。
Magpie:provider 掉出后的 sticky 与恢复(#41)
插件重载、崩溃或安装窗口里「这次没报 provider」,以前会被当成移除,分组与页面跟着掉。本版:
- A(上游已实现,本版验证):
keepUnloaded对「插件仍装着、这次没报」保留上次的 provider; - B:插件清单可写
magpie.keepListedUntilRemoved,默认保留、写false才关(不改变上游对所有插件的默认语义); - C:专用恢复钩子
neartoken:relist→provider.RestorePluginProviders(spec),只恢复PluginLeft记录(崩溃/卸载窗口类),用户显式移除的不恢复。
Magpie:更新失败可见、首装进度(#41 的 P/Q)
- 安装失败落盘
<data>/plugin-install-errors.json,页面可点「重试安装」(magpie:plugin-retry/POST /api/plugins/retry-install,页面 call 与 GUI API 共用一份实现,安装进行中再点直接返回busy); - 失败后自动换国内镜像重试一次(
NPMMirror);半装时清残留目录;单包失败不拖累其余; - 首装逐包进度
preinstallProgress与总进度弹窗:只挡 magpie 本页、失败三出口(重试 / 稍后 / 以后不再提示),装完自动解除。
Magpie:设置页与素材 MCP
设置 → 图像的顺序改为:识图 → 生图 → 视频 → 语音 → 向量 → 识图 MCP → 素材 MCP;生图 / 视频 / 语音 / 向量四行右侧各一个响应超时胶囊(N 分钟 ▾,与「默认/思考强度」同一套度量)。
- 新增
videoModel;生图与视频模型互斥; - 四类媒体各用自己的超时(
imageTimeout/videoTimeout/speechTimeout/embedTimeout),网关四条媒体路径全部接线; - 素材 MCP:端点
/mcp/magpie/materials(旧/mcp/magpie/image继续服务),工具generate_image/generate_video/generate_audio/generation_result;三个工具各自取「设置里选的那个模型」; generate_audio三级降级:标准/v1/audio/speech→ 同供应商chat/completions(OpenAI 兼容的三种取音频形态)→ Gemini 原生generateContent+responseModalities:["AUDIO"];供应商没有音频渠道时给明确文案,不甩原始 500;- 语音/向量行显示补齐为「图标 + 模型名 · provider」。
Magpie:自启动适配(#45)
startWithBackoff对「start抛错」与「返回 error 状态」同样按 0/600/1500 退避重试;自启判断与失败日志共用一份view快照;- Clash 的
autostartKernel把读配置 / 修内核路径与start()放进同一轮 0/1.5/4 秒重试,每轮只读一次view,失败不抛activate()。
Magpie / Clash:数据根不再无界(#46)
usage.jsonl到 128 MB 滚到usage.jsonl.1(先删旧.1,Windows 才能 rename);key 的日/月/总额花销上限跨轮转仍正确(窗口早于实时日志第一条时补读.1),log-v1.bin按文件身份自动重建;masking保留期不再删当天文件(以前总量超限会把刚写的记录一起丢),当天也不占总量;routing/masking在magpie web启动时各扫一遍(此前只有「再写一条」才触发清理);- 插件侧:旧名二进制(
magpie.exe/.exe.new/.before-*.exe,一天宽限)、TEMP 残片(tmp/magpie等,一天宽限)在启动前回收;gateway-error.log滚动先删.1; - Clash:启动时清
tmp/import-*与写了一半的候选配置;删订阅把credentials/<id>.json与缓存 YAML 一起删,不再留 0 字节残片; - 清理动作都写进日志(
[magpie] …清理/[clash] TEMP 清理/ magpie 侧routing:、maskrec:)。
Clash:系统代理恢复失败可诊断(#44)
- PowerShell 失败应答改为
{ok:false, key, win32, message}:键级失败报ProxyEnable/ProxyServer/ProxyOverride,刷新失败单独报InternetSetOption(带GetLastWin32Error()); - 启动自愈、停止结果、看门狗三处日志都带键名与 Win32 码;看门狗写
<租约>.log(64 KB 封顶)并保留租约给下次重试; - 恢复失败仍只降级,不拦内核启停与页面。
验证
| 项 | 结果 |
|---|---|
magpie.fish-plugin |
37,229,994 B,sha256 244d71fa…f28e;7z t 通过(60 文件) |
clash.fish-plugin |
17,188,560 B,sha256 62aa1b2e…2dd8;7z t 通过(28 文件) |
magpie.exe |
83,668,992 B,v0.1.3240+fish.28 / FileVersion 0.1.3240.28 / ProductName magpie fish |
verify-release --dist |
通过(两包身份、版本、sha256、字节、文件数一致) |
| 上游补丁 | magpie-v0.1.3240+fish.28.patch:149 文件 / 248 hunk,干净 v0.1.3240 上 git apply --check 通过 |
| Go | go build -buildvcs=false ./... 通过;internal/usage、internal/maskrec、internal/gateway(历史/保留期)、internal/cli(web 子集)通过 |
| 插件测试 | 91 pass / 0 fail(4 个环境相关 skip) |
| npm | @fish-under-sea/fish-dock-plugin-magpie@2.3.2、…-clash@2.3.2 已发布;官方源与 npmmirror 的 latest 均为 2.3.2 |
| 管理页脚本 | node --check 全部通过(构建脚本自带闸门) |
已知边界
- Usage 页只读实时日志:超过 128 MB 的旧明细(本机约 40 天)在
usage.jsonl.1里,页面不展示;key 的花销上限不受影响。这是「有界」换来的,详见docs/maintainers/storage-budget-magpie.md。 - NearToken 的 TTS/音乐:站点侧暂无可用音频渠道(500/503/404
model_not_found),magpie 已按 audio → chat → Gemini 原生三级降级;chat 通道取音频按 OpenAI 兼容三种形态实现,成功响应样例仍未取得,站点恢复后若返回自有格式需补一条分支(不改协议)。 - #44 的原始样本根因仍未定性:2026-11-03 那条日志没有可复现环境;本版起再出现会直接指出是哪个键/刷新调用、什么 Win32 码。
- 真机未点验:设置页新排版、首装进度弹窗、
generate_audio的真实音频返回、Clash 系统代理开关(出包后建议各过一遍)。
Magpie 2.3.1(模型分类认插件 kind 与用户标注)
插件 2.3.1(Magpie)
只发 Magpie;Clash 仍是 2.3.0,包未动。
Magpie 的magpie.exe重编到补丁v0.1.3207 + fish.26(上游从 v0.1.3140 追平 67 个 tag)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
模型分类:官方判定 + 用户自定义标注(#42)
上一版(#24)只给出了四个分区,判据只有一条——catalog.ServesOf(id) 按模型 ID 名字猜,猜不出就丢弃或当成对话模型。插件 provider 声明的模型更彻底:plugin.Model 没有 kind 字段,capabilities.output 里的 audio / embedding 只用来判「能不能聊」,于是 NearToken 那类插件报上来的语音、向量模型既不进分区、也不在对话列表,直接消失。
本版把分类的来源补齐:
- 插件自己的 kind 先说:
plugin.Model新增kind(image/video/audio/embedding),pluginCatalog按它落Draws/Films/Serves;capabilities.output与模型 id 只作兜底。kind: audio(或embedding)的模型不再混进对话列表,哪怕它同时声明了text输出。 - 用户可以自己标:
settings.ModelKinds从image/video扩到speech/transcription/embedding/rerank,插件 provider 也能标(MarksServesKinds)。模型 chip 右键的 Makes… 菜单从两项变六项。 - 设置页取数补齐:
speakingOf收进插件声明的另一类模型(PluginServing),设置 → 图像的「语音模型 / 向量模型」两行不再只有自定义中转的 live 列表;判据统一走ServedAs(用户标注优先,其次模型自己的列表)。 - 「其他模型」栏:插件说某个模型「给的不是对话」却没说是哪一类时(
PluginUnkinded),编辑器单列一栏,点一下就能归类——否则这些模型三种列表里都看不到。 - 顺带修一处:设置页保存的字段白名单
prefsKeep补上speechModel/embedModel,不再靠后端 merge 兜底。
上游追平
- 基线 v0.1.3140 → v0.1.3207(67 个 tag);
- 重放时两处冲突手工消化:
providers.go的providerJSON初始化行(上游加了相邻字段)、core_budget_test.go的预算数(按新基线实测重设:app.js 1,317,737、核心脚本 1,542,234); - 上游已把「按 list 顺序列 unticked」内联进各处,fish.24 引入的
unticked()不再需要,本次不带。
验证
| 项 | 结果 |
|---|---|
magpie.fish-plugin |
36,903,448 B,sha256 6cb31f5d…54e82;7z t 通过(59 文件) |
go build ./... |
通过 |
| 新增单测 | modelkind_serves_test.go(六类标注 / 插件可标)、plugin_kind_test.go(kind 挡出对话列表)、speakers_kinds_test.go(插件 kind 与用户标注进 Speakers/Embedders)——全绿 |
| 受影响回归 | `go test ./internal/gateway -run 'Speakers |
| 管理页脚本 | node --check 全部通过(构建脚本自带闸门) |
已知边界
- 真机 UI 未点验:设置 → 图像的「语音模型」下拉、编辑器「其他模型」栏需要装上本版后过一遍。
- NearToken 侧要配合:它的
kind取值(chat|image|video|audio|embedding)本版已认;kindOf对「能听音频但输出文本」的对话模型有误判,插件仓已开单(magpie-neartoken#1),修复前这类模型可能被标成音频。
FISH Dock 插件 2.3.0(Clash + Magpie:内置件改按 npm spec 登记)
插件 2.3.0(Clash + Magpie 同版)
两个插件同时到 2.3.0;Magpie 的
magpie.exe仍是补丁v0.1.3140 + fish.24(本版没有重编 exe)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
Magpie:两个内置件改按 npm 包登记
2.2.9 的内置件是「同步目录副本 + 绝对路径」登记,那条 spec 不在 magpie 自己的更新循环里:目录副本停在发版那天的版本,上游(@fish-under-sea/magpie-checkin-relay-probe / @fish-under-sea/magpie-purge)发了修复用户也拿不到。
本版改成与 @magpie-community 那批预装供应商插件同一条路——只把 npm spec 写进 magpie 的 plugins.json:
"@fish-under-sea/magpie-checkin-relay-probe@latest"
"@fish-under-sea/magpie-purge@latest"
- 首装与后续更新都由 magpie 自己的更新循环按 spec 完成;
magpie.fish-plugin不再带bundled-plugins/副本(包从 36.8 MB 降到 36.3 MB);- 迁移:2.2.9 的目录副本条目换成 npm spec(
options/off保留);用户自己钉的版本原样保留;2.2.8 及更早的page-checkin/page-relay-probe仍整条删除; - 代价:首次安装要联网一次。
Clash:无功能改动
版本位跟随统一到 2.3.0,包内容与 2.2.8 一致(mihomo 内核、GeoSite/GeoIP、tun-service 均未改)。
验证
| 项 | 结果 |
|---|---|
magpie.fish-plugin |
36,263,931 B,sha256 f0fd7495…456f0;包内无 bundled-plugins,page-seed.mjs 为新实现(8,410 B) |
clash.fish-plugin |
17,185,169 B,sha256 dc6337f6…797ab6;service/mihomo.exe、GeoSite.dat、GeoIP.dat、tun-service.exe 齐全 |
| 单测 | plugins/magpie/*.test.mjs 74 pass / 3 skip / 0 fail;tools/build-release.test.mjs 全绿 |
| npm | @fish-under-sea/fish-dock-plugin-clash@2.3.0、…-magpie@2.3.0 已发布 |
已知边界
- 首装需要联网一次(magpie 的更新循环按 spec 安装);离线环境首启会登记成功但装不上,下一次更新循环重试。
FISH Dock 插件 2.2.9(签到&探针合并 + 破甲内置 + #36)
Magpie 2.2.9
插件版本 2.2.9;
magpie.exe补丁基线v0.1.3140 + fish.24(文件版本0.1.3140.24)。
校准:FISH Dock ≥ 2.0.0、宿主 API 1、Windows x64。
本版三件事:两个内置页面插件收成一个(解耦后重新内置)、新增内置破甲、#36 四项进宿主补丁。另有 #37 的日志落盘。
一、签到 + 中转站探针 → 一个插件
- 新包:
@fish-under-sea/magpie-checkin-relay-probe@1.0.0,单独维护在
Fish-under-sea/magpie-checkin-relay-probe与 npm 同名包。 - 形态:一个页面插件、两个页面,页内标签切换(签到 / 中转站探针);侧边栏名称 签到&探针,
图标沿用签到那套(page/icon.png+page/icon.svg)。 - 两页的页面代码、图标、样式、各自的测试原样搬入(
page/checkin/、page/relay/),
新增的只有切换壳page/index.html/app.js/style.css与转发层page/relay.js。 - 为什么是帧:两页都按「整个文档就是我」写(全局 id、各自样式表),同文档必互相踩;
帧里的bridge.js连的是本页,所以relay.js把子帧消息换成新 id 转发给 magpie 窗口,
回程换回原 id,主题/可见性事件广播给两个帧(单测 8 条覆盖)。 - 升级迁移:
plugins.json里旧的page-checkin/page-relay-probe(npm 名或旧包内的绝对路径)
整条删除,新条目按稳定路径写入;用户在这两条上设过的off与折叠状态随新条目保留。
不删旧目录里的任何用户数据。
二、新增内置破甲
@fish-under-sea/magpie-purge@0.3.1随 Magpie 包分发,首启同步到
<magpie 数据>/plugins/magpie-purge并以绝对路径登记;页面与网关钩子都从本地目录加载,离线可用。0.3.2 在本次发版期间才发布,只改图标与 README;2.2.9 内置的是 0.3.1,下一版同步。
三、#36 入宿主补丁(fish.24)
- 重列钩子:插件页的「刷新」现在会让宿主再列一次插件模型
(plugin.Providers,与供应商编辑器「获取模型」同一条路径),点完 ≤5 秒即可看到
plugin-providers.json/cache/providers-state.json的 models 数变化。 - 交接防抖:
handOver/settle/dropHostProvider只认「插件自己列出来、且那条
signedIn == true」;不再在删除时catalog.SaveLive(..., nil)。providers.json的
deleted[]不再出现「删→建→删」增长。 - 分组语义:
ModelIDs()只认模型名(宿主模型平面没有分组维度),口径钉在插件契约上——
插件只在「该模型所有分组都停用」时才写条目;部分分组停用留在页面自己的明细里。
新增测试固定这一条。 - 旧 options 清理:启动网关时清一次
@fish-under-sea/magpie-neartoken的
disabledModels/enabledByGroup/disabledByGroup三个键;只动这个包,别的插件同名选项不碰。
四、页面宿主支撑(合并件必须)
frame-src放行页面自己目录(此前是'none');_magpie/bridge.js在页面目录的任意深度都可取(子帧在checkin/、relay/下);- 页面文件补
Access-Control-Allow-Origin: *:sandbox 帧是不透明源,type="module"脚本以
Origin: null取文件,没有这条整个脚本不执行(中转站探针页本来就是 module,之前也受这条影响); - 页面响应不再带
frame-ancestors:Chromium 不拿任何源与不透明祖先做匹配,'self'、地址、
路径源、*都会把子帧拦成ERR_BLOCKED_BY_RESPONSE。页面 URL 自带 32 位一次性 token,
且页面无表单、无导航、无网络,风险面收在这里。
五、#37 日志落盘
- 适配层把
magpie.exe的 stdout/stderr 同时写<插件数据目录>/magpie.log:
单文件 1 MB 滚动、保留.1一份,每次启动先落一行分隔(时间、端口、网关端口)。 gateway-error.log保持原样(只记启动失败 JSON);host/plugin-logs/fish.magpie.log仍是适配层自己的输出。
六、验证
| 项 | 结果 |
|---|---|
go test ./internal/neartoken |
ok |
go test ./internal/plugin -run 'TestDropLegacyOptions' |
ok(TestLoadConcurrentWithSavesAndEdits 在本机 Windows 沙箱恒失败,清洗基线同样失败,属环境) |
node --test plugins/magpie/*.test.mjs |
76 项 / 73 pass / 3 skip / 0 fail |
合并插件自测(test/ + page/relay/app.test.mjs) |
34 项全绿 |
| 真窗口(Edge headless,真 magpie) | 侧边栏「签到&探针」,两页切换均渲染;签到读到台账、探针读到 relay:view 配置 |
| 包内实物 | service/magpie.exe 82,618,880 B;plugins/magpie/bundled-plugins/{magpie-checkin-relay-probe,magpie-purge} 齐全;无 page-plugins 残留 |
| 包摘要 | magpie.fish-plugin 36,817,191 B,sha256 f8f45bfe…a619a |
七、已知边界
frame-ancestors取消是为内嵌帧让路的取舍,见第四节;如果以后要恢复,得让 magpie 的窗口
以非 sandbox 方式托管插件页,那会打开更危险的口子(同源可读 /api)。- 分组的「部分停用」仍不会反映到 magpie 模型清单;这是宿主模型平面没有分组维度的直接结果,
不是本版的遗漏。
FISH Dock 插件 2.2.8(修 Magpie 启动失败 + Clash 不动绕过表)
FISH Dock 插件 2.2.8(Magpie + Clash)
Magpie 2.2.8 —— 修好「准备 Magpie 资料目录失败」
2.2.7 引入的回归:runtime.mjs 用了 normalizePageTitles 但没有 import,于是
启动时的资料准备整段抛 ReferenceError,被外层 catch 成 DATA_MIGRATION_FAILED ——
就是 Dock 上那句「准备 Magpie 资料目录失败,原资料已保留」。2.2.7 在任何机器上都起不来,
升级到 2.2.8 即恢复。
顺带两处配套修正:
- 目录指纹把
package.json按「规范化后的文本」计算,避免每次启动都判定内容变了、
重复发布整套页面目录; - 标题归一化保持幂等(第二遍改动为 0)。
沙箱用你的真实数据副本实测:@Fish-under-sea/签到 → 签到,包名仍是
@fish-under-sea/page-checkin,第二次归一化改动 0,目录指纹稳定。
Clash 2.2.8 —— 不再动别人的绕过表和地址
对照 Clash Verge 的做法,我们之前有两处越界:
- 写死了
ProxyOverride='<local>':Verge 和用户自己的绕过表
(localhost;127.*;10.*;172.16.*…;<local>)会被我们覆盖掉——这就是「本机配置坏了」。
现在只接管ProxyEnable与ProxyServer,ProxyOverride原样沿用当前值。 - 停止后地址还挂着我们的端口:开关虽然关了,但只看
ProxyServer不看ProxyEnable
的程序(不少 Electron / Node 工具如此)会一直走死端口。现在开关已关、地址指向我们的
端口时,把地址一并清空。
并保留上一版的两条兜底:内核一停就收 TUN;没有租约但注册表还指着我们端口时关开关。
校验
plugins/clash65 项测试全过page-seed16 项(1 条已知 flaky 并发用例)通过;标题归一化与指纹稳定性实测通过- 两个包
verify-release均通过
摘要
47427c60eb8a6f573f88ef034092dd3d28084fe5f76e9dd2b576135ab6a86115 magpie.fish-plugin
56366e08e093dd66fbdf3cee0c5b95805e8f02e8cb71b434c4aa4a202ca446db clash.fish-plugin
FISH Dock 插件 2.2.7(侧边栏只留文字 + 内核停即收 TUN)
FISH Dock 插件 2.2.7(Magpie + Clash)
Magpie 2.2.7 —— 侧边栏只显示文字
侧边栏条目原来写着 @Fish-under-sea/签到、@Fish-under-sea/中转站探针。npm 包名
(@fish-under-sea/page-checkin / page-relay-probe)保持不变,但标题里的 scope 只是
噪声。现在启动时做一次幂等归一化:
magpie.page.title与magpie.page.titles.*里以@用户/开头的标题 → 去掉前缀,
只剩「签到」「中转站探针」;- 没有前缀的标题一个字都不碰;去掉后为空则保留原样;
- 包名、版本、其余字段全部不动,第二遍不会再写盘。
Clash 2.2.7 —— 内核一停就把 TUN 收掉
之前的停止路径只在「TUN 服务托管」时才收 TUN。如果上一次会话留了 enabled=1 的 TUN
服务,而这一次是普通模式,内核一停就变成有虚拟网卡、没有内核:所有流量打进死内核,
表现就是「偶发掉线、网络回环、整机没网」。
现在:
- 内核进程自己退出(崩溃 / 被杀 / 手动结束)→ 立刻检查 TUN,
enabled就disable; stop()的tunStop不再要求viaService,只要服务还enabled就收;- 系统代理同上一版一样:没有租约但注册表还指着我们的混合端口 → 直接关开关。
关于「环境变量代理」
排查时发现当前会话里有 HTTP_PROXY=http://127.0.0.1:7895(HTTPS_PROXY 同),而
用户级/机器级环境变量都是空的——它来自父进程继承,插件改不到。内核一停,所有继承
这个变量的程序(模型请求、git、npm)都会打进死端口。自查与清理:
"$env:HTTP_PROXY / $env:HTTPS_PROXY" # 当前会话
[Environment]::GetEnvironmentVariable('HTTP_PROXY','User') # 用户级
netsh winhttp show proxy # WinHTTP(另一套)自己启动 Dock 的那个进程(终端 / 启动器)里清掉再启动即可;插件不会、也不该去改
全局环境变量。
校验
plugins/magpie全部用例通过(新增标题归一化 1 条,含幂等断言)plugins/clash142 通过 / 3 跳过 / 0 失败- 两个包
verify-release均通过
摘要
e9bf3ced587b9880387319ce5ebcf0e1793e4a5c254314a026b52a16f99d7ab7 magpie.fish-plugin
96340e97b7ab920cef10c2d9b3cfbdbbb3ef150887f1c65fef838736ec8493fb clash.fish-plugin