@dsh-workbench/core 0.3.8 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,7 @@ dsh web (:3080) dsh workbench (:3081)
23
23
 
24
24
  | 要有 | 为什么 | 怎么有 |
25
25
  | --- | --- | --- |
26
- | `dsh` | 本体。本包在 `0.1.7-rc.2` 上验过 | `npm i -g @deepseek-ai/dsh` |
26
+ | `dsh` | 本体。本包在 `0.2.1-rc.2` 上验过;**更旧的会被拒绝**(`engines.dsh`,旧到不认识它的 dsh 由启动器当场拒绝并给升级命令)—— DIY 模式是从那一代 dsh 的 preset 清单派生的,旧一代它会整个不出现且不报错 | `npm i -g @deepseek-ai/dsh@latest` |
27
27
  | `node` + `pnpm` | dsh 的 `plugin` 子命令是**转发给 pnpm** 的;没有 pnpm 会直接报 `dsh: pnpm was not found` | 各自装 |
28
28
  | 跑过一次 `dsh web` | `setup` 拿 `~/.dsh/profiles/web` 当模板(**bundle 清单**:这台机器上装了哪些 bundle),也是「配置同步」的默认来源。没有它会**明确报错**,不会静默建出半个 profile | `dsh web`,起来就行,然后 Ctrl-C |
29
29
 
@@ -111,6 +111,7 @@ npx @dsh-workbench/core # ② 起工作台,默认 :3081
111
111
  | 一切正常,但左栏是出厂样子、右边没有面板 | 工作台插件在 Settings 里被关了(见上一条 ⚠️)。**重启之后**启动器不会再让你拿到这种实例:它读到 `dsh.profile.bundles` 里没有它就直接拒绝启动,并打印 `./bin/dsh-workbench setup` |
112
112
  | 模型列表里只有出厂的几个、没有自己配的供应商 | 新装的 profile 不带设置(ADR-0044):设置 → 「配置同步」→ 选来源 → 勾 `llm-` 那几行 → 同步(即生效)|
113
113
  | 「配置同步」里某一行说 `@x 还没装` | 那一行点名的包不在这个 profile 的 `node_modules` 里:`dsh plugin --profile workbench add @x`(或在模块市场装),(装完 dsh 会自行重组;它报 `restartReason` 时才重启)|
114
+ | 左栏没有「工作台DIY」那一项、模式下拉里也没有「工作台 DIY」 | 多半是 dsh 太旧(DIY 模式是从 **dsh 0.2.1-rc.2** 的 preset 清单派生的;旧一代那个 preset 挂不起来,而 dsh 的模式选择器**只列挂得起来的** ⇒ 整个不见且不报错)。**启动体检会把它摆出来并停在那一页**(「检查 DIY 模式 · 挂不起来」+ 缺哪几行 + 升级命令 + 一颗「先进入工作台」);启动器更早一步:dsh 太旧就直接拒绝启动/安装并打印 `npm i -g @deepseek-ai/dsh@latest`,装完**重启工作台**即可。想自己核对是哪一行挂不起来:`dsh` 的 设置 → 「Agent presets」里那一行会带红标与原因 |
114
115
 
