# dsh-plan-build-switch

English | [中文](README.zh.md)

为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) web（`dsh --profile web`）设计的 Plan/Build 模式切换插件。在聊天输入框工具行提供中性配色的 **Plan | Build** 分段切换器、可自定义的全局快捷键，以及完全自定义的 plan 指示——官方「Plan ✕」芯片会被遮蔽，界面中永远不会出现重复或撞色的 plan 控件。

## 功能

- **分段切换器**：位于输入框工具行，高亮当前模式，点击（或按快捷键）切换。Plan = 智能体只规划；Build = 默认执行模式。
- **可自定义快捷键**：默认 `Alt+P`；在 **设置 → General →「Plan 切换快捷键」** 点击胶囊按钮后按下新组合键即可修改（Esc 取消）。任意组合键均可录制，包括裸键。按浏览器保存在 `localStorage`（`dsh.planBuildSwitch.shortcut`）。
- **完全自定义的 plan 表面**：以 priority `-1` 在官方 `conversation.input.plan` 座位注册遮蔽项，官方琥珀色「Plan ✕」芯片不再渲染；本控件是唯一的 plan 指示，使用主题 token 中性配色。
- **无布局抖动**：状态槽固定宽度、禁用态不改颜色；点击段乐观高亮，实时 `plan` 投影无缝对齐。
- **打字安全**：无修饰键的快捷键在输入框内输入字符时不触发（裸 `P` 不会随每次打「p」切换）；Tab、方向键等非打字键任何位置立即生效。
- **双语**（中/英）：走 `planBuildSwitch` locale 命名空间。

## 环境要求

- DeepSeek Harness web profile（`dsh --profile web` 或 `dsh web`），内置 `@deepseek-ai/dsh-web-app` 浏览器插件名录的版本。

## 安装

前置条件：**PATH 上有 pnpm**（`dsh plugin` 会把参数转发给 profile 目录里的 pnpm）。用 `corepack enable` 或 `npm i -g pnpm` 安装。

### 从 npm 仓库安装

```sh
dsh plugin --profile web add dsh-plan-build-switch
```

这就是全部安装步骤：本包是 **profile bundle**（`dsh.bundle`），`dsh plugin` 会自动把它追加进 profile 的 `dsh.profile.bundles`，包内的 `cordis.patch.yml` 在启动时**自动插入插件行——无需手动加行**。

重启 `dsh web`（或 `dsh --profile web`）。安装后加载的页面自带一个极小的「名单探针」，模块启动图变化时**自动刷新页面**——重启/更新后打开的旧页面会自动加载切换器（首次安装仍需要一次手动 F5：安装前打开的页面没有探针）。

卸载：

```sh
dsh plugin --profile web remove dsh-plan-build-switch
```

### 发布前 / 离线（tarball 回退）

在仓库目录执行：

```sh
npm pack                        # 生成 dsh-plan-build-switch-<version>.tgz
dsh plugin --profile web add ./dsh-plan-build-switch-<version>.tgz
```

（`dsh plugin` 会把相对路径锚定到调用目录；bundle 自动合并逻辑同样生效。）

### 从 0.1.x 升级

0.1.x 是纯客户端模块，需要手动在 `cordis.patch.yml` 加行。升级后：

```sh
dsh plugin --profile web add dsh-plan-build-switch@0.2.0   # 提升依赖版本并自动追加 bundle
```

然后**删除你在 `cordis.patch.yml` 里手动加过的 `plan-build-switch` 行**（bundle 已提供），重启 `dsh web`。

### 常见错误对照

| 现象 | 原因 | 处理 |
|---|---|---|
| `pnpm failed in profile directory ...` + `404` / `ERR_PNPM_NO_MATCHING_VERSION` | 包尚未发布，或 npm 镜像未同步 | `pnpm config get registry` 检查镜像；等同步或改用上方 tarball 回退 |
| `pnpm not found on PATH` | 缺 pnpm | `corepack enable` 或 `npm i -g pnpm` |
| `[WARN] Issues with peer dependencies found` | **正常**：profile 运行时从 DSH shell 提供 peer 依赖（`autoInstallPeers: false`） | 忽略 |
| 安装成功但切换器不出现 | 未重启 dsh，或页面先于安装打开（无探针） | 重启 `dsh web`；手动刷新一次 |

## 使用

- 点击输入框工具行的 **Plan** / **Build**，或按快捷键（默认 `Alt+P`）。
- 当前模式段高亮；切换发生在回合进行中时，`…` 状态槽提示「下一轮生效」。
- 修改快捷键：打开 **设置**（侧栏底部）→ **General**，找到「**Plan 切换快捷键**」，点击胶囊按钮后按下新组合键。

## 行为说明

- 切换通过 `commands` Remote 执行宿主 `/plan` 与 `/plan off` 命令——与官方 plan 芯片同一条通道，由按会话隔离的 plan-mode 服务持有。
- 每次成功切换，plan-mode 服务会在会话日志注入一条切换旁白（每提交一次一条）；这是宿主行为，非本插件渲染。
- 快捷键偏好按浏览器保存（localStorage），不跨设备同步。

## 开发

```
src/
  index.js              node 半（纯 UI 插件，空 apply）
  client/
    index.js            插件入口：注册 + locale 字典
    mode-switch.js      输入框切换器组件
    shortcut.js         快捷键状态 + 组合键规范化
    settings-row.js     General 设置录制行
    styles.css          样式（构建时内联进 bundle）
build.mjs               零依赖构建 → lib/（npm pack 时经 prepack 自动执行）
smoke.mjs               bundle 物化 + 注册/渲染冒烟测试
```

```sh
node build.mjs          # 由 src/ 重新生成 lib/
node smoke.mjs          # 模拟浏览器加载器物化 lib/client.js 并验证注册与渲染
npm pack                # 生成可发布 tarball
```

## 发布

```sh
npm login
npm publish
```

MIT 许可。发布前把 `package.json` 的 `repository` 字段改为你的仓库地址。

## License

MIT
