fix(cli): plugin UX — anchor relative specs, reconcile by installed state, guide blocked git builds

- Relative path specs (., ../plugin, file:/link: forms) anchor to the
  invoking directory before forwarding: pnpm's cwd is the profile dir, so a
  bare 'add .' from a plugin checkout used to self-link the profile (exit 0,
  nothing installed). Bare paths stay bare and prefixed specs keep their
  prefix, preserving pnpm's link-vs-copy semantics.
- dsh.plugins reconciles against the INSTALLED state on every successful
  pnpm run, not the dependency diff: an update whose new version gains
  dsh.patch activates the layer; a version that drops it (or a removal)
  deactivates it. Template bundles are never touched.
- A failed pnpm run now names the profile directory, and a git-spec failure
  explains pnpm >=10's prepare-script block with a pointer at the profile's
  pnpm-workspace.yaml allowBuilds (turtle-ui's prepare-based git install is
  the reference consumer); reference README documents all three.
This commit is contained in:
Turtle
2026-08-06 12:16:32 +08:00
parent 65770325e7
commit 52d7515936
5 changed files with 149 additions and 28 deletions

View File

@@ -25,7 +25,7 @@ dsh --profile web --patch ./extra.yml --dump-config
## 插件管理
`dsh plugin --profile <name> <args...>` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base`),然后以 profile 目录为工作目录,把 `<args...>` 原样转发给 `pnpm``add``remove``why``update` 及其他所有 pnpm 子命令都照常可用pnpm 必须在 PATH 上。`add` 成功后,manifest 中声明 `"dsh": { "patch": "./cordis.patch.yml" }` 的包会被追加到 `dsh.plugins`(最后一层);没有该声明的包保持为普通依赖并打印警告。`remove` 把包从 `dsh.plugins` 中移除
`dsh plugin --profile <name> <args...>` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base`),然后以 profile 目录为工作目录,把 `<args...>` 转发给 `pnpm``add``remove``why``update` 及其他所有 pnpm 子命令都照常可用pnpm 必须在 PATH 上。相对路径 spec`.``../plugin` 及其 `file:`/`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout而不是 profile。每次成功运行后`dsh.plugins` 都会与已安装状态对齐:每个解析到 manifest 中声明 `"dsh": { "patch": "./cordis.patch.yml" }` 的包的依赖加入层栈(因此让包获得该声明的 `update` 会将其激活),没有 patch 的依赖保持为普通依赖并给出一次性警告,已移除的依赖则退出层栈
```sh
dsh plugin --profile tui add github:deepseek-harness/turtle-ui
@@ -33,6 +33,8 @@ dsh plugin --profile tui remove turtle-ui
dsh --profile tui
```
Git 托管、随附源码的插件在安装期间通过其 `prepare` 脚本构建,而 pnpm ≥10 在消费方允许之前会阻止该脚本:首次 `add` 会失败并给出 pnpm 的 `allowBuilds` 提示(以及 dsh 指向该 profile 的 `pnpm-workspace.yaml` 的指引);把打印出的键复制到那里并重新运行即可。安装已构建的 tarball 或本地 checkout 不需要任何允许。
## Web 别名
`dsh web``--profile web` 的硬编码别名,并额外接受 Web flag 系列。`--host``--port``--workspace-root` 和可重复的 `--trusted-host` 值会成为作用在组合行之上的 patch负责这些值的插件 schema 会在启动时验证它们。`--dev` 把 web-runtime 行切换到开发模式并插入客户端插件 HMR热模块替换接收器若要无刷新更新客户端 bundle还需单独运行 `pnpm run dev:web` watcher。