115
116
  排障全表在仓库的 [`docs/OPERATIONS.md`](https://github.com/code-farmer-i/dsh-workbench/blob/main/packages/workbench/docs/OPERATIONS.md);
116
117
  把工作台装到别人机器上的前置清单见 [`docs/HANDOFF.md`](https://github.com/code-farmer-i/dsh-workbench/blob/main/packages/workbench/docs/HANDOFF.md)。
package/bin/dsh-workbench CHANGED
@@ -15,7 +15,9 @@
15
15
  # · **仓库副本**(这个包落在一个 git 工作树里):开发用。bundle 以 link 方式装本目录,
16
16
  # 改源码立刻生效(配合 `pnpm run dev`)。
17
17
  # · **安装包**(从内网源下下来的):`setup` 把 **registry 上那个包** 装进 profile。
18
- # 判据是「git 顶层在不在」—— `npm pack` 的产物里不含 .git(见 package.json 的 files)。
18
+ # 判据是「**这个包的 package.json 被那个 git 顶层跟踪**」—— `npm pack` 的产物里不含 .git
19
+ # (见 package.json 的 files);只问"顶层在不在"不够:装出来的那份完全可能落在某个仓库里
20
+ # (`$HOME` 是 dotfiles 仓库、而 npm 前缀就在 `$HOME` 下,实测踩过 —— 症状见下面 GIT_TOP 那段)。
19
21
  # ⚠️ 不能判 `$REPO_DIR/.git`:workspace 之后 .git 在**仓库根**,不在这个包里(实测踩过,
20
22
  # 判错的症状是"仓库副本却去源上装",改源码不再生效,而且不报错)。
21
23
 
@@ -38,12 +40,76 @@ while [ -L "$SELF" ]; do
38
40
  done
39
41
  REPO_DIR="$(cd "$(dirname "$SELF")/.." && pwd -P)"
40
42
  GIT_TOP="$(git -C "$REPO_DIR" rev-parse --show-toplevel 2>/dev/null || true)"
43
+ # `rev-parse --show-toplevel` 只说明"**某个祖先目录**是个仓库"—— 装出来的那份完全可能刚好落在
44
+ # 某个仓库里:最常见的是 `$HOME` 本身就是 dotfiles 仓库,而 npm 的前缀(`~/.nvm/...`、
45
+ # `~/.npm-global`…)就在 `$HOME` 下。那会把"装出来的那份"当成仓库副本,以 link 装进 profile:
46
+ # 市场里工作台那一行会说「这份是本仓正在开发的那一份」,而 `npm i -g …@latest` 之后 profile
47
+ # 指向的东西还会悄悄变。所以还得证明**这份 package.json 本身被那个仓库跟踪**(仓库副本才有的事;
48
+ # 与 seed-workshop.sh 那条"工作树里真有 packages/workbench + packages/module-tools"同旨)。
49
+ if [ -n "$GIT_TOP" ] && ! git -C "$REPO_DIR" ls-files --error-unmatch package.json >/dev/null 2>&1; then
50
+ GIT_TOP=""
51
+ fi
41
52
 
42
53
  if ! command -v dsh >/dev/null 2>&1; then
43
54
  echo "dsh-workbench: PATH 上没有 dsh。先装:npm i -g @deepseek-ai/dsh" >&2
44
55
  exit 1
45
56
  fi
46
57
 
58
+ # ── 硬门禁:dsh 太旧就别起(DIY 模式会整个不见,而且一句错都不报)────────────
59
+ #
60
+ # DIY 模式就是 `preset/diy.patch.yml` 那一行 agent preset,而它是**从 dsh 出厂那份
61
+ # `standard.patch.yml` 派生的**(scripts/gen-diy-preset.mjs)—— 所以它跟的是**派生那一刻的
62
+ # dsh**。dsh 旧到那份清单里有几个包它根本没有时(实测 0.2.0-rc.2 缺
63
+ # `@deepseek-ai/dsh-tool-schedule`),preset 挂不起来;dsh 的模式选择器**只列挂得起来的**
64
+ # (healthy presets only),于是「工作台 DIY」在用户面前整个消失,界面与终端都不吭声。
65
+ # 同一代 dsh 0.2.0 的 `uiWorkspace.startSession()` 也**不收** `agentPreset`(0.2.1-alpha.3 才收),
66
+ # 所以就算 preset 挂上了,「造一个模块」也落不到 DIY 模式 —— 这一档没有"少一把工具"的降级空间。
67
+ #
68
+ # 为什么门禁写在启动器、而不只写 package.json 的 `engines.dsh`:
69
+ # engines.dsh 只有 **0.2.1-alpha.4 起**的 dsh 才读(见 HANDOFF §八),而这台机器上那份 dsh
70
+ # 恰恰可能就是旧到不认识的(0.2.0-rc.2 只读 peerDependencies,而 peer 不能写 ——
71
+ # pnpm 的 auto-install-peers 会把整套 dsh 拖进 profile)。所以旧 dsh 由这里兜。
72
+ #
73
+ # 下限只有一处真相:package.json 的 engines.dsh。这里只读它,别在这儿另写一个版本号。
74
+ DSH_FLOOR="$(WB_MANIFEST="$REPO_DIR/package.json" node -e 'const p = require(process.env.WB_MANIFEST); const e = p.engines ?? {}; process.stdout.write(typeof e.dsh === "string" ? e.dsh : "");' 2>/dev/null || true)"
75
+ DSH_VERSION="$(dsh --version 2>/dev/null | tr -d '[:space:]' | sed 's/^v//' || true)"
76
+
77
+ if [ -n "$DSH_FLOOR" ] && [ -n "$DSH_VERSION" ]; then
78
+ # `>=X.Y.Z[-pre]` 一档:与 dsh 自己那条预检同一口径(semver + includePrerelease)。
79
+ # 认不出的下限形状就不拦 —— 这条是给用户的诊断门,权威仍是 dsh 自己的预检。
80
+ DSH_FLOOR="$DSH_FLOOR" DSH_VERSION="$DSH_VERSION" node -e '
81
+ const floor = /^>=\s*(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec((process.env.DSH_FLOOR ?? "").trim());
82
+ const got = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec((process.env.DSH_VERSION ?? "").trim());
83
+ if (floor === null || got === null) process.exit(0);
84
+ const want = { nums: [+floor[1], +floor[2], +floor[3]], pre: floor[4] === undefined ? [] : floor[4].split(".") };
85
+ const have = { nums: [+got[1], +got[2], +got[3]], pre: got[4] === undefined ? [] : got[4].split(".") };
86
+ for (let i = 0; i < 3; i += 1) {
87
+ if (have.nums[i] !== want.nums[i]) process.exit(have.nums[i] > want.nums[i] ? 0 : 1);
88
+ }
89
+ if (have.pre.length === 0) process.exit(0);
90
+ if (want.pre.length === 0) process.exit(1);
91
+ for (let i = 0; i < Math.max(have.pre.length, want.pre.length); i += 1) {
92
+ const a = have.pre[i];
93
+ const b = want.pre[i];
94
+ if (a === undefined) process.exit(1);
95
+ if (b === undefined) process.exit(0);
96
+ const an = /^\d+$/.test(a);
97
+ const bn = /^\d+$/.test(b);
98
+ if (an && bn) { if (+a !== +b) process.exit(+a > +b ? 0 : 1); continue; }
99
+ if (an !== bn) process.exit(an ? 1 : 0);
100
+ if (a !== b) process.exit(a > b ? 0 : 1);
101
+ }
102
+ process.exit(0);
103
+ ' || DSH_FLOOR_GUARD=$?
104
+ if [ "${DSH_FLOOR_GUARD:-0}" -eq 1 ]; then
105
+ echo "dsh-workbench: 这台机器上的 dsh 是 ${DSH_VERSION},这份外壳要 ${DSH_FLOOR}。" >&2
106
+ echo " 低于它时 DIY 模式(会话里的「工作台 DIY」)挂不起来,而 dsh 的模式选择器只列挂得起来的" >&2
107
+ echo " —— 它会**整个不出现**,不报错。所以这里直接拒绝启动。" >&2
108
+ echo " 升级 dsh(再重启一次工作台): npm i -g @deepseek-ai/dsh@latest" >&2
109
+ exit 1
110
+ fi
111
+ fi
112
+
47
113
  pkg_version() {
48
114
  node -p "require('$REPO_DIR/package.json').version" 2>/dev/null || echo "0.0.0"
49
115
  }