# 变更记录 版本号在仓库根的 `package.json`,同时会显示在设置页页头徽标上(`client.js` 的 `PACKAGE_VERSION` 必须与它逐字一致,验收有断言盯着)。 ## v0.4.3 — 2026-10-11 **新增「上架插件市场」文档**(`docs/marketplace.md`):条目 YAML、格式坑、PR 描述与步骤。插件市场不直接收录,它的列表来自精选清单 [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin),投稿是往那边提一个 `data/plugins/kkj-luna__dsh-image-bridge.yml`。文档把两件事写清楚了:**只声明 `dsh.client` 不算可安装**(这是最常见的被拒原因),以及面对目录里同类插件(`dsh-image-create`、`dsh-ark9canvas` 等)该主动说明哪些差异——指南的规则是"不是先来后到,是谁更好"。 **`docs/marketplace.md` 加入 `files` 白名单**:它之前不在白名单里,所以不会随包发布。文档既已入仓,就该让 npm 上那份也读得到。 **修掉四处过时的图标描述**:v0.4.2 换了配色,但两份手册里仍写着"蓝底白图 / white mark on brand blue",手册的目录树也还标着"蓝底白图"。这类"改了 A 忘了描述 A 的文档"最容易积累,所以这次一并扫干净(`icon.svg` 注释里那处保留——它是在解释改动理由,"纯蓝底白图会显得更跳"是理由本身)。 **验收**:444 条断言全绿;29 个相对链接零死链;门面中英 15=15 节、手册 31=31 节。 ## v0.4.2 — 2026-10-11 **图标改配色**:插件列表/市场里显示的图标从**蓝底白图**改为**近黑底 + 渐变蓝图形**。 理由来自实际观感:旧图标那块品牌蓝(`#4176e6`)在深色列表里比邻居更亮、更"跳"——列表上其它插件要么是低饱和底、要么是渐变蓝实底,只有它是纯品牌蓝铺满。现在底色换成近黑(`#111318`,略偏蓝以免在纯黑主题里浮起来),图形用一条从上到下的蓝渐变,与邻居同族但更安静。 **图形几何一个字节没动**:`icon.svg` 与 `client.js` 内联图形(设置页导航用)的几何数据必须逐条一致,所以这次只改 `fill` / `stroke` / 渐变定义,图形元素的坐标保持原样——跨文件几何断言继续通过。 **新增两条断言,钉死两个真实踩过的坑**: - **渐变亮度下限**。黑底有个副作用:渐变里深的一端如果贴到品牌蓝(`#2f6bff`,相对亮度约 0.17),压在 `#111318` 上对比度只有 1.7:1,图标会糊成一块。现在断言要求渐变最亮端亮度 ≥ 0.35,并断言底色亮度 < 0.02,顺带禁止把渐变改回纯白。 - **XML 良构性**。这个文件**曾经因为注释里出现连续两个连字符而在远端渲染成破图**——XML 规范禁止该序列,GitHub 的 sanitizer 与 librsvg 直接拒绝整份文件,而浏览器宽容,所以本机怎么看都是好的,只有"README 里内嵌图标变成破图"这种远端现象才暴露。以前只在注释里写了句提醒,现在加断言盯住,不再依赖"有人记得"。 **验收**:444 条断言全绿(client 183 → 184,新增的就是上面那条 XML 断言);27 个相对链接零死链;门面中英 15=15 节、手册 31=31 节。 ## v0.4.1 — 2026-10-11 **发布到 npm。** `kkj-luna-dsh-image-bridge@0.4.1` 上了 npm,安装从此是一条命令: ```sh dsh plugin --profile web add kkj-luna-dsh-image-bridge ``` v0.4.0 做完了"能发布"的全部准备(改名、包清单、发布前断言),但**它自己没发出去**——所以第一个真正出现在 npm 上的版本是 v0.4.1。四份文档的安装节也随之把 npm 改回主推、`github:` 降为"想跟最新提交"的备选。 **修掉一个打包缺陷(发布前体检抓到的)**:`files` 白名单里显式列着 `docs/logo.png`、`docs/settings-zh.png`、`docs/settings-en.png`,于是它们**绕过了 `.npmignore` 的排除规则**跟着进了包——tarball 从 149 KB 涨到 537 KB,安装后 node_modules 里多出三张运行时用不到的图(那三张只在 README 里当插图)。`.npmignore` 说"排除 `docs/*.png`"、`files` 说"包含这三张",两边打架时以白名单为准;这个矛盾本身就是隐患。现在包是 **13 个文件 / 149 KB**。 **这就是"发布前体检"存在的意义**:如果直接 `npm publish`,这三张图会永久留在 v0.4.1 的 tarball 里——npm 不允许重发同一个版本号,只能再发一版。 **2FA**:npm 现在强制要求发布时提供一次性验证码(`npm publish --otp=123456`),绕过 2FA 的旧式令牌正在被逐步禁用。 ## v0.4.0 — 2026-10-11(未发布到 npm) **为发布 npm 做的改造**:包名从 `@local/dsh-image-bridge` 改为 **`kkj-luna-dsh-image-bridge`**。 > **这个版本没有发布到 npm。** v0.4.0 完成了改名与包清单准备,但发布时 npm 要求 2FA 验证码, > 当时没有走完那一步,于是 `registry.npmjs.org/kkj-luna-dsh-image-bridge` 一直是 404, > 安装只能用 `github:` 或本地目录。**第一个真正发布的版本是 v0.4.1**,npm 上不会有 v0.4.0。 ```sh dsh plugin --profile web add kkj-luna-dsh-image-bridge ``` **为什么必须改名**:`@local/` 不是任何人拥有的 npm scope,**发不出去**;而补丁行的 `name` 必须等于**安装用的包名**(loader 走 `resolveBundleDir("dsh", name, …)` 去解析这个包),所以"包名"与"补丁行 name"只能一起改。实测确认过:仓库根原本没有 `package.json` 时 `github:` 装法也会失败,同一处结构决定了两件事。 **GitHub 用户名改为 `kkj-luna`**:仓库地址、issue 链接、README 徽章、`client.js` 里的 `REPO_URL` 与 `package.json` 的 `repository`/`homepage`/`bugs` 一起更新。npm 包名里的前缀跟着用户名走(`kkj520-dsh-image-bridge` → `kkj-luna-dsh-image-bridge`)——**旧包名从未发布过**,所以这次改名不影响任何已安装的用户。GitHub 会自动重定向旧地址,但配置里写死的 URL 必须自己改,否则徽章与 issue 链接会指向重定向而非真实地址。 **保持不变(更新不丢配置的关键)** - 补丁行 id `image-bridge-v4` 与设置命名空间 `image-bridge-v4` **一个字都没动**——行 id 是 profile 配置的锚点,也是设置页写入的命名空间。 - 升级只需改 profile 里那一行的依赖名(`@local/dsh-image-bridge` → `kkj-luna-dsh-image-bridge`)。`verify-upgrade` 那套断言覆盖了改名场景,按真实层序合成后确认配置零漂移。 **包清单(为发布 npm 补齐)** - 去掉 `private: true`(留着就发不出去),加 `publishConfig.access: public`。 - 补 `repository` / `homepage` / `bugs` / `keywords`(npm 页面与搜索引擎需要)。 - 加 `scripts.test`(一条命令跑完六套验收)与 `scripts.prepublishOnly`(发布前先过清单断言——**发错版本发不出去**比发出去再撤回代价小得多)。 **三种装法** | 方式 | 命令 | 适合 | | --- | --- | --- | | **npm(推荐)** | `dsh plugin --profile web add kkj-luna-dsh-image-bridge` | 日常使用;预构建安装,免源码构建授权 | | GitHub | `dsh plugin --profile web add github:kkj-luna/dsh-image-bridge` | 想跟最新提交、或 npm 上还没发到那一版 | | 本地目录 | `dsh plugin --profile web add <仓库绝对路径>` | 开发本插件 | **验收** - 断言 **425** 条全绿。改名涉及三处必须逐字一致的声明(`package.json` / `index.js` 的 `export const name` / `cordis.patch.yml` 的 `name`),断言会抓"只改一半"。 - 顺带修掉一条**断言里的错误假设**:徽标文案原先按"包名去掉 scope = 仓库名"推导,改名后这个推导不再成立。现在改为读取客户端自己的 `REPO_NAME` 常量——测试应当核对**界面真的用了哪个常量**,而不是自己再猜一遍推导规则。 - 链接检查 27 个相对链接零死链。 ## v0.3.0 — 2026-10-11 **一条命令安装**:插件包根目录从 `plugins/dsh-image-bridge-v4/` 上移到**仓库根**。 ```sh dsh plugin --profile web add github:kkj-luna/dsh-image-bridge ``` 为什么必须动结构:`dsh plugin add` 对 git 形式(`github:owner/repo`)是把整仓交给 pnpm 取包,**没法指定子目录**——它只会打仓库根那个 `package.json`。插件在子目录里时这条命令根本走不通,只能"先克隆、再填本地绝对路径"。dsh-market / superpowers-dsh / whale-widget 这些插件的仓库根都直接是插件包,原因就在这里。 **改了哪些文件** - `package.json`、`cordis.patch.yml`、`index.js`、`client.js`、`locale/`、`icon.svg` → 仓库根 - 插件完整手册 `README.md` / `README.en.md` → `docs/manual.md` / `docs/manual.en.md`(避免与仓库门面 README 撞名;仓库门面才是 npm 页面该显示的那份) - 插件目录内那份 `LICENSE` 删掉——与仓库根的那份**逐字节相同**(同一 SHA256),留两份迟早会漂移 **保持不变(这是"更新不丢配置"的关键)** - 包名 `@local/dsh-image-bridge`、补丁行 id `image-bridge-v4`、设置命名空间 `image-bridge-v4` **一个字都没动**。行 id 是 profile 配置的锚点,也是设置页写入的命名空间,改它等于让所有老用户的服务商配置失效。 - 升级只需改 profile 里那一行 `link:` 依赖的路径(`.../plugins/dsh-image-bridge-v4` → 仓库根)。`verify-upgrade` 按真实层序合成后确认**配置零漂移**。 **打包卫生** 新增 `.npmignore`:`.dib-verify/`(验收套件)、`docs/*.png`(截图与 logo)、`.ref-*.tmp*`(本地缓存)都不进包。`files` 白名单同步更新(`README.en.md` 已不存在,改为 `docs/manual*.md` 与 `CHANGELOG.md`)。装到用户机器上的只有跑起来需要的东西。 **验收** - 断言 **425** 条全绿:迁移前基线 425 → 迁移后仍 425,全部套件在新结构下通过。 - 两条断言随结构更新:`CHANGELOG` 路径从 `ROOT/../../` 改为 `ROOT/`;"目录名必须是 dsh-image-bridge-v4"改成钉住**新结构**(包根有 `package.json` 与挂载声明、旧子目录已移除)。 - 真实环境验证:profile 里失效的 junction 重建后,通过它读到 `@local/dsh-image-bridge @ 0.3.0`;`verify-upgrade` 24/24;跨进程端到端真实出图(512×512 PNG,252,622 字节,已落盘)。 ## v0.2.2 — 2026-10-11 修掉审查报告里剩下的用户体验与无障碍缺陷(A4 / A6 / A7 / A8 / A10 / A12 / A17),并把安装说明改成"让 Agent 帮你装"优先。 **修掉的缺陷** - **图片加载失败会留下裂图**(A4):`loadImage` 只覆盖"拿地址"这一步,地址拿到了不代表图能取到(附件被清理、地址过期、文件被删)。原先只靠 promise 的 reject,浏览器层的失败没人接,卡片就显示半张图加一个系统破图图标。现在 `img` 挂了 `onError`,走与"地址都拿不到"同一句可读文案。 - **状态灯"过承诺"**(A6):绿灯有**两种来源**——本次会话真测过,或"这家保存过模型列表"这个**持久信号**。原先两者共用一句「已连接」,而那个信号只证明曾经成功过,密钥可能早已被吊销、界面也不会重新验证。现在状态小字分四档,持久信号那档明说「以前可用(已保存模型列表,本次未测试)」,与悬停说明同源。 - **重复提交**(A7 / A8):保存是异步的,而 `state.phase` 要等一次渲染才变成 `saving`——**回车连按两下**正好落在这个窗口里,会写两遍配置、必要时还写两遍密钥。现在四条保存路径(删除提供商 / 保存提供商 / 保存模型设置 / 保存尺寸)共用一把 ref 闸门,在**赋值那一刻**生效;每次结束(无论成败)都复位,否则第二次点保存会被无声吞掉。 - **顺带补上的并发缺口**:A19 之后四条路径写的都是**同一套完整字段**,两个保存并发时后落盘的那个会把前一个的结果整片覆盖。「保存尺寸」与「保存模型设置」原先**没有**走闸门——现在四条统一,并有断言钉住"提供商保存进行中时,保存尺寸会被挡住"。 - **长错误看不全**(A10):状态行是单行省略的(`text-overflow:ellipsis`),而服务商报错经常很长(带 URL、状态码、响应体片段)。没有 `title` 时用户只能看到半句话,而"看不全错误"等于"没法排查"。现在 `title` 恒等于完整文案。 - **徽标读屏读中文**(A12):页头徽标的 `aria-label` 是硬编码中文,英文界面下读屏会读出中文。现在走语言包,中英各一条、占位符现场替换。 - **176 项模型只能箭头翻**(A17):模型下拉在真实配置里能有 176 项,键盘却帮不上忙。现在支持**输入跳转**(type-ahead):按字符跳到第一个匹配项、连续重复同一字符轮换到下一个同前缀项、带 Ctrl/Meta/Alt 的组合键不当作输入;搜索缓冲**不跨交互存活**(关掉菜单再打开按新字符,不会拼成上一次的词——这条是修 bug 时实测发现的)。 **安装说明** 参照成熟插件的写法把安装节按"省事程度"重排:**最推荐让 Agent 帮你装**(给一段可直接粘贴的话,Agent 自己克隆、装、重启、核对),其次是自己敲命令,并新增一节说清两个名字的来历——`@local/` 是 DSH 给本地自作插件的官方约定(避免与 npm 真包撞名),目录名与行 id 里的 `-v4` 是内部重写计数器。 **文档与验收** - 断言从 **414** 条增至 **425** 条(`verify-client` 169 → 180),每项修复都有对应断言;重复提交与状态灯两项都做了红-绿验证。 - 插件手册里状态灯那一节改成四档口径。 ## v0.2.1 — 2026-10-11 v0.2.0 之后的一轮修复与文档改版。**行为上最重要的一条**:超时模型换了,见下。 **超时模型简化:只看"连不上",不看"画得慢"** v0.2.0 有两条线:一条是"请求发出后多久没拿到响应头就换备用"(`fallbackAfterMs`,设置页「主模型超时(毫秒)」,默认 90000),另一条是写死的连接宽限。前者按**响应快慢**判断服务商行不行——同步生图本来就要几十秒(实测 42–61 秒才回响应头),这个判断既做不准,也容易把正常的慢生成误杀,实现还绕(要区分"发出前"与"发出后"、超时后还要探活解释)。现在**整体删掉按响应时间判断的那一套**,只留连接: - 设置页改成「**连接超时(秒)**」(`connectTimeoutSeconds`,默认 **15**):**用户填秒**,代码内部自动换算毫秒,且换算只在一个函数里发生。DNS / TCP / TLS / 代理在这段时间内没把请求发出去,就算这家连不上,**改用备用模型**。 - **备用模型的连接上限固定 30 秒**(`FALLBACK_CONNECT_TIMEOUT_S`),刻意不做成设置项:备用是最后一条路,不该再多一个会填错的旋钮。 - **请求一旦发出就不再计时**:服务商画多久都照等,整次调用的上限仍由 `timeoutMs`(默认 180000)兜底。老配置里的 `fallbackAfterMs` 变成未知字段,会被插件的配置归一直接丢掉,不影响运行。 - **两家都连不上时,错误以「模型连接失败」开头**,并列出两次尝试各自的原因与去哪儿检查(设置页地址、本机网络、或者点「测试连接」)。 - **已经发出过的请求不再重发**:非幂等的 POST 重发一次,服务商可能已经生成并计费两次(这是旧实现里真实存在的重复计费路径)。 - 顺带删掉**超时后探活**:没有按响应时间的超时之后,它已经是一条永远走不到的死路。 **无障碍** - **浮层的焦点管理**:打开时把焦点收进浮层、Tab / Shift+Tab 不会跑到背后的页面,关闭时回到打开它的那个元素(此前焦点留在背后,键盘用户等于在"看不见的地方"操作)。 - **自定义尺寸文本框有了可访问名称**(走语言包,中英各自正确)——此前它是一个没有名字的文本框,读屏用户无法知道它是干什么的。 - **卡片文案不再中英混杂**:图片「加载中 / 加载失败」、图片替代文本、以及失败且无正文时的「未知错误」,此前都写死在代码里(英文界面会冒出中文);现在一律走语言包,断言会用英文渲染一遍来钉住。 - **焦点环不再可能整体消失**:`outline` 的宽度令牌缺失时整条声明会失效,键盘用户就完全看不到焦点在哪;现在宽度与颜色各自带 fallback(颜色兜底到其它主题令牌,不引入任何字面色)。 **安全加固(审计后续)** - **客户端诊断日志不再可能写满磁盘**:这条通道由浏览器驱动、Host 没有观测手段,所以它必须存在;但原先只有"单条长度上限",一个出错循环就能无限追加。现在三层一起挡——单条 10 KiB 截断、**60 条 / 10 秒**的速率上限(超出的丢弃并计数)、**总量 1 MiB** 到顶就轮转到 `.1`(只留一份备份)。被丢弃时仍会写一条"已丢弃 N 条":否则"日志里没有"会被误读成"没发生过"。 - **落盘不再跟着符号链接走出工作区**:原先只挡"路径里写了 `..`",挡不住工作区里一个指向外部的目录链接——词法路径仍然"在工作区内",实际写到了外面。现在把两侧都解析成真实路径再比一次。**红-绿验证过**:去掉这层确认后,生成的 PNG 真的出现在了工作区外(断言当场抓到)。注意它**不是抛错而是警告降级**:图已经生成、已经计费,不该因为落盘失败丢掉结果。 - **诊断日志不再记录密钥长度**:`keyLength` 属于凭据元数据,能把穷举空间缩小一截,而对排查没有帮助(要回答的是"填没填")。现在只记 `keyProvided`,断言反过来钉住"不得出现 keyLength"。 **每次保存都写完整快照(A19:不再只写一半)** 设置页有**四处保存**(删除提供商 / 保存提供商 / 保存模型设置 / 保存尺寸),它们写的是**同一行配置**。此前每条路径各写自己那部分——「保存尺寸」只写 `{ size }`——于是存在"甲写一半、乙写另一半"的窗口:任何一次保存都可能把别的字段留在旧值上,用户在 A 处的改动可能被 B 处的保存抹掉。现在四处统一走同一个 `snapshotPatch`,一次写全本页拥有的五个字段(`providers` / `activeProviderId` / `modelRoutes` / `connectTimeoutSeconds` / `size`),**不存在只写一半的路径**。对应地,原有一条把它当成正确行为的断言(「且这一次只写 size」)已改为钉住完整快照,并新增一条**字段全集一致**的结构性防线:四条路径写入的键名集合必须完全相同且覆盖全部字段——将来有人再加一条只写一半的保存路径会立刻变红(红-绿验证过,把 `size` 从快照里拿掉后断言直接指出 `missing: ["size"]`)。 **依赖缺失时不再静默降级** `@deepseek-ai/dsh-tools` 解析不到时(它提供 `defineTool`,把参数编译成 JSON Schema),**不再**退化成恒等函数照常注册工具。实测过的原因:恒等兜底传进去的参数不是合法 JSON Schema,而 `ctx.tools.register` **照样接受、不抛错**——于是表现为「插件装好了、工具也在,但模型看不到参数说明、传错参数也不会被拦」,一个静默失效的工具比一个明确的报错糟糕得多。现在宁可不注册工具,并把原因写进启动自述;设置页、自诊断与 RPC 通道照常可用,用户看得到该修什么。 **图标是坏的 XML(README 破图的真正原因)** `icon.svg` 的注释里写了两个 CSS 变量名,而 **XML 规范禁止注释内出现连续两个连字符**——文件其实不是良构 XML。浏览器宽容所以在应用里正常显示,但 librsvg 与 GitHub 的 sanitizer 都拒绝它,表现为 README 顶部的 logo 变成破图。现在注释里不再出现双连字符,并在注释里写明这条禁忌。**几何数据一个字节没动**(跨文件一致性断言照旧通过)。 **功能调整** - **去掉「显示生图模型」一整套**:系统提示段、结果卡片里的 model 行、描述提示与相关断言一起撤除(保留生成中的秒级计时)。模型归属改为在对话里说明,不再由插件渲染那一行。 **文档与验收** - 中英双语 README(仓库门面 + 插件手册),仓库门面按 dsh-market 的骨架重排,并放上设置页的真实截图;顶层 logo 改用位图 `docs/logo.png`(512×512,由 icon.svg 渲染而来,与插件图标同源)。 - 两轮 README 改版,参照三个成熟 DSH 插件的写法:**仓库门面**补上「安装怎么确认装好了 / 三步开始 / 常见问题 / 安全与隐私 / 开发与验收」,把原先分开的「测试」「排查」并进新节以消重复;**插件手册**把「你能做什么」按主题分组,并补「目录结构」「运行时文件在哪」两张表——插件自己不往插件目录写任何东西,运行时数据全在 `$DSH_HOME`,这张表是用户排查时的第一现场。 - 新增 `verify-security` 套件(SSRF 拒收、回包上限、`baseUrl` 策略、**符号链接逃逸、日志总量封顶与轮转**)与 `verify-upgrade` 套件(升级后用户配置不丢);断言从 v0.2.0 的 380 条增至 **414** 条。 - `verify-client` 收尾显式退出:本套件把全局 `setInterval` 换成桩时钟、又加载浏览器半的模块,跑完后事件循环可能还挂着环境留下的 handle,导致"断言早就跑完了、脚本却不肯结束"——那看起来像死循环或失败。 ## v0.2.0 — 2026-10-10 > 历史记录:本版描述的「主模型超时(毫秒) / `fallbackAfterMs`」按响应时间换备用模型的机制,已在 **v0.2.1 整体删除**(见上)。这一节按当时的实际行为保留,不再代表当前版本。 修掉一轮多维审查里最要命的几处,并加上安全边界与对应验收。 **修掉的缺陷** - **路由指向已改名/删除的服务商时静默掉档**:旧实现找不到服务商就退回「当前生效服务商的 `imageModel`」,于是把**别的服务商的模型名**发到了这家的地址上,换回一句 `404 Model not exist`,真正的错因完全看不出来。真机上就是这么炸的(路由里是 `other`、卡片实际叫 `others`)。现在:没有可用备用 → 明确报错并点名那个 id、一个请求都不发;有可用备用 → 直接走备用并警告路由已失效。 - **主用构造期失败导致备用永不到达**:主用缺地址/缺凭据时旧实现在解析备用之前就抛错,配了备用也从不上场。现在会把失败原因连同备用一起处理。 - **`test` / `models` 用 B 的密钥打 A 的地址**:地址此前会回退到「当前生效服务商」,与密钥配对错位。现在地址**不回退**:只填密钥不填地址直接报错。 - **`fetchResilient` 从没把 signal 交给 fetch**:取消与超时传不到网络层,"去掉信号重试"名不副实。 - **双端归一已实质漂移**:客户端补上 `baseUrl` 尾斜杠、模型名与模型列表的 trim;`fallbackAfterMs` 两端统一为只接受正整数(此前 Host 认浮点、界面会把浮点洗成默认值)。 - **浮层里按 Esc 会连浮层一起关**:只展开下拉时按 Esc 会把菜单和整张卡片一起关掉,丢掉刚填的 API Key 与拉回来的模型列表。 **新增的安全边界** - 服务商**返回的图片地址**只允许 `http` / `https`,并拒绝环回与私有网段(云元数据 `169.254.169.254`、`10.x`、`192.168.x` 等),下载限时 15 秒、限长 20 MiB。 - 生图接口回包正文上限 32 MiB,且正文读取可被取消(此前"响应头一到就裸奔")。 - 明确区分两类地址:**对方给的地址**严格拦私网;**用户自己填的接口地址**允许本机(本地生图服务、本地 mock 都是正当用法),只校验协议。 **主模型超时的语义修正** `fallbackAfterMs`(设置页「主模型超时」,默认 90000)改为**从"请求真正发出"之后起算**,DNS/TCP/TLS 的耗时不再计入。起因是一次实测:跨境到某服务商,请求发出只用了 381ms、而响应头要 60.8 秒,旧实现把这 381ms 也算进"服务商慢"的账上,甚至会出现"请求还没送到就判超时"。超时后还会自动探活一次,把"服务商挂了"与"服务商在慢慢画"分成两句可读的话。 **文档与验收** - 中英双语 README(仓库门面 + 插件手册),仓库门面按 dsh-market 的骨架重排。 - 新增 `verify-security` 套件(SSRF 拒收、回包上限、`baseUrl` 策略)与 `verify-upgrade` 套件(升级后用户配置不丢);断言从 94 条增至 **380** 条。 - 采用 MIT 许可。 ## v0.1.0 — 2026-10-10 首个可用版本:`image_generate` / `image_edit` 两个工具、多服务商配置、模型路由(生图/修图 × 主用/备用)、设置页自绘下拉、Web 界面测试连接与拉取模型、自定义工具卡片、三份自诊断、双端一致的凭据名派生。