# dsh-fastswitch 让 DeepSeek Harness 的**会话切换**变快,只做两件事,都可单独关闭。 > English: [README.md](./README.md) ## 它解决什么 切换会话时,DSH 会重新向 Host 要一份「首屏历史」。这段历史有一个写死的窗口——至少 50 条消息——在长对话里这一帧能达到 **2 MB**,而这正是切换时那几秒的等待来源。 同时,页面初次构建时,几个组件会各自去拉同一批只读目录接口:`session/modelCatalog` 6 次、`credentials/describe` 7 次、`agentPresets/list` 6 次、`cotTranslation/limits` 3 次。它们没有去重,也没有缓存。 dsh-fastswitch 在浏览器里对这两件事各做一处改动: 1. **首屏窗口可配置** —— 把外发的 `session/follow` 请求里的 `turnWindow.minMessages` 从 50 改小(默认 20)。Host 只校验 `0 < minMessages <= maxMessages`,所以这是协议允许的请求,不是打补丁。凡是要「加载更早」的分页请求(200 条)一律不动。 2. **只读 RPC 去重 + 缓存** —— 包装 `window.fetch`,对只读目录接口做 5 分钟结果缓存,并发调用合并为一次实际请求。 ## 实测 同一台机器、同一个页面、同一段会话: | 指标 | 默认 | 装上之后 | |---|---|---| | 首屏快照(一次长会话) | 2,040,432 B | **1,054,070 B** | | `session/modelCatalog` | 6 次 | **1 次** | | `credentials/describe` | 7 次 | **1 次** | | `agentPresets/list` | 6 次 | **1 次** | | 首屏请求总数 | 52 | **33** | 数字来自一次真实测量,取决于会话长度与浏览器缓存状态,不是常量。 ## 安装 在插件市场里搜索 **fastswitch**,或直接: ```sh dsh plugin --profile web add github:guofug/dsh-fastswitch ``` 装完**重启或等 HMR 重载**一次生效。 ## 配置 全部通过 `localStorage`,无需改配置文件: | 键 | 默认 | 说明 | |---|---|---| | `dsh-fastswitch` | — | 设为 `off` 关闭全部功能 | | `dsh-fastswitch-window` | `20` | 首屏窗口条数;`0` 表示不改写 | | `dsh-fastswitch-ttl` | `300000` | 结果缓存时长(毫秒);`0` 表示不缓存 | | `dsh-fastswitch-merge` | `800` | 并发合并窗口(毫秒) | 例: ```js localStorage.setItem('dsh-fastswitch-window', '10') // 更激进 localStorage.setItem('dsh-fastswitch', 'off') // 临时全关 ``` ## 怎么确认它在工作 ```js window.__dshFastswitch // { installed: true, // ws: { rewritten: 3, untouched: 40 }, // fetch: { calls: 51, hits: 10, dedup: 8, bypass: 33 } } ``` - `ws.rewritten` 每切换一次会话应 +1; - `fetch.hits + fetch.dedup` 就是省掉的请求数。 ## 边界 - **只影响浏览器**。终端、SDK、ACP、其他客户端不受影响。 - **不改 DeepSeek Harness 的任何文件**,也不改 Host。窗口是通过改写外发请求实现的,缓存是浏览器侧的 `fetch` 包装;卸载插件即恢复原行为。 - 不含「会话停泊缓存」(把已打开的会话留在内存里以便瞬间切回)。那需要改动 Session 生命周期内部实现,跨版本容易碎,本项目有意不做。 - 缓存只覆盖**只读**目录接口。任何写操作、流式响应、鉴权接口都不在缓存范围内。 ## 兼容性 - 面向 `dsh ^0.2.1-rc.2`(见 `engines.dsh`)。 - 两处包装都做了幂等保护,HMR 重载不会重复叠加。 - 任何一处包装失败都不会破坏页面:失败即跳过,功能降级为原生行为。 ## 许可 MIT