docs: record the 0.1.7-rc.1 adaptation and resync the user docs
New design record `docs/plans/2026-09-23-dsh-0.1.7-rc.1-adaptation.md` (method, the version-bump-only delta, the code-card break and the mermaid regression it exposed, the over-yield recovery, the live 3080 upgrade with its boot-log findings, and the evidence — including the note that the mount lane first ran against a stale tarball because `e2e_resolve_tarball` picks the newest existing one instead of packing). AGENTS.md §3 gains the rc.1 rules: the boot-time peer preflight (a new §3.4 item 12) with its four gotchas, the vendor hoist lesson, and the code-card/toolbarLabels contract. Two claims are corrected while we are here: the guide's four-entry description cap was attributed to rc.1 but `GuideBody.tsx` and the host's terminal guide entry are byte-identical across alpha.1 / alpha.2 / rc.1, and the icon surface is 25 named imports plus a type-only `IconProps`, not 26. README / README_EN / guide: version, badges, peer floor, the pinned-DSH advice (`alpha` is now 0.1.7-alpha.2 while rc.1 rides `next`), the reduced refusal list, and the correction that npm `latest` is 0.1.5-rc.3.
This commit is contained in:
@@ -19,13 +19,13 @@
|
||||
|
||||
「npm 打包 → 真实挂载 → 无头渲染」门禁(证明打包产物在真实 DSH 挂载后不 crash):`pnpm build && pnpm pack` 产 tarball → `scripts/e2e-mount.sh` 装进全新 scratch profile(`dsh plugin --profile web add <tarball>`)并启动真实 `dsh web`(keyless,`--port 0`)→ `tests/e2e/mount.e2e.ts`(Playwright)断言 `[data-dsh-better-sidebar]` 挂载、无错误条/pageerror/console 错误,展开 DSH 原生右侧栏后经其 guide 页逐个打开本插件贡献的 tab 类型**以及宿主自己的终端条目**(必须恰好 1 条——多于 1 条即意味着插件又在遮蔽宿主),再经插件文件树(原生 `files` kind 接管)打开 seed 文件强制加载 editor chunk(`client-editor.js`),并跑 mermaid / README 预览与 sidechat 宿主路由烟测。**`browser` 不在这个清单里,而是显式断言缺席**:DSH 0.1.7 的 `ui-sidebar-browser` 只在 desktop profile 挂载(`web-app` 的 patch 里 `disabled: ctx.get('profileContext')?.name !== 'desktop'`),lane 全走 web profile,钉住「没有」比默默放过更能暴露宿主立场的变化。
|
||||
|
||||
本地:`pnpm build && pnpm pack && pnpm exec playwright install chromium && pnpm test:mount`(`DSH_CMD` 未设时 `scripts/e2e-common.sh` 回退的 npx 钉版是 `DSH_NPX_SPEC`,默认 `@deepseek-ai/dsh@0.1.7-alpha.1`——**不钉就会解析 `latest`,而 `latest` 仍是插件已不支持的 0.1.5 线**)。CI 钉 `@deepseek-ai/dsh@0.1.7-alpha.1`(npm `alpha`;`latest` 仍是 0.1.5-rc.2;peer 下限 `^0.1.7-alpha.1`)。该步骤用 `NODE_OPTIONS=--max-old-space-size=4096`:钉版自身的传递依赖是浮动 `^` 范围,上游分阶段发布预发布版时(rc.2 于 2026-09-10 的 14:43–14:57 逐包上线)npm 会组出混合 peer 图,3062 条 ERESOLVE 后 OOM(exit 134);另一个失败模式是对未发布兄弟包 ETARGET,靠「钉一个已完整发布的版本」修掉。**不要加 `--legacy-peer-deps`**:它跳过的正是全局安装必须提供的 peer,`@deepseek-ai/dsh-app-boot` 在 boot 时 require 的 `@deepseek-ai/cordis-plugin-group` 是 peer 而非 dependency,加了它 CLI 直接 `ERR_MODULE_NOT_FOUND`(实测过一次,见 rc.2 计划 C 节)。`ci-windows` 的 `Test` 跑 `pnpm test:windows`(`--maxWorkers=1`)而非 `pnpm test`——多个 spec 真起进程(`smoke` / `install-powershell` / `git`),2 核 runner 上并行起 ConPTY / 冷启 `powershell.exe` 是超时与 worker 静默死亡的放大器;`vitest.config.ts` 的全局 `testTimeout: 15_000`(默认 5000 在 Windows 上对真起进程的用例太低,三个不同文件先后翻车)是配套的一半。e2e spec 命名 `*.e2e.ts` + vitest `exclude` 双保险;**改 `exclude` 必须保留默认排除项**(exclude 整体替换默认值)。
|
||||
本地:`pnpm build && pnpm pack && pnpm exec playwright install chromium && pnpm test:mount`(`DSH_CMD` 未设时 `scripts/e2e-common.sh` 回退的 npx 钉版是 `DSH_NPX_SPEC`,默认 `@deepseek-ai/dsh@0.1.7-rc.1`——**不钉就会解析 `latest`,而 `latest` 仍是插件已不支持的 0.1.5 线**)。CI 钉 `@deepseek-ai/dsh@0.1.7-rc.1`(**pin 一律写精确版本号,不要写 `@alpha`**:rc.1 上线时 npm `alpha` 指的是 **0.1.7-alpha.2**,rc.1 走的是 `next`;`latest` 仍是 0.1.5-rc.3;peer 下限 `^0.1.7-rc.1`)。该步骤用 `NODE_OPTIONS=--max-old-space-size=4096`:钉版自身的传递依赖是浮动 `^` 范围,上游分阶段发布预发布版时(rc.2 于 2026-09-10 的 14:43–14:57 逐包上线)npm 会组出混合 peer 图,3062 条 ERESOLVE 后 OOM(exit 134);另一个失败模式是对未发布兄弟包 ETARGET,靠「钉一个已完整发布的版本」修掉。**不要加 `--legacy-peer-deps`**:它跳过的正是全局安装必须提供的 peer,`@deepseek-ai/dsh-app-boot` 在 boot 时 require 的 `@deepseek-ai/cordis-plugin-group` 是 peer 而非 dependency,加了它 CLI 直接 `ERR_MODULE_NOT_FOUND`(实测过一次,见 rc.2 计划 C 节)。`ci-windows` 的 `Test` 跑 `pnpm test:windows`(`--maxWorkers=1`)而非 `pnpm test`——多个 spec 真起进程(`smoke` / `install-powershell` / `git`),2 核 runner 上并行起 ConPTY / 冷启 `powershell.exe` 是超时与 worker 静默死亡的放大器;`vitest.config.ts` 的全局 `testTimeout: 15_000`(默认 5000 在 Windows 上对真起进程的用例太低,三个不同文件先后翻车)是配套的一半。e2e spec 命名 `*.e2e.ts` + vitest `exclude` 双保险;**改 `exclude` 必须保留默认排除项**(exclude 整体替换默认值)。
|
||||
|
||||
---
|
||||
|
||||
## 3. DSH 0.1.7-alpha.1 适配要点(0.1.7-alpha.1+ 基线)
|
||||
## 3. DSH 0.1.7 适配要点(0.1.7-rc.1+ 基线)
|
||||
|
||||
**v0.21.0-alpha.1 起仅支持 DSH 0.1.7-alpha.1+**(peer 下限 `^0.1.7-alpha.1`,CI 钉 `@deepseek-ai/dsh@0.1.7-alpha.1`)。**下限必须动**:semver 的预发布规则要求比较子与候选版本同 `[major,minor,patch]` 元组,`^0.1.6-alpha.2` 在数学上**永远容纳不下任何 `0.1.7-*` 预发布版**(实测 `0.1.7-alpha.1` 对 `^0.1.6-alpha.2` / `>=0.1.6-alpha.2` 全是 false),而 `^0.1.7-alpha.1` 天然容纳 0.1.7 的 alpha/rc 全线。**支持线取舍**:0.1.6-alpha.2 及更早的用户停留在 **v0.19.1**(0.20.0 这一版从未发布到 npm)——本版破坏面足够大(`dsh-settings` 整体重写、26 个图标具名导出消失、会话格式 v3→v4),按本仓库先例不写运行时兼容层。发版:release.yml 按版本号是否含 `-` 自动选 `alpha`/`latest` dist-tag(`0.21.0-alpha.1` 含 `-` → `alpha`;npm `latest` 仍是 0.19.1)。
|
||||
**v0.21.0-rc.1 起仅支持 DSH 0.1.7-rc.1+**(peer 下限 `^0.1.7-rc.1`,CI 钉 `@deepseek-ai/dsh@0.1.7-rc.1`)。**下限必须动**:semver 的预发布规则要求比较子与候选版本同 `[major,minor,patch]` 元组,`^0.1.6-alpha.2` 在数学上**永远容纳不下任何 `0.1.7-*` 预发布版**(实测 `0.1.7-alpha.1` 对 `^0.1.6-alpha.2` / `>=0.1.6-alpha.2` 全是 false),而 `^0.1.7-rc.1` 天然容纳 0.1.7 的 rc/正式全线。**下限从 alpha.1 收到 rc.1 是刻意的**:`0.21.0-alpha.1` 从未发布到 npm(`latest` 仍是 v0.19.1,npm 上没有 alpha.1 的下载量),而修掉 rc.1 的 `DiffBlockLabels` 之后,同一份代码在 alpha.1 上会**崩**——alpha.1 的 `DiffBlock` 仍读上游已删除的 `labels.files`。声明与「真机验证过的宿主」一致,比声明一条跑不通的支持线更安全;rc.1 起 peer 还是**启动期硬约束**(见 §3.4 第 12 条),声明过宽的代价从「可能报错」变成「静默不加载」。**支持线取舍**:0.1.6-alpha.2 及更早的用户停留在 **v0.19.1**(0.20.0 这一版从未发布到 npm)——本版破坏面足够大(`dsh-settings` 整体重写、25 个图标具名导出消失、会话格式 v3→v4),按本仓库先例不写运行时兼容层。发版:release.yml 按版本号是否含 `-` 自动选 `alpha`/`latest` dist-tag(`0.21.0-rc.1` 含 `-` → `alpha`;npm `latest` 仍是 0.19.1)。
|
||||
|
||||
### 3.1 本版四类硬破坏(都是「不修就崩或静默失效」)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
- `viewOf()` = `describe({redactSecrets:true}).find(d => d.ns === ns)`;写入 = `update(ns, patch, expectedRevision)`(`SettingsConflictError` 仍导出、构造签名未变,409 分支保留)。
|
||||
- `ctx.effect(() => settings.configure({ auto: false }, ctx.fiber))` —— 官方 README 给「自带设置页的插件」的写法;不这么做 Settings 会把同一批字段渲染两遍。
|
||||
- **`settings/document-updated` 监听不到,不要写**:它在 settings 服务自己的 context 上 `emit`,而 cordis 的事件只向上冒泡到该 ctx 的祖先,插件的 fiber 是兄弟。本插件改用「客户端每次重新读取表单时重新求值」覆盖同样的触发点(`settingsFace.get()` 里跑门控同步)。
|
||||
2. **`ui-primitives` 图标整族改名**:`Icon<Name><14|16>` → `Icon<Name>Regular`(1px 描边)/ `Icon<Name>Medium`(1.3px)。0.1.6 的 81 个 `export const Icon*` 在 0.1.7 变成 184 个,**旧的尺寸后缀名一个不剩**(`git grep -c Outline16 <tag> -- packages/client/ui-primitives/src` = 0)。插件 26 个具名导入消失、17 个文件受影响。**失败模式是 render 期而不是 load 期**:插件 client bundle 是 CJS + external,产物是裸属性读,缺导出 = `undefined` → React 抛 `Element type must be invalid`,不是 ESM link error。**改名必须同时钉回尺寸**:0.1.6 的 `IconXxx14` 默认 `size = 14`,0.1.7 的 `XxxRegular` 一律默认 16,所以原先依赖 14px 默认值的 5 处(`TabBar.tsx` / `Sidebar.tsx` / `FileTree.tsx` 的 `IconCloseFillRegular`、`SubagentView.tsx` 两处 `IconRefreshOutlineRegular`)必须显式传 `size={14}`,否则**静默变大 2px**。另有 `StateDot` 的 ongoing 态被整图重画(10px 像素矩阵 → 14px 圆环 spinner,默认尺寸 `10 → 14`),签名兼容故无编译错误;插件选择跟随宿主观感。
|
||||
2. **`ui-primitives` 图标整族改名**:`Icon<Name><14|16>` → `Icon<Name>Regular`(1px 描边)/ `Icon<Name>Medium`(1.3px)。0.1.6 的 81 个 `export const Icon*` 在 0.1.7 变成 184 个,**旧的尺寸后缀名一个不剩**(`git grep -c Outline16 <tag> -- packages/client/ui-primitives/src` = 0)。插件 25 个 icon 具名导入消失、17 个文件受影响。**失败模式是 render 期而不是 load 期**:插件 client bundle 是 CJS + external,产物是裸属性读,缺导出 = `undefined` → React 抛 `Element type must be invalid`,不是 ESM link error。**改名必须同时钉回尺寸**:0.1.6 的 `IconXxx14` 默认 `size = 14`,0.1.7 的 `XxxRegular` 一律默认 16,所以原先依赖 14px 默认值的 5 处(`TabBar.tsx` / `Sidebar.tsx` / `FileTree.tsx` 的 `IconCloseFillRegular`、`SubagentView.tsx` 两处 `IconRefreshOutlineRegular`)必须显式传 `size={14}`,否则**静默变大 2px**。另有 `StateDot` 的 ongoing 态被整图重画(10px 像素矩阵 → 14px 圆环 spinner,默认尺寸 `10 → 14`),签名兼容故无编译错误;插件选择跟随宿主观感。**rc.1 复查:`icons/index.tsx` 只新增了 `IconUsersOutline{Artwork,Regular,Medium}`,无删除、无改名,也没有任何既有 icon 的默认尺寸变化**(`export const` 187 → 189;`icons/props.ts` 与 `shared-artwork.tsx` 逐字未变)——上面这轮改名是 alpha.1 的历史账,不是 rc.1 的。**计数更正**:插件实际是 **25 个 icon 具名导入 + 1 个 type-only `IconProps`**(`tests/primitives-exports.spec.ts` 会实时提取导入面并与装好的包对照,数字写错它会先红)。
|
||||
3. **会话格式 v3 → v4**(`packages/session/session-format-v3-to-v4`):两处变化。
|
||||
- **`source.kind === 'plugin'` 被硬拒**(`message-sources.ts` 抛 `format v4 message requires a producer-owned source kind`),而插件的 sidechat 边界注入正是那个形状。改用 **`plugin:dsh-better-sidebar`**:与 DSH 自己的 v3→v4 迁移对历史行产出的 kind **逐字一致**(`producerKind()` 对未知插件名返回 `` `plugin:${plugin}` ``),所以新旧数据形状统一,**历史 sidechat 会话不会丢**。类型层面还需一条 `declare module '@deepseek-ai/dsh-llm'` 的 `MessageSourceMap` 增强(0.1.7 把它改成合并可扩展的封闭联合,没有共享 catch-all)。
|
||||
- **tool 结果消息重写**:`role: 'user'` + 嵌套 `type: 'tool-result'` 包装块 → `role: 'tool'` + **顶层** `content` / `isError` / `toolCallId`。插件的 4 个解析器原先靠 `candidate.type === 'tool-result'` 命中,在新形状下恒返回空串(**静默空白**)。现在四处都**同时接受新旧形状**(旧分支必须保留:历史日志里就是旧形状)。
|
||||
@@ -44,7 +44,8 @@
|
||||
### 3.2 本版的能力让出与收敛
|
||||
|
||||
5. **只读文件预览交还宿主**:0.1.7 的 `ui-sidebar-documentpreview` 长齐了 code / excel(xlsx,xls,csv,tsv) / office(宿主侧转 PDF) / pdf / image / html / markdown / text,并带缩放与**按目录自动刷新**。插件删掉自己的 `image` / `pdf` / `binary-download` 三个 viewer,并在 `src/client/native/index.ts` 的 `editor.canOpen` 里**拒绝认领**这些扩展名(`canOpen` 返回 false 就把地址让给内置 `text` 的 `fallback` 档):
|
||||
`xlsx xls xlsb xlt xltx xltm ods ots fods csv tsv pdf png jpg jpeg gif webp svg bmp ico avif doc docx dot dotx ppt pptx`
|
||||
`xlsx xls csv tsv fods pdf png jpg jpeg gif webp svg bmp ico doc docx ppt pptx`
|
||||
**rc.1 修掉了一处过度让出**:最初让出的 27 个里,有 9 个宿主**根本没有渲染器**(`xlsb xlt xltx xltm ots dot dotx avif`——`avif` / `ods` 在 `ui-sidebar-documentpreview/src/client/document/unviewable.ts` 的「已知二进制、无渲染器」表里直接走空状态,其余 7 个落回 text 兜底后按二进制判定失败,同样是空状态),点开只有一句「暂不支持预览」;而这些文件在让出**之前**是走插件兜底显示下载面板的——也就是说这是一处真实的用户可见回归。现已收回这 9 个,`fods` 继续让出(它是扁平 XML 文本,宿主 text 兜底会用纯文本显示,比下载面板有用)。`tests/native-surface.spec.ts` 现在**双向**钉住这条边界:宿主渲染的必须拒绝、宿主没有渲染器的必须认领。
|
||||
**保留在插件侧的三件**:`md/markdown`(自带渲染器,用户认为优于内置)、`html/htm`(自带沙箱预览 + `htmlViewerNoSandbox` / `htmlViewerDefaultUnsafe`,宿主没有这两个开关)、以及 `code` catch-all(**它是可编辑的 CodeMirror + 保存**,内置那几个是只读预览)。未知二进制(`.zip`/`.wasm`)仍走 `code` 认领 → 宿主 fsRead 判 binary → head 重匹配无 sniffer → `EditorHost.tsx` 的 `load.status === 'binary'` 兜底渲染下载面板,**功能不回归**。
|
||||
6. **宿主 `browser` kind 在 Web profile 不再挂载**:`packages/bundle/web-app/cordis.patch.yml` 给 `ui-sidebar-browser` 加了 `disabled: !!js "ctx.get('profileContext')?.name !== 'desktop'"`。因此 e2e 的 `HOST_OWNED_TABS` 只剩 `['terminal']`,并且**显式断言 browser 条目缺席**(钉住新真值,而不是默默放宽)。DSH 同时新增用户设置 `linkOpening` 决定正文链接进侧栏还是新标签页。
|
||||
7. **外链接管收敛**:删掉 `browserInterceptLinks` / `browserInterceptHttp` / `browserInterceptHttps` 三个偏好键(含 20 份词典的 key)。新行为是**只认领声明了 `urlTarget` 的链接**,其余一律不 `preventDefault`、放行给宿主;认领成功但目标类型此刻不可用时 `window.open(url, '_blank', 'noopener,noreferrer')` 兜底。**修掉了一个真实回归**:0.1.6 那版把浏览器交还宿主时,`openInSidebar` 仍兜底到 `'browser'`,而插件注册表里已无该类型、`service.openTab` 对未注册类型静默 `return`——默认配置下插件自绘 markdown(sidechat 转录 / 编辑器预览 / diff)里的 http 链接**点了没反应**。
|
||||
@@ -62,15 +63,16 @@
|
||||
|
||||
1. **一次性 token 鉴权**:就绪行 `dsh web: http://127.0.0.1:<port>/?token=<43字符>`(导航换签名 cookie,干净 URL 401)。`e2e-mount.sh` 的 URL grep 必须延伸到空白(`[^ ]*`,在 `/` 截断丢 token);e2e 统一走 `tests/e2e/host.ts`(token 必选:`parseLaunchUrl` 对裸 origin 直接抛错),带 stamps 导航走 `gotoPage()`(先 addCookies 再直达——token 换 cookie 的 303 会丢弃同 URL 其它 query 参数)。插件 `/sidebar/*` 路由不受影响,同源 fetch 照旧。
|
||||
2. **Remote gateway 斜杠 RPC(唯一方言)**:`POST /api/workspace/create`,payload 恰为 `{args: {...}}`,**args 按控制器 TS 参数名包装**(`workspace/create`、`session/create` → `{args:{request:{...}}}`;`session/list` 参数名 `_request` **不可省略**——`{}` 也被拒 `args fields do not match the descriptor`);envelope `method` 与路径一致,点分路径 404。请求由 `tests/e2e/host-protocol.ts` 的 `rpcAttempt` 构造、`tests/e2e-host-protocol.spec.ts` 锁定。
|
||||
3. **`MarkdownText` labels 嵌套契约**:必填 `labels: { code: { copyLabel, copiedLabel }, footnotes }`(漏传回退硬编码中文)。四个渲染点(mermaid.tsx / MarkdownHtml.tsx / TextEditor.tsx / SideChatView.tsx)统一走 `src/client/markdown-labels.tsx` 的 `markdownTextProps()`。**0.1.7 逐字未变**。
|
||||
4. **侧边对话转录走自有路由,不碰客户端宿主 RPC**:`ctx.connection.api`(含 `sessions.history`)在 alpha.1 整体移除,继任 `session/follow|page` 又对 `origin:'subagent'` 会话强制 subagent 地址(普通 `{kind:'session'}` 被 `agent-busy` 拒)且分页 `throughSeq` 不得超当前游标。转录因此由 **`sidechat.events`** 插件路由供给(`src/sidechat-routes.ts`:live 读 `agent.session.snapshotEvents()`、冷读 `sessionPersistence.inspect`,服务端 `session/end-seed` 切割 + `afterSeq` 增量)。**0.1.5 起实时增量不在日志里**:`assistant/chunk` 事件被删除,进行中的模型增量改由 `agent/assistant-stream` 瞬时帧发布(`start`/`chunk`/`end`,不入会话日志),结算时才落 `assistant/message` 或 `assistant/attempt`。插件在宿主侧 `src/assistant-live.ts` 折叠这些帧成有界缓冲。**0.1.7 复查:`packages/core/agent/src/runtime-types.ts` 逐字未变,无需调整。**
|
||||
3. **`MarkdownText` labels 嵌套契约**:必填 `labels: { code: { copyLabel, copiedLabel, toolbarLabels? }, footnotes }`(漏传回退硬编码中文)。四个渲染点(mermaid.tsx / MarkdownHtml.tsx / TextEditor.tsx / SideChatView.tsx)统一走 `src/client/markdown-labels.tsx` 的 `markdownTextProps()`。**alpha.1 逐字未变;rc.1 新增可选的 `labels.code.toolbarLabels`**(`{codeLabel, wrapLabel, unwrapLabel}` 三个必填串)——传了它 `CodeBlock` 才渲染宿主新的 code card(语言名 + 换行开关 + 复制),不传就保留旧的 `data-code-block-banner` info banner。插件选择**全面采用**(同时用宿主同一套措辞 `codeBlock.title|wrap|unwrap`),所以 `MarkdownCopyLabels` 现在是 5 个字段,每个构造点都要给全(`tests/mermaid-markdown.spec.tsx` / `tests/markdown-html-render.spec.tsx` 两个 fixture 一并同步)。**同时修掉它带出来的坑**:新 card 对没有语法高亮的语言(mermaid 正是)显示 `codeLabel`,**info string 不再进 DOM**,于是 `src/client/mermaid.tsx` 原来那条「读 banner 里的 `mermaid` 字样」的探测恒假、围栏不再被换成图(三个 mermaid 用例当场红);现改为按**围栏正文**匹配——`splitMermaidBlocks(text)` 得到的 mermaid 正文集合 vs `block.querySelector('code')` 的文本,两侧 `trimEnd()`。`DiffBlockLabels` / `ReadBlockLabels` 在 rc.1 里改为继承 `CodeToolbarLabels` 且**删除了 `DiffBlockLabels.files`**,所以 `src/client/SideChatView.tsx` 的 diff / read 两个字典要给三个新键、并删掉 `files`(`sideChatBlockFiles` 词条随之从 20 份词典中删除)。
|
||||
4. **侧边对话转录走自有路由,不碰客户端宿主 RPC**:`ctx.connection.api`(含 `sessions.history`)在 alpha.1 整体移除,继任 `session/follow|page` 又对 `origin:'subagent'` 会话强制 subagent 地址(普通 `{kind:'session'}` 被 `agent-busy` 拒)且分页 `throughSeq` 不得超当前游标。转录因此由 **`sidechat.events`** 插件路由供给(`src/sidechat-routes.ts`:live 读 `agent.session.snapshotEvents()`、冷读走 `sessionPersistence` 的**句柄 API** `open(id,'read')` → `read()` → `close()`;`inspect` 早在 0.1.5 就被删除,注释里再写它属于历史残留,服务端 `session/end-seed` 切割 + `afterSeq` 增量)。**0.1.5 起实时增量不在日志里**:`assistant/chunk` 事件被删除,进行中的模型增量改由 `agent/assistant-stream` 瞬时帧发布(`start`/`chunk`/`end`,不入会话日志),结算时才落 `assistant/message` 或 `assistant/attempt`。插件在宿主侧 `src/assistant-live.ts` 折叠这些帧成有界缓冲。**0.1.7 复查:`packages/core/agent/src/runtime-types.ts` 逐字未变,无需调整。**
|
||||
5. **`dsh-subagent` 的 `SUBAGENT_DESCRIPTOR_VERSION` 仍是 3**(0.1.7 复查:`descriptor.ts` 两 tag 同值)。sidechat 种子的 `subagent/descriptor` 版本由宿主包盖章,插件不硬编码;测试断言跟随常量(`tests/sidechat-routes.spec.ts`),勿钉字面量。
|
||||
6. **`@deepseek-ai/dsh-client-runtime` 包已消亡**(继任 seed 是裸名 `dsh-client-store`,无 `/client` 子路径):peerDependencies、devDependencies、`dsh.client.inject`、chunk externals 白名单(`src/client/chunk-loader.ts` / `tsdown.config.ts` / `tests/chunk-loader.spec.ts` / `tests/manifest-consistency.spec.ts` 四处同步)均已无该条目。
|
||||
7. **e2e scratch profile 的 `minimumReleaseAgeExclude` 含 `'@deepseek-ai/*'`**(`scripts/e2e-mount.sh` / `e2e-aggregate-mount.sh`,与仓库根 `pnpm-workspace.yaml` 同策):alpha 版本常在发布后 24h 内跑 lane,pnpm 11 的 `minimumReleaseAge` 默认会拒装新鲜包。
|
||||
8. **插件开发树的 dsh-* 传递 peer 需提升为 devDependencies**(alpha.3 首见):`dsh-subagent` 等 npm 包把 `dsh-attachment` 等 dsh-* 姊妹包声明为 peerDependencies(由宿主 bundle 树统一提供,宿主侧无此问题),插件仓库若只直接依赖其中一部分,其余 peer 在 pnpm 下会解析到树上残留的旧版——如 `dsh-attachment@0.1.1-rc.1` 缺 `admitPromptContent` 导出、`dsh-subagent` 产物 import 它时测试加载即崩。因此 devDependencies 需涵盖 dev 树实际触达的全部 peer(attachment / scope / session-projection / system-prompt / user-approval / util-time 等,与直接依赖同款精确钉版);**`@deepseek-ai/cordis` peer 自 alpha.3 起要求 `^4.0.2`,0.1.7 起要求 `^4.0.3`**。适配新版本时先跑 `pnpm peers check`,把新失配的传递 peer 一并提升进 devDependencies。**0.1.7 新增的同类问题**见 §3.3 第 12 条(`ui-primitives` 的第二层裸 import)。例外:**`dsh-client-locale` 的 peer/devDep 允许落后于基线**的历史已消除,rc.1 起上游恢复发版,0.1.7 起与 DSH 同 tuple。
|
||||
9. **右侧栏是 DSH 原生栏,插件只提供 tab 类型**:聊天里一切文件打开(工具行 / 产物行 / 正文提及 / 行内代码路径)统一走 `ctx.sidebarRight.openResource(fileAddressFor(sessionId, cwd, path))`。插件的每个 `TabDescriptor` 注册成原生 tab 类型(`kind = descriptor.id`,`extension` 带)+ 原生 tab 体(`sidebar.right.pane.tab` keyed 槽,key = `dsh-better-sidebar:<id>`);`editor` 类型同时认领 `dsh-resource://file/**`(**但按 §3.2 第 5 条的清单让出一部分**),并接管内置 `files` 页面 kind(`openTab('files')` 打开插件文件树,注销即复位)。`ctx.sidebarRight.openTab/openResource/close` 只对**在屏会话**写入;跨会话用具体类上的 `openTabIn/openResourceIn/closeIn`。原生 tab 的插件侧状态在 `src/client/native/tab-adapter.tsx`。**注册必须等服务、不能等槽声明**:原生栏先声明 `sidebar.right.pane.tab` 再 `provide('sidebarRightTabs')`,真机 profile 上槽声明回调里 `ctx.get('sidebarRightTabs')` 仍是 undefined(实测 3 秒后才出现),按槽触发注册会静默什么都不注册且永不重试——用 `ctx.inject(['sidebarRightTabs'], cb)` 驱动类型注册(`tests/native-surface.spec.ts` 以「槽先触发、服务后到达」的顺序守护)。**0.1.6-alpha.2 起**:`SidebarRightGuideEntry.id` 必填且同 provider 内唯一(缺它会静默清空整个承载面);同 provider 的 guide 条目是**追加**关系,`chain` 那种「替换宿主条目」的语义只存在于 `conversation.chat.turnTail` 且已被上游改成 `list`。**0.1.7 起**:`sidebar-right` 本体的契约**零破坏**——槽名无改名、`SidebarRightTabDefinition` 没有新的必填字段、只有新增的可选 `keepMounted` 与 `ISidebarRight.mounted`,`openTabIn/openResourceIn/closeIn` 在具体 class 上字节不变;`tab.visible` 语义收紧为 `active && (...)`(全局面板/后台会话时 body 不挂载);持久化校验收紧(非根 / 列轴 / 嵌套 / 3+ docked pane 的 split 一律判非法**整份丢弃**,0.1.6 的 sidebar 自己产不出这种布局);`RightbarRoot` 现在为每个保留会话渲染一个隐藏 seat(`SidebarSessionViews`,未导出、插件拿不到)。原生 tab 体宿主 `.paneBody` 是**有确定高度的块级滚动容器**(非 flex 容器),native 适配层因此给每个 tab 体包一层 `height:100%` 的列 flex 宿主(`sidebar.module.css` 的 `.nativeTabHost`),tab 组件根继续用 `flex:1`/`height:100%`。全局面板(根级 `main` keyed 槽 + `sidebar.panellist` + `ctx.layout.selectPanel/beginNavigation`、`rightbar` 改根级并新增 `rightbar.session`)插件**不接入**,只做兼容。底部工作台的中心列锚点认 `[data-slot="main.conversation"]`(并跳过 `display: contents` 祖先,同时保留 alpha.1 的 `[data-slot="conversation"]`);文件地址语法跟随 alpha.2(`fileAddressFor` 一律 session 作用域、绝对路径保留前导 `/`、`parseFileAddress` 前缀解析并去 `?`/`#`)。**rc.1 起**:宿主原生指南只在列出的条目 ≤ 4 条时渲染说明(上游 `MAX_DESCRIBED_ENTRIES = 4`;更长的列表是整列丢弃,不是截断)——插件默认贡献 4 个 guide 条目(文件 / 文件变动 / 任务管理 / 侧边对话),**与宿主的终端条目合计后可能超过 4 条**,此时说明不渲染;插件**不恢复**旧的 `nativeGuideDesc` 通用兜底句。
|
||||
8. **插件开发树的 dsh-* 传递 peer 需提升为 devDependencies**(alpha.3 首见):`dsh-subagent` 等 npm 包把 `dsh-attachment` 等 dsh-* 姊妹包声明为 peerDependencies(由宿主 bundle 树统一提供,宿主侧无此问题),插件仓库若只直接依赖其中一部分,其余 peer 在 pnpm 下会解析到树上残留的旧版——如 `dsh-attachment@0.1.1-rc.1` 缺 `admitPromptContent` 导出、`dsh-subagent` 产物 import 它时测试加载即崩。因此 devDependencies 需涵盖 dev 树实际触达的全部 peer(attachment / scope / session-projection / system-prompt / user-approval / util-time 等,与直接依赖同款精确钉版);**`@deepseek-ai/cordis` peer 自 alpha.3 起要求 `^4.0.2`,0.1.7-alpha.1 要求 `^4.0.3`,rc.1 起要求 `~4.0.4`**(rc.1 顺手把 vendor 一起抬了:cordis 4.0.4 / schemastery 3.18.4 / cordis-plugin-group 1.0.4 / cordis-plugin-include 1.0.9;loader 保持 1.0.5)。**rc.1 实测的教训**:只改 `dependencies` 里的 schemastery 和 peer 里的 cordis **不够**——`cordis-plugin-group` / `-include` 是 `dsh-app-boot` / `dsh-config-editor` 的**传递 peer**,pnpm 会继续沿用 lockfile 里的旧副本,`pnpm peers check` 一次报出四类 unmet peer;按本条把四个 vendor 包**显式钉进 devDependencies** 才收敛(这也是 rc.1 那条「DSH 内部引用一律精确版本」的 workspace-release-ranges 政策的直接后果)。适配新版本时先跑 `pnpm peers check`,把新失配的传递 peer 一并提升进 devDependencies。**0.1.7 新增的同类问题**见 §3.3 第 12 条(`ui-primitives` 的第二层裸 import)。例外:**`dsh-client-locale` 的 peer/devDep 允许落后于基线**的历史已消除,rc.1 起上游恢复发版,0.1.7 起与 DSH 同 tuple。
|
||||
9. **右侧栏是 DSH 原生栏,插件只提供 tab 类型**:聊天里一切文件打开(工具行 / 产物行 / 正文提及 / 行内代码路径)统一走 `ctx.sidebarRight.openResource(fileAddressFor(sessionId, cwd, path))`。插件的每个 `TabDescriptor` 注册成原生 tab 类型(`kind = descriptor.id`,`extension` 带)+ 原生 tab 体(`sidebar.right.pane.tab` keyed 槽,key = `dsh-better-sidebar:<id>`);`editor` 类型同时认领 `dsh-resource://file/**`(**但按 §3.2 第 5 条的清单让出一部分**),并接管内置 `files` 页面 kind(`openTab('files')` 打开插件文件树,注销即复位)。`ctx.sidebarRight.openTab/openResource/close` 只对**在屏会话**写入;跨会话用具体类上的 `openTabIn/openResourceIn/closeIn`。原生 tab 的插件侧状态在 `src/client/native/tab-adapter.tsx`。**注册必须等服务、不能等槽声明**:原生栏先声明 `sidebar.right.pane.tab` 再 `provide('sidebarRightTabs')`,真机 profile 上槽声明回调里 `ctx.get('sidebarRightTabs')` 仍是 undefined(实测 3 秒后才出现),按槽触发注册会静默什么都不注册且永不重试——用 `ctx.inject(['sidebarRightTabs'], cb)` 驱动类型注册(`tests/native-surface.spec.ts` 以「槽先触发、服务后到达」的顺序守护)。**0.1.6-alpha.2 起**:`SidebarRightGuideEntry.id` 必填且同 provider 内唯一(缺它会静默清空整个承载面);同 provider 的 guide 条目是**追加**关系,`chain` 那种「替换宿主条目」的语义只存在于 `conversation.chat.turnTail` 且已被上游改成 `list`。**0.1.7 起**:`sidebar-right` 本体的契约**零破坏**——槽名无改名、`SidebarRightTabDefinition` 没有新的必填字段、只有新增的可选 `keepMounted` 与 `ISidebarRight.mounted`,`openTabIn/openResourceIn/closeIn` 在具体 class 上字节不变;`tab.visible` 语义收紧为 `active && (...)`(全局面板/后台会话时 body 不挂载);持久化校验收紧(非根 / 列轴 / 嵌套 / 3+ docked pane 的 split 一律判非法**整份丢弃**,0.1.6 的 sidebar 自己产不出这种布局);`RightbarRoot` 现在为每个保留会话渲染一个隐藏 seat(`SidebarSessionViews`,未导出、插件拿不到)。原生 tab 体宿主 `.paneBody` 是**有确定高度的块级滚动容器**(非 flex 容器),native 适配层因此给每个 tab 体包一层 `height:100%` 的列 flex 宿主(`sidebar.module.css` 的 `.nativeTabHost`),tab 组件根继续用 `flex:1`/`height:100%`。全局面板(根级 `main` keyed 槽 + `sidebar.panellist` + `ctx.layout.selectPanel/beginNavigation`、`rightbar` 改根级并新增 `rightbar.session`)插件**不接入**,只做兼容。底部工作台的中心列锚点认 `[data-slot="main.conversation"]`(并跳过 `display: contents` 祖先,同时保留 alpha.1 的 `[data-slot="conversation"]`);文件地址语法跟随 alpha.2(`fileAddressFor` 一律 session 作用域、绝对路径保留前导 `/`、`parseFileAddress` 前缀解析并去 `?`/`#`)。**原生指南说明的 4 条上限(归属更正:这是 0.1.7-alpha.1 起就存在的既成事实,不是 rc.1 的变更)**:`ui-sidebar-right/src/client/tabs/guide/GuideBody.tsx` 的 `MAX_DESCRIBED_ENTRIES = 4` 及其判定行在 alpha.1 / alpha.2 / rc.1 三个 tag 上**逐字相同**,宿主终端的 guide 条目(`ui-sidebar-terminal/src/client/TerminalGuide.tsx`)也是 alpha.1 就有了,`ui-sidebar-terminal/src` 在 rc.1 **零改动**。含义不变:条目 ≤ 4 条才渲染说明,更长的列表是整列丢弃而不是截断——插件默认贡献 4 个 guide 条目(文件 / 文件变动 / 任务管理 / 侧边对话),与宿主的终端条目合计后可能超过 4 条,此时说明不渲染;插件**不恢复**旧的 `nativeGuideDesc` 通用兜底句。
|
||||
10. **自定义种子必须带 fork 标记对(`meta.isSeeded: true` + `inheritedEventCount`)**:dsh-session 契约「只给 seed 不标 isSeeded,种子算重放历史而非继承前缀」——缺标记时 `Session.ownEvents()` 含整个种子,子会话的 inbox 折重放种子里的 `agent/inbox/spliced`,**继承父会话切割时刻未领取的 inbox 输入**。宿主 `session.fork`(api-session-controller)的调用即规范形态;回归由 `tests/sidechat-seed-validation.spec.ts`(真实 `Session.create` + 对 `ownEvents()` 跑 inbox 折)守护。**0.1.7 复查:`Session.create` 的五个参数与函数体逐字相同**;上游新增了 `buildForkSeed(events, boundary)` 导出,与本插件手工的 `buildSidechatInheritance` 职责重叠但**收益不明确**(插件还有 dangling-tool-call 退回结构化快照的自有需求),暂不替换。
|
||||
11. **`dsh.plugin.json` 从来不是 DSH 契约**:0.1.7 全树 grep 仍 **0 命中**。DSH 真正读的是 `package.json` 的 `dsh.bundle.patch` + `dsh.client`(`platform`/`inject`/`immediately`/`external`)+ `exports["./client"]`。`dsh.plugin.json` 只服务第三方 registry(社区市场)通道,`lib/client-registry.js` 同理;`tests/manifest-consistency.spec.ts` 守护的是这条通道的形状,不是 DSH 契约。**`dsh.manifestVersion` 也仍是「只声明、零读」**(0.1.7 的 `package-manifest` README 自己写明「Current installers and loaders do not enforce `dsh.manifestVersion` or `engines.dsh`」)。0.1.7 的官方管控面新增:`plugin-manager` 的**多 registry 回退**(`registryPlan()`:配置源 → `fallbackRegistries`(默认含 `registry.npmmirror.com`),`network`/`timeout`/`not-found`/`no-matching-version` 会自动问下一个源;`registry` 入参只存在于 Web 对话框与 `plugin_manager` 工具,**CLI 没有 registry flag**)、`waitForInstall`、以及**插件展示元数据**:`package.json#icon`(36×36、纯填充无描边、**双色渐变**——与 DSH 自带的 `PluginArtwork*` 同风格:它们「carry their own brand colors instead of riding currentColor」,且每个都是多色,单色版在 30px 行内尺寸下会读成一块纯色板)+ `locale/<lang>.json` 的 `meta.title`/`description`。本插件**已采纳**(v0.21.0-alpha.1):`icon.svg` + `locale/en.json` + `locale/zh.json`,并由 `tests/plugin-meta.spec.ts` 守护「声明了就必须发布出去」。三条硬规则:icon 必须是**包内相对路径**且写进 `files`;`locale/en.json` 是发现基线(缺它整个目录都不读);`exports` 必须暴露 `./locale/*.json` 与 `./package.json`。**所有失败都是静默的**——元数据有问题只会退化成一行纯文字,没有任何报错。`dsh.bundle.patch` 现在多了形状校验(非法值会 `throw`,引导期跳过该 bundle),本插件是合法的单字符串。
|
||||
11. **`dsh.plugin.json` 从来不是 DSH 契约**:0.1.7 全树 grep 仍 **0 命中**。DSH 真正读的是 `package.json` 的 `dsh.bundle.patch` + `dsh.client`(`platform`/`inject`/`immediately`/`external`)+ `exports["./client"]`。`dsh.plugin.json` 只服务第三方 registry(社区市场)通道,`lib/client-registry.js` 同理;`tests/manifest-consistency.spec.ts` 守护的是这条通道的形状,不是 DSH 契约。**`dsh.manifestVersion` 也仍是「只声明、零读」**(0.1.7 的 `package-manifest` README 自己写明「Current installers and loaders do not enforce `dsh.manifestVersion` or `engines.dsh`」)。0.1.7 的官方管控面新增:`plugin-manager` 的**多 registry 回退**(`registryPlan()`:配置源 → `fallbackRegistries`(默认含 `registry.npmmirror.com`),`network`/`timeout`/`not-found`/`no-matching-version` 会自动问下一个源;`registry` 入参只存在于 Web 对话框与 `plugin_manager` 工具,**CLI 没有 registry flag**)、`waitForInstall`、以及**插件展示元数据**:`package.json#icon`(36×36、纯填充无描边、**双色渐变**——与 DSH 自带的 `PluginArtwork*` 同风格:它们「carry their own brand colors instead of riding currentColor」,且每个都是多色,单色版在 30px 行内尺寸下会读成一块纯色板)+ `locale/<lang>.json` 的 `meta.title`/`description`。本插件**已采纳**(v0.21.0-rc.1):`icon.svg` + `locale/en.json` + `locale/zh.json`,并由 `tests/plugin-meta.spec.ts` 守护「声明了就必须发布出去」。**rc.1 复查:`packages/boot/app-boot/src/package-meta.ts` 与 `scripts/verify-package-meta.ts` 在两个 tag 上逐字相同**(`ui-plugin-manager/src/client/presentation.ts` 只多了一段 `incompatible-version` 文案),所以上面三条硬规则与「**没有任何尺寸/渐变校验**」都仍然成立。三条硬规则:icon 必须是**包内相对路径**且写进 `files`;`locale/en.json` 是发现基线(缺它整个目录都不读);`exports` 必须暴露 `./locale/*.json` 与 `./package.json`。**所有失败都是静默的**——元数据有问题只会退化成一行纯文字,没有任何报错。`dsh.bundle.patch` 现在多了形状校验(非法值会 `throw`,引导期跳过该 bundle),本插件是合法的单字符串。
|
||||
12. **peer 声明是启动期硬约束(rc.1 起;本版最容易静默失效的一处)**:`packages/boot/app-boot/src/plugin-compatibility.ts`(rc.1 **新文件**)只做一件事——遍历 profile 行的 `peerDependencies`,对**名字为 `@deepseek-ai/dsh` 或以 `@deepseek-ai/dsh-` 开头**的条目跑 `semver.satisfies(宿主版本, range, { includePrerelease: true })`,不满足就把整行 `row.disabled = true`(group 行连 `group` 一起关掉),只在 stderr 留一行 `disabling profile plugin <label>: <reason>`。调用点:`compatibility-preflight.ts` 的 `prepareProfileEntries`(`dsh web --profile <p>` 的必经路径)、`profile.ts`(bundle 行,异常被吞成 skip,该 bundle 不再贡献 patch 层)、`agent-preset-registry/src/mount.ts`(预置行),以及 plugin-manager 的安装前/安装后校验。**四个要点**:(a)它**只读 peer,不读 `engines.dsh` / `dsh.manifestVersion`**(那两个字段仍然零读者,见第 11 条);(b)`peerDependenciesMeta.optional` **没有任何豁免**——我们那条 optional 的 `@deepseek-ai/dsh-client-ui-sidebar-right` 照样参与判定;(c)`includePrerelease` 被强制打开,判定比 npm 宽松(`^0.1.6-alpha.2` 也能满足 `0.1.7-rc.1`),但**精确版本号、或没有预发布子句的范围(如 `^0.1.7`)一定不过**;(d)豁免只能写 profile 自己的 `compatibility.json`(`dsh plugin allow-version <pkg@ver> --dsh-version <exact> --accept-risk`),没有全局开关也没有环境变量。因此本仓库的 DSH peer **一律写 `^<基线>` 浮动范围、绝不钉精确版本**(devDependencies 才用精确钉版);`tests/market-manifest.spec.ts` 新增一条守护把这条规则钉住。**`pnpm peers check` 看不到这个失败模式**:它校验的是解析出来的 dev 树,不是宿主会读的范围形状。
|
||||
|
||||
---
|
||||
|
||||
@@ -103,4 +105,5 @@
|
||||
- **插件展示元数据**:`package.json#icon` + `locale/<lang>.json`(DSH 0.1.7+ 的 Plugins 页与 `plugin_manager` 列表),由 `tests/plugin-meta.spec.ts` 守护。
|
||||
- **接入 API 全参考**:[docs/external-plugin-guide.md](docs/external-plugin-guide.md)(消费插件开发者向;§0 原生栏承载面 / §4 Tab API / §5 FileViewer API / §7 服务方法 / §10 平台陷阱 / §11 已移除的自由窗口 / §12 皮肤契约 / §15 真实案例)。
|
||||
- **设计文档**:[docs/plans/](docs/plans/)(30+ 份逐特性设计,含实施偏差记录)。
|
||||
- **关键测试守护**:`tests/service.spec.ts` / `builtins.spec.ts`(注册表与内置清单:**5 tab + 3 viewer**——终端与浏览器已交还宿主,只读预览也按 §3.2 第 5 条让出,只剩 markdown / html / code)/ `market-manifest.spec.ts`(市场约束,含 `pnpm pack` 后的产物面)/ `manifest-consistency.spec.ts`(registry 通道形状)/ `e2e-host-protocol.spec.ts`(RPC 双协议)/ `native-surface.spec.ts`(原生右侧栏承载面,含 guide 条目 id 唯一性)/ `theme.spec.ts`(皮肤契约,含空白面板胶囊几何)/ `plugin-list.spec.ts`(推荐插件目录)/ `fs-search.spec.ts`(host 文件名搜索)/ `fs-watch.spec.ts`(文件树目录 watch 的去抖、句柄上限与错误路径)/ `smoke.spec.ts` 的 settings 段(按 entry id 读写表单、**一次性 legacy 迁移**、open 工具门控)。
|
||||
- **测试不得依赖非普适二进制**:CI 跑 ubuntu + windows 两个 runner,`rg` / `fd` / `jq` 这类「开发机上有」的工具在 runner 上没有,代价是整个 spec 在**收集阶段**失败(`spawnSync rg ENOENT`)而本地永远绿——上一版的 `tests/primitives-exports.spec.ts` 就这么让分支红了两轮。取文件清单用 `readdirSync` 自己走,或只用 `git` / `tar` / `pnpm` / node 内置能力;确需外部工具时先探测存在性并跳过。
|
||||
- **关键测试守护**:`tests/service.spec.ts` / `builtins.spec.ts`(注册表与内置清单:**5 tab + 3 viewer**——终端与浏览器已交还宿主,只读预览也按 §3.2 第 5 条让出,只剩 markdown / html / code)/ `market-manifest.spec.ts`(市场约束,含 `pnpm pack` 后的产物面)/ `manifest-consistency.spec.ts`(registry 通道形状)/ `e2e-host-protocol.spec.ts`(RPC 双协议)/ `native-surface.spec.ts`(原生右侧栏承载面:guide 条目 id 唯一性、以及 `canOpen` 的「拒绝清单不得宽于宿主渲染器」双向边界)/ `theme.spec.ts`(皮肤契约,含空白面板胶囊几何)/ `plugin-list.spec.ts`(推荐插件目录)/ `fs-search.spec.ts`(host 文件名搜索)/ `fs-watch.spec.ts`(文件树目录 watch 的去抖、句柄上限与错误路径)/ `smoke.spec.ts` 的 settings 段(按 entry id 读写表单、**一次性 legacy 迁移**、open 工具门控)。
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
> [!IMPORTANT]
|
||||
> **已适配 DSH 原生侧边栏 API**(v0.19.0 起):右列就是 DSH 自己的右侧栏——插件的每个 tab 类型与 tab 体通过 `ctx.sidebarRightTabs` / `ctx.sidebarRight` 注册与打开,聊天里的文件打开统一走 `ctx.sidebarRight.openResource('dsh-resource://file/…')`,插件**不再自绘右侧面板**(旧的浮窗能力同步移除)。自绘的底部工作台与开放给其他插件的 `ctx.betterSidebar` 服务保持不变,接入方式见[插件接入指南](docs/external-plugin-guide.md)。
|
||||
>
|
||||
> **v0.21.0-alpha.1 起宿主支持下限是 DSH `0.1.7-alpha.1`**(peer 下限 `^0.1.7-alpha.1`;npm dist-tag `alpha`,`latest` 仍是 **v0.19.1**)。DSH 0.1.7 自带完整的文档预览(表格 / PDF / 图片 / Office),因此插件**把只读预览整体让给内置**(只保留 Markdown / HTML / 可编辑的代码编辑器)、**把外链接管收敛为「只认领声明了 `urlTarget` 的链接」**(按协议分流的三个外链接管设置项已删除),并**重写了设置接入面**(偏好迁到 profile 里本插件的挂载行,旧的 `settings.yaml` 段在首次启动时自动回迁);文件树同时获得**实时刷新**。**0.1.6-alpha.2 及更早的用户请停留在 v0.19.1**——注意 **0.20.0 这一版从未发布到 npm**,这些变更全部落在 v0.21.0-alpha.1。
|
||||
> **v0.21.0-rc.1 起宿主支持下限是 DSH `0.1.7-rc.1`**(peer 下限 `^0.1.7-rc.1`;npm dist-tag `alpha`,`latest` 仍是 **v0.19.1**)。DSH 0.1.7 自带完整的文档预览(表格 / PDF / 图片 / Office),因此插件**把只读预览整体让给内置**(只保留 Markdown / HTML / 可编辑的代码编辑器)、**把外链接管收敛为「只认领声明了 `urlTarget` 的链接」**(按协议分流的三个外链接管设置项已删除),并**重写了设置接入面**(偏好迁到 profile 里本插件的挂载行,旧的 `settings.yaml` 段在首次启动时自动回迁);文件树同时获得**实时刷新**。**0.1.6-alpha.2 及更早的用户请停留在 v0.19.1**——注意 **0.20.0 这一版从未发布到 npm**,这些变更全部落在 v0.21.0-rc.1。
|
||||
|
||||
<!-- Hero -->
|
||||
<div align="center">
|
||||
@@ -14,7 +14,7 @@
|
||||
<a href="https://github.com/omdsh-dev/DSH-better-sidebar/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/omdsh-dev/DSH-better-sidebar" /></a>
|
||||
<a href="https://opensource.org/licenses/MIT"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
|
||||
<a href="https://dshfind.com/zh/plugins/omdsh-dev/DSH-better-sidebar?ref=badge"><img alt="dshfind" src="https://dshfind.com/api/badge/omdsh-dev/DSH-better-sidebar?lang=zh" /></a><br /><br />
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本(v0.21.0-alpha.1):0.1.7-alpha.1+" src="https://img.shields.io/badge/DSH-0.1.7--alpha.1%2B-4d6bfe" /></a>
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本(v0.21.0-rc.1):0.1.7-rc.1+" src="https://img.shields.io/badge/DSH-0.1.7--rc.1%2B-4d6bfe" /></a>
|
||||
<a href="https://github.com/topics/dsh-better-sidebar"><img alt="插件生态:GitHub topic dsh-better-sidebar" src="https://img.shields.io/badge/%E6%8F%92%E4%BB%B6%E7%94%9F%E6%80%81-topic%20dsh--better--sidebar-4d6bfe" /></a><br /><br />
|
||||
<img alt="文件管理" src="https://img.shields.io/badge/-文件管理-4d6bfe" /> <img alt="编辑预览" src="https://img.shields.io/badge/-编辑预览-4d6bfe" /> <img alt="内置浏览器" src="https://img.shields.io/badge/-内置浏览器-4d6bfe" /> <img alt="文件变动" src="https://img.shields.io/badge/-文件变动-4d6bfe" /> <img alt="后台任务" src="https://img.shields.io/badge/-后台任务-4d6bfe" /> <img alt="侧边对话" src="https://img.shields.io/badge/-侧边对话-4d6bfe" /> <img alt="插件接入" src="https://img.shields.io/badge/-插件接入-4d6bfe" /><br /><br />
|
||||
<b>右侧栏 + 底部面板双工作台</b>,并把 <code>ctx.betterSidebar</code> 服务开放给所有插件——<br />
|
||||
@@ -65,9 +65,9 @@
|
||||
**前置**:已装好 DSH(`dsh web` 能正常运行),Node.js ≥ 20、pnpm ≥ 10。
|
||||
|
||||
**支持的 DSH 版本**:
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本(v0.21.0-alpha.1):0.1.7-alpha.1+" src="https://img.shields.io/badge/DSH-0.1.7--alpha.1%2B-4d6bfe" /></a>
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本(v0.21.0-rc.1):0.1.7-rc.1+" src="https://img.shields.io/badge/DSH-0.1.7--rc.1%2B-4d6bfe" /></a>
|
||||
|
||||
> 📌 **通道与支持线**:`v0.21.0-alpha.1` 是 **alpha 通道**(npm dist-tag `alpha`),适配 DSH **0.1.7-alpha.1+**(peer 下限 `^0.1.7-alpha.1`,CI 钉 `@deepseek-ai/dsh@0.1.7-alpha.1`)。**npm `latest` 仍是 `v0.19.1`**——注意 `v0.20.0` 这一版**从未发布到 npm**,本仓库从 0.19.1 直接跳到这条 0.21 开发线。**下限必须动**:semver 的预发布规则让 `^0.1.6-alpha.2` 在数学上永远匹配不到任何 `0.1.7` 预发布版。**DSH 0.1.6-alpha.2 及更早(含 npm `latest` 的 0.1.5-rc.2)的用户请固定安装 `dsh-better-sidebar@0.19.1`**——0.1.7 的破坏面足够大(`dsh-settings` 整体重写、`ui-primitives` 图标具名导出整族改名、会话格式 v3→v4),本版不写运行时兼容层;DSH 0.1.5-alpha.2 及更早同样请用旧版(`0.19.0-alpha.1` / `0.18.x` / `0.17.1`)。
|
||||
> 📌 **通道与支持线**:`v0.21.0-rc.1` 是 **alpha 通道**(npm dist-tag `alpha`),适配 DSH **0.1.7-rc.1+**(peer 下限 `^0.1.7-rc.1`,CI 钉 `@deepseek-ai/dsh@0.1.7-rc.1`)。**装 DSH 请写精确版本号**:0.1.7-rc.1 在 npm 上走 `next` 通道,`alpha` 此刻指的是 0.1.7-alpha.2——`npm i -g @deepseek-ai/dsh@0.1.7-rc.1`。**npm `latest` 仍是 `v0.19.1`**——注意 `v0.20.0` 这一版**从未发布到 npm**,本仓库从 0.19.1 直接跳到这条 0.21 开发线。**下限必须动**:semver 的预发布规则让 `^0.1.6-alpha.2` 在数学上永远匹配不到任何 `0.1.7` 预发布版。**DSH 0.1.6-alpha.2 及更早(含 npm `latest` 的 0.1.5-rc.3)的用户请固定安装 `dsh-better-sidebar@0.19.1`**——0.1.7 的破坏面足够大(`dsh-settings` 整体重写、`ui-primitives` 图标具名导出整族改名、会话格式 v3→v4),本版不写运行时兼容层;DSH 0.1.5-alpha.2 及更早同样请用旧版(`0.19.0-alpha.1` / `0.18.x` / `0.17.1`)。
|
||||
|
||||
```sh
|
||||
dsh plugin --profile web add dsh-better-sidebar@alpha
|
||||
@@ -133,7 +133,7 @@ dsh plugin --profile web add dsh-better-sidebar@alpha
|
||||
5. 硬刷新浏览器(Cmd/Ctrl+Shift+R)即可看到效果(client 改动无需重启 DSH;host 半改动才需重启)
|
||||
```
|
||||
|
||||
更新:`git pull && pnpm install && pnpm build` → 硬刷新浏览器即可(client 改动热加载生效,无需重启 DSH;host 半改动才需重启)。切回 npm 通道时,把依赖改回 npm 上的对应版本(稳定线 `"^0.19.1"`;本 alpha 线 `"^0.21.0-alpha.1"`)再 `pnpm install`。
|
||||
更新:`git pull && pnpm install && pnpm build` → 硬刷新浏览器即可(client 改动热加载生效,无需重启 DSH;host 半改动才需重启)。切回 npm 通道时,把依赖改回 npm 上的对应版本(稳定线 `"^0.19.1"`;本 alpha 线 `"^0.21.0-rc.1"`)再 `pnpm install`。
|
||||
|
||||
</details>
|
||||
|
||||
@@ -259,23 +259,23 @@ GitHub topic [`dsh-better-sidebar`](https://github.com/topics/dsh-better-sidebar
|
||||
|
||||
## 🆕 最近更新
|
||||
|
||||
**支持的 DSH 版本**:<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本(v0.21.0-alpha.1):0.1.7-alpha.1+" src="https://img.shields.io/badge/DSH-0.1.7--alpha.1%2B-4d6bfe" /></a> · 完整发布历史见 [Releases](https://github.com/omdsh-dev/DSH-better-sidebar/releases)
|
||||
**支持的 DSH 版本**:<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本(v0.21.0-rc.1):0.1.7-rc.1+" src="https://img.shields.io/badge/DSH-0.1.7--rc.1%2B-4d6bfe" /></a> · 完整发布历史见 [Releases](https://github.com/omdsh-dev/DSH-better-sidebar/releases)
|
||||
|
||||
### v0.21.0-alpha.1
|
||||
### v0.21.0-rc.1
|
||||
|
||||
> 🧪 **alpha 通道**(npm dist-tag `alpha`,安装 `dsh-better-sidebar@alpha`;npm `latest` 仍是 **v0.19.1**):仅支持 **DSH 0.1.7-alpha.1+**(peer 下限 `^0.1.7-alpha.1`,CI 钉 `@deepseek-ai/dsh@0.1.7-alpha.1`)。**DSH 0.1.6-alpha.2 及更早的用户请固定在 v0.19.1**——0.1.7 动了设置服务、图标具名导出与会话格式三处硬契约,本版不写运行时兼容层。⚠️ **上一版 v0.20.0 从未发布到 npm**:它的终端 / 浏览器让出也一并落在本版,npm 上从 0.19.1 直接到本版。
|
||||
> 🧪 **alpha 通道**(npm dist-tag `alpha`,安装 `dsh-better-sidebar@alpha`;npm `latest` 仍是 **v0.19.1**):仅支持 **DSH 0.1.7-rc.1+**(peer 下限 `^0.1.7-rc.1`,CI 钉 `@deepseek-ai/dsh@0.1.7-rc.1`)。**DSH 0.1.6-alpha.2 及更早的用户请固定在 v0.19.1**——0.1.7 动了设置服务、图标具名导出与会话格式三处硬契约,本版不写运行时兼容层。⚠️ **上一版 v0.20.0 从未发布到 npm**:它的终端 / 浏览器让出也一并落在本版,npm 上从 0.19.1 直接到本版。
|
||||
|
||||
- 🗂️ **只读文件预览整体让给 DSH 的文档预览**:DSH 0.1.7 的 `ui-sidebar-documentpreview` 自带表格 / PDF / 图片 / Office 渲染(宿主侧 Office→PDF 转换、电子表格 worker 表格、图片 / PDF 缩放、按目录自动刷新),所以插件删掉了自己的 `image` / `pdf` / `binary-download` 三个 viewer,并在 `editor.canOpen` 里**拒绝认领**这些扩展名——`xlsx xls xlsb xlt xltx xltm ods ots fods csv tsv pdf png jpg jpeg gif webp svg bmp ico avif doc docx dot dotx ppt pptx`——把文件地址交回宿主。**插件仍保留三件宿主没有的**:Markdown(自带渲染器)、HTML(自带沙箱预览 + `htmlViewerNoSandbox` / `htmlViewerDefaultUnsafe` 两个安全开关)、以及**可编辑**的文本 / 代码编辑器(内置那几个是只读预览);未知二进制(`.zip` / `.wasm`)仍走代码编辑器判 binary 后的下载面板,功能不回归。
|
||||
- 🗂️ **只读文件预览整体让给 DSH 的文档预览**:DSH 0.1.7 的 `ui-sidebar-documentpreview` 自带表格 / PDF / 图片 / Office 渲染(宿主侧 Office→PDF 转换、电子表格 worker 表格、图片 / PDF 缩放、按目录自动刷新),所以插件删掉了自己的 `image` / `pdf` / `binary-download` 三个 viewer,并在 `editor.canOpen` 里**拒绝认领**这些扩展名——`xlsx xls csv tsv fods pdf png jpg jpeg gif webp svg bmp ico doc docx ppt pptx`——把文件地址交回宿主。**rc.1 收回其中 9 个**:`xlsb` / `xlt` / `xltx` / `xltm` / `ots` / `dot` / `dotx` / `avif` / `ods` 宿主其实**没有渲染器**(点开只有「暂不支持预览」),而它们在让出之前是走插件兜底显示下载面板的,属于我们上一版自己引入的回归;现由插件的 `code` catch-all 重新认领。`fods` 继续让出(宿主会用纯文本显示这段扁平 XML,比下载面板有用)。**插件仍保留三件宿主没有的**:Markdown(自带渲染器)、HTML(自带沙箱预览 + `htmlViewerNoSandbox` / `htmlViewerDefaultUnsafe` 两个安全开关)、以及**可编辑**的文本 / 代码编辑器(内置那几个是只读预览);未知二进制(`.zip` / `.wasm`)仍走代码编辑器判 binary 后的下载面板,功能不回归。
|
||||
- 🔗 **外链接管收敛**:删掉按协议分流的三个外链接管设置项(20 份词典的相关词条一并删除)。现在插件**只认领有 tab 类型通过 `urlTarget` 明确声明认领的链接**,其余一律放行、由宿主决定(DSH 0.1.7 新增用户设置 `linkOpening`,决定正文链接进侧栏还是新标签页);**一个都没认领到时不阻止默认行为**;认领成功但目标类型在打开那一刻已不可用(插件卸载 / 被关)时兜底 `window.open(url, '_blank', 'noopener,noreferrer')`——顺手修掉了上一版留下的真实回归:插件自绘 markdown(侧边对话转录 / 编辑器预览 / diff 面板)里的 http 链接点了没反应。另外宿主的 `browser` kind **在 Web profile 已不再挂载**(0.1.7 只在 desktop profile 挂载它)。
|
||||
- ⚙️ **设置接入面重写 + 用户偏好的自动回迁**:DSH 0.1.7 删除了插件可注册的设置命名空间,改为**按插件 Loader 行的 entry id 找表单**(`SettingsForms`:只剩 `describe` / `update` / `replace` / `mutate` / `configure`)。插件偏好因此落在 **profile 的 cordis patch 文档**里(即本插件的挂载行),不再是 `~/.dsh/settings.yaml`;schema 来自插件模块导出的 `Config`(本版把用户偏好并进 `Config`,并给每个偏好字段标 `meta.volatile = true`——**这一个标记就是「改设置实时生效、不重挂插件」的全部机制**)。**用户设置不会丢**:插件首次启动时会把旧 `settings.yaml` / `settings.yaml.imported` 里的 `dsh-better-sidebar` 段一次性回迁(只在该行还没有任何用户值时执行,且只迁移当前 schema 仍声明的字段)。entry id 是**运行时自发现**的(本包默认 `better-sidebar`,聚合包挂载时会是别的 id),不硬编码。
|
||||
- 🔄 **文件树实时刷新**:插件接管了内置「文件」页,宿主自己的按目录 watch 覆盖不到它——本版新增 `/sidebar/ws/fs-watch`:客户端上报**已展开**的目录,宿主按目录 `fs.watch`(150ms 去抖、每连接 64 个句柄上限、路径仍走 `fs.tree` 同一道 workspace fence),改动后只重列那一层、折叠即退订。此前文件树会一直陈旧到手动刷新。
|
||||
- 🐛 **会话跟随修好了**:插件此前读的是一个**不存在的 `SessionListState.current` 字段**(插件的类型镜像自己造了它,编译期一直放行),导致「按会话持久化」实际没绑上、窄屏 park 门控恒假。现在改用 DSH 0.1.7 的 `ctx.sidebarRight.mounted`(只在该列真正换成另一个会话时才变化)。
|
||||
- 🖥️ **模型侧代价不变**:插件原有的 8 个 `terminal_*` 工具(默认关)已在上一版删除,上游等价物 `@deepseek-ai/dsh-tool-terminal` **仍未被任何 shipped bundle 默认挂载**,需要持久终端时请在 profile 的 `cordis.patch.yml` 里自行插入一行 `tool-terminal`(否则模型只有一次性 `bash` / `pwsh`)。
|
||||
- 📐 **基线**:`@deepseek-ai/dsh-*` 全部钉 `0.1.7-alpha.1`,`@deepseek-ai/cordis` peer 下限 `^4.0.3`;`ui-primitives` 图标具名导出整族改名(`Icon<Name><14|16>` → `Icon<Name>Regular` / `Medium`,26 个具名导入随之适配);会话格式 v3→v4(sidechat 边界注入改用 `plugin:dsh-better-sidebar`,tool 结果消息改 `role: 'tool'` 顶层形状,解析器同时接受新旧两种形状以兼容历史日志)。
|
||||
- 📐 **基线**:`@deepseek-ai/dsh-*` 全部钉 `0.1.7-rc.1`,`@deepseek-ai/cordis` peer 下限 `^4.0.3`;`ui-primitives` 图标具名导出整族改名(`Icon<Name><14|16>` → `Icon<Name>Regular` / `Medium`,26 个具名导入随之适配);会话格式 v3→v4(sidechat 边界注入改用 `plugin:dsh-better-sidebar`,tool 结果消息改 `role: 'tool'` 顶层形状,解析器同时接受新旧两种形状以兼容历史日志)。
|
||||
|
||||
### v0.20.0(开发线,**从未发布**)
|
||||
|
||||
> 🚫 **这一版没有发布到 npm**(npm 上 `latest` 仍是 v0.19.1):它原本是 0.1.6-alpha.2 线的正式版,开发完成后被 0.21 线直接取代,所以下面这些变更实际随 **v0.21.0-alpha.1** 一起发布。原本的定位:仅支持 **DSH 0.1.6-alpha.2+**(peer 下限 `^0.1.6-alpha.2`,CI 钉 `@deepseek-ai/dsh@0.1.6-alpha.2`)。**这是一次破坏性变更版**:0.1.5-rc.* 用户请固定 `dsh-better-sidebar@0.19.1`。适配记录见 [docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md](docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md)。
|
||||
> 🚫 **这一版没有发布到 npm**(npm 上 `latest` 仍是 v0.19.1):它原本是 0.1.6-alpha.2 线的正式版,开发完成后被 0.21 线直接取代,所以下面这些变更实际随 **v0.21.0-rc.1** 一起发布。原本的定位:仅支持 **DSH 0.1.6-alpha.2+**(peer 下限 `^0.1.6-alpha.2`,CI 钉 `@deepseek-ai/dsh@0.1.6-alpha.2`)。**这是一次破坏性变更版**:0.1.5-rc.* 用户请固定 `dsh-better-sidebar@0.19.1`。适配记录见 [docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md](docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md)。
|
||||
|
||||
- 🖥️ **终端交给 DSH 内置**:DSH 0.1.6 自带右列终端(`ui-sidebar-terminal`),所以插件删掉了整套自研终端——`pty-manager` / `agent-pty` / `pty-deps` / 8 个 `terminal_*` 工具 / xterm 视图与字体链接 / 跨会话固定终端,以及 `node-pty` 依赖、它的 `allowBuilds` 放行与安装脚本的 `-Repair` 模式。**注意**:模型因而失去跨调用持久的终端(只剩一次性 `bash` / `pwsh`);上游 `@deepseek-ai/dsh-tool-terminal` 未被内置 bundle 挂载,需要时请自行在 profile 里启用。
|
||||
- 🌐 **浏览器视图让给内置**:插件删掉 `BrowserView` / 沙箱状态条 / 嵌入性探测(含宿主 `browser.probe` 路由)与两个只配置自家 iframe 的设置项;**保留**聊天与界面的外链接管(按协议分流是宿主没有的能力),目标改为 DSH 内置的 `browser` tab 类型。
|
||||
@@ -631,7 +631,7 @@ GitHub topic [`dsh-better-sidebar`](https://github.com/topics/dsh-better-sidebar
|
||||
## 🛠️ 开发与构建
|
||||
|
||||
```sh
|
||||
pnpm install # @deepseek-ai/* devDependencies 已发布(基线 0.1.7-alpha.1,alpha dist-tag),直接解析、无需令牌
|
||||
pnpm install # @deepseek-ai/* devDependencies 已发布(基线 0.1.7-rc.1,alpha dist-tag),直接解析、无需令牌
|
||||
pnpm typecheck # tsc --noEmit
|
||||
pnpm lint # eslint .(flat config:js + typescript-eslint + react-hooks recommended)
|
||||
pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types
|
||||
|
||||
+13
-13
@@ -3,7 +3,7 @@
|
||||
> [!IMPORTANT]
|
||||
> **Built on DSH's native sidebar API** (since v0.19.0): the right column *is* DSH's own sidebar — every plugin tab type and tab body registers and opens through `ctx.sidebarRightTabs` / `ctx.sidebarRight`, every file open from the chat goes through `ctx.sidebarRight.openResource('dsh-resource://file/…')`, and the plugin **no longer draws a right panel of its own** (the old free-window capability is gone with it). The self-drawn bottom workbench and the `ctx.betterSidebar` service other plugins register against are unchanged — see the [plugin integration guide](docs/external-plugin-guide.md).
|
||||
>
|
||||
> **Since v0.21.0-alpha.1 the host support floor is DSH `0.1.7-alpha.1`** (peer floor `^0.1.7-alpha.1`; npm dist-tag `alpha`, while `latest` is still **v0.19.1**). DSH 0.1.7 ships a complete document preview of its own (spreadsheets / PDF / images / Office), so the plugin **hands every read-only preview back to the built-in** (keeping only Markdown / HTML / the editable code editor), **narrows the external-link takeover to links a tab type explicitly claims through `urlTarget`** (the three protocol-routing settings are gone), and **rewrites how it reaches settings** (preferences now live on this plugin's mount row in the profile, with the old `settings.yaml` section imported once on first boot); the file tree also gains **live refresh**. **Hosts on 0.1.6-alpha.2 or earlier should stay on v0.19.1** — note that **v0.20.0 was never published to npm**; every one of these changes shipped in v0.21.0-alpha.1.
|
||||
> **Since v0.21.0-rc.1 the host support floor is DSH `0.1.7-rc.1`** (peer floor `^0.1.7-rc.1`; npm dist-tag `alpha`, while `latest` is still **v0.19.1**). DSH 0.1.7 ships a complete document preview of its own (spreadsheets / PDF / images / Office), so the plugin **hands every read-only preview back to the built-in** (keeping only Markdown / HTML / the editable code editor), **narrows the external-link takeover to links a tab type explicitly claims through `urlTarget`** (the three protocol-routing settings are gone), and **rewrites how it reaches settings** (preferences now live on this plugin's mount row in the profile, with the old `settings.yaml` section imported once on first boot); the file tree also gains **live refresh**. **Hosts on 0.1.6-alpha.2 or earlier should stay on v0.19.1** — note that **v0.20.0 was never published to npm**; every one of these changes shipped in v0.21.0-rc.1.
|
||||
|
||||
<!-- Hero -->
|
||||
<div align="center">
|
||||
@@ -14,7 +14,7 @@
|
||||
<a href="https://github.com/omdsh-dev/DSH-better-sidebar/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/omdsh-dev/DSH-better-sidebar" /></a>
|
||||
<a href="https://opensource.org/licenses/MIT"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
|
||||
<a href="https://dshfind.com/en/plugins/omdsh-dev/DSH-better-sidebar?ref=badge"><img alt="dshfind" src="https://dshfind.com/api/badge/omdsh-dev/DSH-better-sidebar?lang=en" /></a><br /><br />
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions (v0.21.0-alpha.1): 0.1.7-alpha.1+" src="https://img.shields.io/badge/DSH-0.1.7--alpha.1%2B-4d6bfe" /></a>
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions (v0.21.0-rc.1): 0.1.7-rc.1+" src="https://img.shields.io/badge/DSH-0.1.7--rc.1%2B-4d6bfe" /></a>
|
||||
<a href="https://github.com/topics/dsh-better-sidebar"><img alt="Plugin ecosystem: GitHub topic dsh-better-sidebar" src="https://img.shields.io/badge/plugin%20ecosystem-topic%20dsh--better--sidebar-4d6bfe" /></a><br /><br />
|
||||
<img alt="File management" src="https://img.shields.io/badge/-File%20management-4d6bfe" /> <img alt="Edit & preview" src="https://img.shields.io/badge/-Edit%20%26%20preview-4d6bfe" /> <img alt="Built-in browser" src="https://img.shields.io/badge/-Built-in%20browser-4d6bfe" /> <img alt="Changes" src="https://img.shields.io/badge/-Changes-4d6bfe" /> <img alt="Background tasks" src="https://img.shields.io/badge/-Background%20tasks-4d6bfe" /> <img alt="Side Chat" src="https://img.shields.io/badge/-Side%20Chat-4d6bfe" /> <img alt="Plugin integration" src="https://img.shields.io/badge/-Plugin%20integration-4d6bfe" /><br /><br />
|
||||
<b>A dual workbench (right sidebar + bottom panel)</b> that opens its <code>ctx.betterSidebar</code> service to every plugin —<br />
|
||||
@@ -65,9 +65,9 @@
|
||||
**Prerequisites**: DSH installed (`dsh web` boots), Node.js ≥ 20, pnpm ≥ 10.
|
||||
|
||||
**Supported DSH versions**:
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions (v0.21.0-alpha.1): 0.1.7-alpha.1+" src="https://img.shields.io/badge/DSH-0.1.7--alpha.1%2B-4d6bfe" /></a>
|
||||
<a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions (v0.21.0-rc.1): 0.1.7-rc.1+" src="https://img.shields.io/badge/DSH-0.1.7--rc.1%2B-4d6bfe" /></a>
|
||||
|
||||
> 📌 **Channel and support line**: `v0.21.0-alpha.1` ships on the **alpha channel** (npm dist-tag `alpha`) and targets DSH **0.1.7-alpha.1+** (peer floor `^0.1.7-alpha.1`, CI pins `@deepseek-ai/dsh@0.1.7-alpha.1`). **npm `latest` is still `v0.19.1`** — note that `v0.20.0` was **never published to npm**; this repository jumped straight from 0.19.1 to this 0.21 line. **The floor had to move**: semver's prerelease rule means `^0.1.6-alpha.2` can never match any `0.1.7` prerelease. **Hosts on DSH 0.1.6-alpha.2 or earlier (including the 0.1.5-rc.2 that is npm's `latest`) should pin `dsh-better-sidebar@0.19.1`** — 0.1.7's breakage is large enough (the `dsh-settings` rewrite, the wholesale rename of `ui-primitives` icon exports, session format v3→v4) that this version writes no runtime compatibility layer; DSH 0.1.5-alpha.2 and earlier should likewise stay on their old versions (`0.19.0-alpha.1` / `0.18.x` / `0.17.1`).
|
||||
> 📌 **Channel and support line**: `v0.21.0-rc.1` ships on the **alpha channel** (npm dist-tag `alpha`) and targets DSH **0.1.7-rc.1+** (peer floor `^0.1.7-rc.1`, CI pins `@deepseek-ai/dsh@0.1.7-rc.1`). **Pin the DSH version exactly**: 0.1.7-rc.1 rides npm's `next` dist-tag while `alpha` currently points at 0.1.7-alpha.2 — `npm i -g @deepseek-ai/dsh@0.1.7-rc.1`. **npm `latest` is still `v0.19.1`** — note that `v0.20.0` was **never published to npm**; this repository jumped straight from 0.19.1 to this 0.21 line. **The floor had to move**: semver's prerelease rule means `^0.1.6-alpha.2` can never match any `0.1.7` prerelease. **Hosts on DSH 0.1.6-alpha.2 or earlier (including the 0.1.5-rc.3 that is npm's `latest`) should pin `dsh-better-sidebar@0.19.1`** — 0.1.7's breakage is large enough (the `dsh-settings` rewrite, the wholesale rename of `ui-primitives` icon exports, session format v3→v4) that this version writes no runtime compatibility layer; DSH 0.1.5-alpha.2 and earlier should likewise stay on their old versions (`0.19.0-alpha.1` / `0.18.x` / `0.17.1`).
|
||||
|
||||
```sh
|
||||
dsh plugin --profile web add dsh-better-sidebar@alpha
|
||||
@@ -95,7 +95,7 @@ If anything fails, check the troubleshooting table in the README at https://gith
|
||||
dsh plugin --profile web add dsh-better-sidebar@alpha
|
||||
```
|
||||
|
||||
or bump the version in `~/.dsh/profiles/web/package.json` to the matching npm version (stable line `"^0.19.1"`; this alpha line `"^0.21.0-alpha.1"`) and run `pnpm install`. Then hard-refresh the browser (Cmd/Ctrl+Shift+R) — client changes do not need a DSH restart.
|
||||
or bump the version in `~/.dsh/profiles/web/package.json` to the matching npm version (stable line `"^0.19.1"`; this alpha line `"^0.21.0-rc.1"`) and run `pnpm install`. Then hard-refresh the browser (Cmd/Ctrl+Shift+R) — client changes do not need a DSH restart.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -133,7 +133,7 @@ To debug local changes or track the dev branch, point the dependency at a local
|
||||
5. Restart DSH and hard-refresh
|
||||
```
|
||||
|
||||
Update: `git pull && pnpm install && pnpm build` → just hard-refresh the browser (client changes hot-reload; only host-half changes need a DSH restart). To switch back to the npm channel, restore the matching npm version (stable line `"^0.19.1"`; this alpha line `"^0.21.0-alpha.1"`) and re-run `pnpm install`.
|
||||
Update: `git pull && pnpm install && pnpm build` → just hard-refresh the browser (client changes hot-reload; only host-half changes need a DSH restart). To switch back to the npm channel, restore the matching npm version (stable line `"^0.19.1"`; this alpha line `"^0.21.0-rc.1"`) and re-run `pnpm install`.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -263,23 +263,23 @@ The GitHub topic [`dsh-better-sidebar`](https://github.com/topics/dsh-better-sid
|
||||
<a href="https://github.com/user-attachments/assets/946f7028-4967-461e-a750-d1b5056b62d0"><img width="33%" alt="Service API base screenshot" src="https://github.com/user-attachments/assets/946f7028-4967-461e-a750-d1b5056b62d0" /></a>
|
||||
</div>
|
||||
|
||||
**Supported DSH versions**: <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions (v0.21.0-alpha.1): 0.1.7-alpha.1+" src="https://img.shields.io/badge/DSH-0.1.7--alpha.1%2B-4d6bfe" /></a> · full release history on the [Releases](https://github.com/omdsh-dev/DSH-better-sidebar/releases) page
|
||||
**Supported DSH versions**: <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions (v0.21.0-rc.1): 0.1.7-rc.1+" src="https://img.shields.io/badge/DSH-0.1.7--rc.1%2B-4d6bfe" /></a> · full release history on the [Releases](https://github.com/omdsh-dev/DSH-better-sidebar/releases) page
|
||||
|
||||
### v0.21.0-alpha.1
|
||||
### v0.21.0-rc.1
|
||||
|
||||
> 🧪 **alpha channel** (npm dist-tag `alpha`, install `dsh-better-sidebar@alpha`; npm `latest` is still **v0.19.1**): supports **DSH 0.1.7-alpha.1+** only (peer floor `^0.1.7-alpha.1`, CI pins `@deepseek-ai/dsh@0.1.7-alpha.1`). **Hosts on DSH 0.1.6-alpha.2 or earlier should stay on v0.19.1** — 0.1.7 moves three hard contracts (the settings service, the icon named exports and the session format) and this version writes no runtime compatibility layer. ⚠️ **The previous v0.20.0 was never published to npm**: its terminal / browser handover ships here too, so npm goes straight from 0.19.1 to this version.
|
||||
> 🧪 **alpha channel** (npm dist-tag `alpha`, install `dsh-better-sidebar@alpha`; npm `latest` is still **v0.19.1**): supports **DSH 0.1.7-rc.1+** only (peer floor `^0.1.7-rc.1`, CI pins `@deepseek-ai/dsh@0.1.7-rc.1`). **Hosts on DSH 0.1.6-alpha.2 or earlier should stay on v0.19.1** — 0.1.7 moves three hard contracts (the settings service, the icon named exports and the session format) and this version writes no runtime compatibility layer. ⚠️ **The previous v0.20.0 was never published to npm**: its terminal / browser handover ships here too, so npm goes straight from 0.19.1 to this version.
|
||||
|
||||
- 🗂️ **Read-only file previews handed to DSH's document preview**: DSH 0.1.7's `ui-sidebar-documentpreview` ships its own spreadsheet / PDF / image / Office rendering (host-side Office→PDF conversion, worker-backed spreadsheet tables, image / PDF zoom, per-directory auto-refresh), so the plugin deleted its `image` / `pdf` / `binary-download` viewers and **refuses** those extensions in `editor.canOpen` — `xlsx xls xlsb xlt xltx xltm ods ots fods csv tsv pdf png jpg jpeg gif webp svg bmp ico avif doc docx dot dotx ppt pptx` — handing the file address back to the host. **Three things the host does not have stay in the plugin**: Markdown (its own renderer), HTML (its own sandboxed preview plus the `htmlViewerNoSandbox` / `htmlViewerDefaultUnsafe` safety switches), and the **editable** text / code editor (the built-in ones are read-only previews); unknown binaries (`.zip` / `.wasm`) still land on the code editor's download pane after the binary check, so nothing regresses.
|
||||
- 🗂️ **Read-only file previews handed to DSH's document preview**: DSH 0.1.7's `ui-sidebar-documentpreview` ships its own spreadsheet / PDF / image / Office rendering (host-side Office→PDF conversion, worker-backed spreadsheet tables, image / PDF zoom, per-directory auto-refresh), so the plugin deleted its `image` / `pdf` / `binary-download` viewers and **refuses** those extensions in `editor.canOpen` — `xlsx xls csv tsv fods pdf png jpg jpeg gif webp svg bmp ico doc docx ppt pptx` — handing the address back to the host. **rc.1 takes nine of them back**: `xlsb` / `xlt` / `xltx` / `xltm` / `ots` / `dot` / `dotx` / `avif` / `ods` have **no host renderer at all** (opening one only said "preview is not available"), yet before the handover they reached the plugin's download pane — a regression we introduced ourselves in the previous version. The plugin's `code` catch-all claims them again. `fods` stays handed over (the host shows that flat XML as plain text, which beats a download pane). — handing the file address back to the host. **Three things the host does not have stay in the plugin**: Markdown (its own renderer), HTML (its own sandboxed preview plus the `htmlViewerNoSandbox` / `htmlViewerDefaultUnsafe` safety switches), and the **editable** text / code editor (the built-in ones are read-only previews); unknown binaries (`.zip` / `.wasm`) still land on the code editor's download pane after the binary check, so nothing regresses.
|
||||
- 🔗 **External-link takeover narrowed**: the three protocol-routing external-link settings are gone (with their keys in all 20 locale dictionaries). The plugin now takes over **only links a tab type explicitly claims through `urlTarget`** and lets everything else through for the host to route (DSH 0.1.7 adds the user setting `linkOpening`, deciding whether prose links open in the sidebar or a new tab); **when nothing claims a link it does not preventDefault**; a successful claim whose target type is unavailable at open time falls back to `window.open(url, '_blank', 'noopener,noreferrer')` — which also fixes a real regression from the previous version: http links inside plugin-drawn markdown (Side Chat transcripts / editor previews / diff panes) did nothing when clicked. Separately, the host's `browser` kind is **no longer mounted in the Web profile** (0.1.7 mounts it in the desktop profile only).
|
||||
- ⚙️ **Settings surface rewritten + preferences imported automatically**: DSH 0.1.7 removed the registrable settings namespace in favour of **looking a form up by the plugin Loader row's entry id** (`SettingsForms`: only `describe` / `update` / `replace` / `mutate` / `configure` remain). Plugin preferences therefore live in the **profile's cordis patch document** (i.e. this plugin's mount row), not in `~/.dsh/settings.yaml`; the schema comes from the plugin module's exported `Config` (this version merges the user preferences into `Config` and marks every preference field `meta.volatile = true` — **that single flag is the entire "settings apply live, without remounting the plugin" mechanism**). **Your settings are not lost**: on first boot the plugin imports the `dsh-better-sidebar` section of the old `settings.yaml` / `settings.yaml.imported` once (only while that row still has no user values, and only fields the current schema still declares). The entry id is **discovered at runtime** (this bundle defaults to `better-sidebar`; an aggregate bundle mounts it under a different id) and never hardcoded.
|
||||
- 🔄 **Live-refreshing file tree**: the plugin takes over the built-in Files page, so the host's own per-directory watch cannot cover that tree — this version adds `/sidebar/ws/fs-watch`: the client reports the directories it has **expanded**, the host watches exactly those with `fs.watch` (150ms debounce, a 64-handle cap per connection, paths going through the same workspace fence as `fs.tree`), and a change re-lists just that level; collapsing unsubscribes. Before this, the tree stayed stale until a manual refresh.
|
||||
- 🐛 **Session following fixed**: the plugin used to read a **non-existent `SessionListState.current` field** (its own type mirror invented it, so the compiler never complained), which meant per-session persistence was never actually bound and the narrow-viewport park gate was always false. It now uses DSH 0.1.7's `ctx.sidebarRight.mounted` (set only when the column really switches to another session).
|
||||
- 🖥️ **The model-side cost is unchanged**: the plugin's own 8 `terminal_*` tools (off by default) were already removed in the previous version, and the upstream equivalent `@deepseek-ai/dsh-tool-terminal` is **still not mounted by any shipped bundle** — add a `tool-terminal` row to your profile's `cordis.patch.yml` when you need a persistent terminal (otherwise the model only has one-shot `bash` / `pwsh`).
|
||||
- 📐 **Baseline**: every `@deepseek-ai/dsh-*` pins `0.1.7-alpha.1`, with the `@deepseek-ai/cordis` peer floor at `^4.0.3`; `ui-primitives` renamed its whole family of named icon exports (`Icon<Name><14|16>` → `Icon<Name>Regular` / `Medium`, 26 named imports adapted); session format v3→v4 (the Side Chat boundary injection now uses `plugin:dsh-better-sidebar`, and tool-result messages use the top-level `role: 'tool'` shape, with parsers accepting both old and new shapes for historical logs).
|
||||
- 📐 **Baseline**: every `@deepseek-ai/dsh-*` pins `0.1.7-rc.1`, with the `@deepseek-ai/cordis` peer floor at `^4.0.3`; `ui-primitives` renamed its whole family of named icon exports (`Icon<Name><14|16>` → `Icon<Name>Regular` / `Medium`, 26 named imports adapted); session format v3→v4 (the Side Chat boundary injection now uses `plugin:dsh-better-sidebar`, and tool-result messages use the top-level `role: 'tool'` shape, with parsers accepting both old and new shapes for historical logs).
|
||||
|
||||
### v0.20.0 (dev line, **never published**)
|
||||
|
||||
> 🚫 **This version never reached npm** (npm `latest` is still v0.19.1): it was meant to be the stable release on the 0.1.6-alpha.2 line, but the 0.21 line replaced it before release, so everything below actually shipped in **v0.21.0-alpha.1**. Its original positioning: supports **DSH 0.1.6-alpha.2+** only (peer floor `^0.1.6-alpha.2`, CI pins `@deepseek-ai/dsh@0.1.6-alpha.2`). **This is a breaking-change release**: hosts on 0.1.5-rc.* should pin `dsh-better-sidebar@0.19.1`. See [docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md](docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md) for the adaptation record.
|
||||
> 🚫 **This version never reached npm** (npm `latest` is still v0.19.1): it was meant to be the stable release on the 0.1.6-alpha.2 line, but the 0.21 line replaced it before release, so everything below actually shipped in **v0.21.0-rc.1**. Its original positioning: supports **DSH 0.1.6-alpha.2+** only (peer floor `^0.1.6-alpha.2`, CI pins `@deepseek-ai/dsh@0.1.6-alpha.2`). **This is a breaking-change release**: hosts on 0.1.5-rc.* should pin `dsh-better-sidebar@0.19.1`. See [docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md](docs/plans/2026-09-21-dsh-0.1.6-alpha.2-adaptation.md) for the adaptation record.
|
||||
|
||||
- 🖥️ **Terminal handed to DSH's built-in**: DSH 0.1.6 ships its own right-column terminal (`ui-sidebar-terminal`), so the plugin deleted its whole terminal stack — `pty-manager` / `agent-pty` / `pty-deps` / the 8 `terminal_*` tools / the xterm view and font-linking / cross-session terminal pinning — along with the `node-pty` dependency, its `allowBuilds` grant and the installer's `-Repair` mode. **Note**: the model therefore loses a cross-call persistent terminal (only one-shot `bash` / `pwsh` remain); the upstream `@deepseek-ai/dsh-tool-terminal` is not mounted by any shipped bundle, so enable it yourself in the profile when you need it.
|
||||
- 🌐 **Browser view handed to the built-in**: the plugin deleted `BrowserView` / the sandbox status bar / the embeddability probe (including the host's `browser.probe` route) and the two settings that only configured its own iframe; it **keeps** the external-link takeover in the chat and UI (protocol-based routing is the capability the host does not have), now targeting DSH's built-in `browser` tab type.
|
||||
@@ -627,7 +627,7 @@ The dashed cards at the end of the "Sidebar content" / "File viewers" grids in t
|
||||
## 🛠️ Development & Build
|
||||
|
||||
```sh
|
||||
pnpm install # @deepseek-ai/* devDependencies resolve (baseline 0.1.7-alpha.1, alpha dist-tag) — no token needed
|
||||
pnpm install # @deepseek-ai/* devDependencies resolve (baseline 0.1.7-rc.1, alpha dist-tag) — no token needed
|
||||
pnpm typecheck # tsc --noEmit
|
||||
pnpm lint # eslint . (flat config: js + typescript-eslint + react-hooks recommended)
|
||||
pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> 面向 **消费插件开发者**:如何让你的插件向 better-sidebar 注册新的侧边栏页面(tab)和文件类型预览器。
|
||||
>
|
||||
> 适用版本:**v0.4.0+**(`ctx.betterSidebar` 服务);声明式设置 **v0.4.1+**;text/number 设置行 **v0.11.0+**;badge/生命周期/定向打开/插件设置/版本探测 **v0.12.0+**;select 设置行(`settingSelect`)与外链认领(`urlTarget`)**v0.13.0+**;统一 `@deepseek-ai/cordis` 类型基底 **v0.15.2+**。当前版本 **v0.21.0-alpha.1**(npm dist-tag `alpha`;`latest` 仍是 **v0.19.1**,peer 下限 `^0.1.7-alpha.1`,仅支持 DSH **0.1.7-alpha.1+**)。**v0.19.0 移除了自绘右侧面板与自由窗口**(见 §0、§11);**自 v0.20.0 开发线起**(**注意:0.20.0 从未发布到 npm,这些变更全部落在 v0.21.0-alpha.1**)插件**移除了自带的终端**(宿主 0.1.6 的 `ui-sidebar-terminal` 取代,见 §4.4)、**移除了终端固定(pin)**,并在 0.1.7 上**把浏览器视图与只读文件预览整体让给宿主**(`ui-sidebar-browser` / `ui-sidebar-documentpreview`,见 §4.4、§5.4)、**收敛了外链接管**(见 §4.1)、**重写了设置接入面**(`SettingsForms`,见 §8.2)、**给文件树加了实时刷新**(见 §10);同时**删除了轮尾产物行接管**(DSH 0.1.6 把 `conversation.chat.turnTail` 从 chain 改成只能追加的 list,替换语义不复存在)。
|
||||
> 适用版本:**v0.4.0+**(`ctx.betterSidebar` 服务);声明式设置 **v0.4.1+**;text/number 设置行 **v0.11.0+**;badge/生命周期/定向打开/插件设置/版本探测 **v0.12.0+**;select 设置行(`settingSelect`)与外链认领(`urlTarget`)**v0.13.0+**;统一 `@deepseek-ai/cordis` 类型基底 **v0.15.2+**。当前版本 **v0.21.0-rc.1**(npm dist-tag `alpha`;`latest` 仍是 **v0.19.1**,peer 下限 `^0.1.7-rc.1`,仅支持 DSH **0.1.7-rc.1+**)。**v0.19.0 移除了自绘右侧面板与自由窗口**(见 §0、§11);**自 v0.20.0 开发线起**(**注意:0.20.0 从未发布到 npm,这些变更全部落在 v0.21.0-rc.1**)插件**移除了自带的终端**(宿主 0.1.6 的 `ui-sidebar-terminal` 取代,见 §4.4)、**移除了终端固定(pin)**,并在 0.1.7 上**把浏览器视图与只读文件预览整体让给宿主**(`ui-sidebar-browser` / `ui-sidebar-documentpreview`,见 §4.4、§5.4)、**收敛了外链接管**(见 §4.1)、**重写了设置接入面**(`SettingsForms`,见 §8.2)、**给文件树加了实时刷新**(见 §10);同时**删除了轮尾产物行接管**(DSH 0.1.6 把 `conversation.chat.turnTail` 从 chain 改成只能追加的 list,替换语义不复存在)。
|
||||
> 权威代码:`src/client/service.ts`(服务实现)、`src/client/builtins/`(内置 5 tab + 3 viewer 参考实现)、`lib/types/client/service.d.ts`(类型声明)。
|
||||
> 仓库开发规则(硬约束 / CI / 发版)见 [AGENTS.md](../AGENTS.md)。
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
| 布局持久化 | 原生栏的布局**只在内存**(刷新后回到折叠默认),插件自己的底部工作台仍然持久化 |
|
||||
| 跨会话打开 | 目标会话的右侧栏 store 未挂载时,打开会排队到该会话上屏后重放 |
|
||||
| 内置类型接管 | 插件的 `editor` 类型以 `extension` 优先级认领 `dsh-resource://file/**`(压过内置 `ui-sidebar-documentpreview` 的 `text` 预览——即 `fallback` 带),并接管内置 `files` 页面 kind(`openTab('files')` 打开插件的文件树);插件卸载/禁用时内置实现自动复位。**但认领是有选择的**:宿主自己的文档预览已经覆盖的格式(表格 / PDF / 图片 / Office,清单见 §5.4)由 `editor.canOpen` 主动**拒绝**,地址交回内置 `text` 档 |
|
||||
| 文件树实时刷新(v0.21.0-alpha.1+) | 插件接管了内置 `files` 页,所以宿主自己的按目录 watch 覆盖不到这棵树——插件自带一条 `/sidebar/ws/fs-watch` socket:客户端上报**已展开**的目录集,宿主侧按目录 `fs.watch`(150ms 去抖、每连接上限 64 个句柄),变动后只让那一层缓存失效并重列;目录折叠即退订。路径仍走 `fs.tree` 同一道 workspace fence |
|
||||
| 链接接管(v0.21.0-alpha.1+) | DOM 层只接管**有类型通过 `urlTarget` 声明认领**的外链(Ctrl/Cmd/Shift/Alt 点击一律放行);一个都没认领到时**不阻止默认行为**,交回宿主。见 §4.1 的 `urlTarget` |
|
||||
| 文件树实时刷新(v0.21.0-rc.1+) | 插件接管了内置 `files` 页,所以宿主自己的按目录 watch 覆盖不到这棵树——插件自带一条 `/sidebar/ws/fs-watch` socket:客户端上报**已展开**的目录集,宿主侧按目录 `fs.watch`(150ms 去抖、每连接上限 64 个句柄),变动后只让那一层缓存失效并重列;目录折叠即退订。路径仍走 `fs.tree` 同一道 workspace fence |
|
||||
| 链接接管(v0.21.0-rc.1+) | DOM 层只接管**有类型通过 `urlTarget` 声明认领**的外链(Ctrl/Cmd/Shift/Alt 点击一律放行);一个都没认领到时**不阻止默认行为**,交回宿主。见 §4.1 的 `urlTarget` |
|
||||
| path 种子的去向(v0.19.2+) | `path` seed 的含义**跟随类型**:只有 `editor`(唯一认领 `dsh-resource://file/**` 的类型)把 path 转成资源地址打开(文件落在编辑器);**其余类型保留页面型打开**,path 随导航 params 落到合成记录的 `tab.path` 供组件消费——组件型 tab 的 path seed 不会被改道到文件编辑器(v0.19.0/0.19.1 上一切 path seed 都被改道,组件从未挂载,#632) |
|
||||
| 终端(已交还宿主) | 插件**不再提供任何终端**:宿主 0.1.6 起自带 `ui-sidebar-terminal`(kind `terminal`),插件侧 PTY 栈与 `terminal_*` 工具整体删除。这里不再有「插件终端数量上限」这类语义 |
|
||||
| 底部工作台的开合 | 落到底部工作台的打开一律展开它(新建与聚焦都算),因此 `openTab` 的落点永远可见;开合按钮注册在 DSH 会话头的 utilities 槽(`conversation.session.header.utilities`),不在插件自己的宿主里 |
|
||||
@@ -226,7 +226,7 @@ interface TabDescriptor {
|
||||
*
|
||||
* **没被认领的链接一律放行**(插件不 preventDefault):DSH 0.1.7 起正文链接的
|
||||
* 去向由宿主的用户设置 `linkOpening` 决定(进侧栏还是新标签页),插件自绘
|
||||
* markdown 里则走 `<a>` 自己的默认行为。**v0.21.0-alpha.1 起那三个「按协议分流」
|
||||
* markdown 里则走 `<a>` 自己的默认行为。**v0.21.0-rc.1 起那三个「按协议分流」
|
||||
* 的旧设置项已删除**(旧文档里的键会被忽略),本插件不再有任何接管总闸——
|
||||
* 认领与否完全由你的 urlTarget 决定;Ctrl/Cmd/Shift/Alt 点击永远绕过接管。
|
||||
* 认领成功但目标类型在打开那一刻已不可用(插件卸载 / 被设置关闭)时,点击
|
||||
@@ -415,7 +415,7 @@ ctx.effect(() => {
|
||||
|
||||
你的 `id` 不可与上述重复,否则 `registerTab` 抛 `"tab type \"X\" already registered"`。
|
||||
|
||||
**自 v0.20.0 开发线起删除的类型(迁移提示;0.20.0 从未发布,变更落在 v0.21.0-alpha.1)**:
|
||||
**自 v0.20.0 开发线起删除的类型(迁移提示;0.20.0 从未发布,变更落在 v0.21.0-rc.1)**:
|
||||
|
||||
| 原 id | 现状 | 你该怎么做 |
|
||||
|---|---|---|
|
||||
@@ -504,7 +504,9 @@ interface FileViewerProps {
|
||||
>
|
||||
> ⚠️ **让给宿主的格式(重要,影响你的 viewer 能不能被调用)**:DSH 0.1.7 的 `ui-sidebar-documentpreview` 自带 code / excel(xlsx,xls,csv,tsv) / office(宿主侧转 PDF)/ pdf / image / html / markdown / text 预览,并带缩放与**按目录自动刷新**——本插件原有的 image / pdf / binary-download 三个 viewer 描述符因此删除。更重要的是**路由**:插件的 `editor` 类型在 `canOpen` 里对下列扩展名一律返回 false(`src/client/native/index.ts` 的 `HOST_OWNED_EXTS`),把地址让给内置 `text` 档,**根本不会进入本插件的 `matchFileViewer`**:
|
||||
>
|
||||
> `xlsx xls xlsb xlt xltx xltm ods ots fods csv tsv pdf png jpg jpeg gif webp svg bmp ico avif doc docx dot dotx ppt pptx`
|
||||
> `xlsx xls csv tsv fods pdf png jpg jpeg gif webp svg bmp ico doc docx ppt pptx`
|
||||
>
|
||||
> **这份清单现在是「宿主渲染器实际覆盖的集合」,不多不少**:`v0.21.0-rc.1` 收回了 9 个宿主其实**没有渲染器**的扩展名(`xlsb` / `xlt` / `xltx` / `xltm` / `ots` / `dot` / `dotx` / `avif` / `ods`——前两个落在宿主的 `document/unviewable.ts`「已知二进制、无渲染器」表里,其余落回 text 兜底后按二进制判定失败,一律只有「暂不支持预览」),它们重新由插件的 `code` catch-all 认领并落到下载面板。`fods` 保留让出:宿主会用纯文本显示那段扁平 XML,比下载面板有用。`tests/native-surface.spec.ts` 双向钉住这条边界(宿主能渲染的必须拒绝、宿主不能渲染的必须认领)。
|
||||
>
|
||||
> 后果:**你注册这些扩展名的 viewer 仍然合法(注册表不冻结 id,`matchFileViewer` 也会命中),但通过聊天 / 文件树 / 编辑器的正常文件打开路径拿不到它们**——那是宿主的文档预览。要在这些格式上做文章,只能自己在页面里渲染(或像 [Office 预览插件](https://github.com/HuanLinOTO/dsh-plugin-better-sidebar-plugin-office) 那样在宿主接管前的旧版本上生效)。**可用的是 md/markdown / html/htm 与 code catch-all 三类**(外加任何不在上表里的扩展名)。未知二进制(`.zip` / `.wasm`)仍走 code 认领 → `fs.read` 判 binary → head 重匹配无 sniffer → 编辑器渲染下载面板,功能不回归。
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
> 适配对象:`dsh-better-sidebar` v0.20.0 开发线(支持 DSH 0.1.6-alpha.2)→ **v0.21.0-alpha.1(仅支持 DSH 0.1.7-alpha.1+)**。
|
||||
> 基线标签:`dsh-v0.1.6-alpha.2`(`ddefc45fbc`)→ `dsh-v0.1.7-alpha.1`(`c36a83ff6b`),相隔 **1299 个 commit / 4754 个文件变更**。
|
||||
> 本文记录**为什么这么改**与**改完的证据**;规则性结论沉淀在仓库根 `AGENTS.md` §3。
|
||||
>
|
||||
> ⚠️ **后续**:`v0.21.0-alpha.1` **从未发布到 npm**——这条开发线随后又适配到 **0.1.7-rc.1**,peer 下限收到 `^0.1.7-rc.1`,整个 0.21 线的变更一并随 **v0.21.0-rc.1** 出货。本文保留为 alpha.1 阶段的原始记录(结论仍然有效),最新状态见 [2026-09-23-dsh-0.1.7-rc.1-adaptation.md](2026-09-23-dsh-0.1.7-rc.1-adaptation.md)。
|
||||
|
||||
## 1. 怎么做的(方法与边界)
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# DSH 0.1.7-rc.1 适配记录
|
||||
|
||||
> 适配对象:`dsh-better-sidebar` v0.21.0-alpha.1(支持 DSH 0.1.7-alpha.1)→ **v0.21.0-rc.1(仅支持 DSH 0.1.7-rc.1+)**。
|
||||
> 基线标签:`dsh-v0.1.7-alpha.1`(`c36a83ff6b`)→ `dsh-v0.1.7-rc.1`(`46a7f68b09`),相隔 **318 个 commit / 1361 个文件变更**(中间还跨过一个没适配的 `0.1.7-alpha.2`)。
|
||||
> 本文记录**为什么这么改**与**改完的证据**;规则性结论沉淀在仓库根 `AGENTS.md` §3(新增 §3.4 第 12 条)。上一阶段见 [2026-09-22-dsh-0.1.7-alpha.1-adaptation.md](2026-09-22-dsh-0.1.7-alpha.1-adaptation.md)。
|
||||
|
||||
## 1. 怎么做的(方法与边界)
|
||||
|
||||
先 `git fetch` 把 `dsh-v0.1.7-alpha.2` / `dsh-v0.1.7-rc.1` 两个 tag 取进本地 DSH 克隆,然后按「与本插件相交的 surface」分五路并行侦察:启动预检与展示元数据、`ui-primitives` 导出面、会话/会话快照/流式契约、平台契约(file-address / settings / webserver / gateway / 客户端 bundle 装载)、宿主文档预览能力盘点。**五路的结论一致指向「本版是发行候选收敛版,不是新一轮重写」**:绝大多数「变更文件」是 `package.json` 的版本号与 `workspace:^` → `workspace:*|~` 改写,`src/` 逐字未变。
|
||||
|
||||
侦察子的报告一律当线索处理,本轮**亲自复核**了四件事:`DiffBlockLabels` 的字段增删(读两个 tag 的 `DiffBlock.tsx`)、宿主渲染器覆盖的扩展名集合(读 `documentpreview/src/client/*/index.ts` 与 `document/unviewable.ts`)、`MAX_DESCRIBED_ENTRIES` 的真实归属(三 tag 逐字比对 `GuideBody.tsx`)、以及 icon 具名导入的真实条数(脚本提取导入面,得 25 而不是文档里记的 26)。
|
||||
|
||||
## 2. 本版到底改了什么
|
||||
|
||||
**零 `src/` 变化**(只有版本号与依赖面改写):`ui-sidebar-right`、`ui-slots`、`ui-settings`、`dsh-settings` 与 loader 的 volatile 机制、`webserver` + `client/connection` 的鉴权、`packages/session` 全线(**会话格式仍是 v4**,没有 v4→v5)、`llm` 的 `MessageSourceMap`、`subagent`(descriptor 仍是 v3)、`ui-conversation` 的槽锚点与 `turnTail`、客户端 externals 白名单(9 个 specifier 逐字不变)、`util/workspace-path` 的 `fileAddressFor`/`parseFileAddress`、`plugin-artwork.tsx` / `package-meta.ts` / `scripts/verify-package-meta.ts`(后两者逐字相同,所以图标与 locale 的三条硬规则、以及「没有任何尺寸校验」都仍然成立)。
|
||||
|
||||
真实变化只有两类:
|
||||
|
||||
1. **`ui-primitives` 的代码卡**(唯一会编译失败的一处):新增 `CodeToolbar.tsx`(alpha.1 上不存在),其 `CodeToolbarLabels` 的 `codeLabel` / `wrapLabel` / `unwrapLabel` **三个必填**;`DiffBlockLabels` / `ReadBlockLabels` 改为继承它,且**删除了 `DiffBlockLabels.files`**。icon 模块只**新增**了 `IconUsersOutline{Artwork,Regular,Medium}`,无删除、无改名、既有 icon 默认尺寸也没动。
|
||||
2. **启动期 peer 预检**(rc.1 新文件 `packages/boot/app-boot/src/plugin-compatibility.ts`):见 §4。
|
||||
|
||||
另外 rc.1 把 **vendor 补丁**一起抬了:`@deepseek-ai/cordis` 4.0.3 → 4.0.4、`schemastery` 3.18.3 → 3.18.4、`cordis-plugin-group` 1.0.3 → 1.0.4、`cordis-plugin-include` 1.0.8 → 1.0.9(loader 已是 1.0.5)。这是上游 workspace-release-ranges 政策的直接后果——包内 DSH 引用发布成**精确版本**,vendor 用 `~`。
|
||||
|
||||
## 3. 插件侧改了什么
|
||||
|
||||
### 3.1 版本与依赖面
|
||||
`package.json` / `dsh.plugin.json` / `src/client/service.ts` 的 `SIDEBAR_SERVICE_VERSION` 同步到 `0.21.0-rc.1`;14 个 DSH peer 从 `^0.1.7-alpha.1` 收到 `^0.1.7-rc.1`;28 个 devDependency 钉 `0.1.7-rc.1`。
|
||||
|
||||
**只改这两处不够**:`pnpm peers check` 一次报出四类 unmet peer——`cordis-plugin-group` / `-include` 是 `dsh-app-boot` / `dsh-config-editor` 的**传递 peer**,pnpm 会继续沿用 lockfile 里的旧副本。按 AGENTS.md §3.4 第 8 条的既有做法,把 `@deepseek-ai/cordis@4.0.4`、`@deepseek-ai/cordis-plugin-group@1.0.4`、`@deepseek-ai/cordis-plugin-include@1.0.9` 三个**显式钉进 devDependencies**(并抬 `schemastery` 到 `^3.18.4`)后收敛。
|
||||
|
||||
### 3.2 代码卡标签(唯一的编译破坏)
|
||||
`src/client/SideChatView.tsx` 的 diff / read 两个字典补上三个新键、删掉 `files`;`sideChatBlockFiles` 词条从 20 份词典中删除。**不放进 `shared`**:`TerminalBlockLabels` 不继承 `CodeToolbarLabels`,而 `terminal: { ...shared }` 是新鲜对象字面量,会触发多余属性检查。
|
||||
|
||||
**红证据**:切换 devDeps 到 rc.1 后 `pnpm typecheck` 报
|
||||
`Type '{ files: …; copy: string; … }' is missing the following properties from type 'DiffBlockLabels': codeLabel, wrapLabel, unwrapLabel`(`src/client/SideChatView.tsx(337,40)`);改完转绿。
|
||||
|
||||
### 3.3 全面采用宿主的新代码卡
|
||||
`src/client/markdown-labels.tsx` 的 `labels.code` 补 `toolbarLabels`,措辞照抄宿主(`codeBlock.title|wrap|unwrap`),四个 markdown 渲染点一并从旧的 `data-code-block-banner` info banner 切到新的 code card。`MarkdownCopyLabels` 由 2 字段扩到 5 字段,三个构造点(`TextEditor.tsx` / `DiffPane.tsx` / `SideChatView.tsx`)与两个测试 fixture 同步。
|
||||
|
||||
**这个改动带出一个真实回归,且当场被测试抓到**:新 card 对没有语法高亮的语言显示 `codeLabel`,而 mermaid 正是没有 shiki grammar 的语言——**info string 不再进 DOM**,于是 `src/client/mermaid.tsx` 里那条「读 banner 第一个元素的文本是不是 `mermaid`」的探测恒假,三个 `tests/mermaid-markdown.spec.tsx` 用例立刻红(`the mermaid fence must be swapped for a diagram: expected null not to be null`)。改为按**围栏正文**匹配:`splitMermaidBlocks(text)` 取出 mermaid 正文集合,与 `block.querySelector('code')` 的文本两侧 `trimEnd()` 后比对;`language-mermaid` 类名作为第一探针保留。
|
||||
|
||||
### 3.4 收回 9 个过度让出的扩展名
|
||||
上一版把 27 个扩展名整体让给宿主,但其中 9 个宿主**根本没有渲染器**:`avif` / `ods` 落在 `document/unviewable.ts` 的「已知二进制、无渲染器」表里直接走空状态,`xlsb` / `xlt` / `xltx` / `xltm` / `ots` / `dot` / `dotx` 落回 text 兜底后按二进制判定失败、同样是空状态。**这些文件在让出之前是走插件兜底显示下载面板的**,所以这是上一版自己引入的用户可见回归(rc.1 没有修复它)。现从 `HOST_OWNED_EXTS` 移除这 9 个,剩 18 个;`fods` 继续让出(宿主用纯文本显示这段扁平 XML,比下载面板有用)。
|
||||
|
||||
`canOpen` 此前**零测试覆盖**,这正是回归没被发现的原因;补了双向守护(`tests/native-surface.spec.ts`)。**红证据**:把旧的 27 项清单临时还原后,新用例报 `AssertionError: macro.xlsb: expected false to be true`。
|
||||
|
||||
### 3.5 peer 范围守护
|
||||
`tests/market-manifest.spec.ts` 增加一条:每个 `@deepseek-ai/dsh*` peer 必须是 `^0.1.7-<预发布>` 形式的浮动范围。理由见 §4——**失败是静默的**,而 `pnpm peers check` 看不到它(它校验解析出来的 dev 树,不校验宿主会读的范围形状)。
|
||||
|
||||
### 3.6 钉版与文档
|
||||
CI 的 `npm install -g` 与 `scripts/e2e-common.sh` 的 `DSH_NPX_SPEC` / `DSH_EXPECT_VERSION` 都钉到 `0.1.7-rc.1`,并在注释里写明**必须写精确版本号**:rc.1 上线时 npm `alpha` 指的是 **0.1.7-alpha.2**,rc.1 走的是 `next`。README / README_EN 的 6 处 shields badge、支持线段落、让出扩展名清单与「基线」段同步;指南头部版本行同步;AGENTS.md 见 §6。
|
||||
|
||||
## 4. rc.1 新增的启动期 peer 预检(本版最值得记住的一处)
|
||||
|
||||
`plugin-compatibility.ts` 遍历 profile 行的 `peerDependencies`,对名字为 `@deepseek-ai/dsh` 或以 `@deepseek-ai/dsh-` 开头的条目跑 `semver.satisfies(宿主版本, range, { includePrerelease: true })`;不满足就把整行 `row.disabled = true`,只在 stderr 留一行。四个要点:
|
||||
|
||||
- **只读 peer**,`engines.dsh` 与 `dsh.manifestVersion` 仍然零读者(`package-manifest` 的 README 在 rc.1 逐字未变,它自己的措辞已经落后于代码);
|
||||
- `peerDependenciesMeta.optional` **没有任何豁免**——我们那条 optional 的 `@deepseek-ai/dsh-client-ui-sidebar-right` 照样参与判定;
|
||||
- `includePrerelease` 被强制打开,判定比 npm **宽松**(`^0.1.6-alpha.2` 也能满足 `0.1.7-rc.1`),但**精确版本号或没有预发布子句的范围(如 `^0.1.7`)一定不过**;
|
||||
- 豁免只能写 profile 自己的 `compatibility.json`,没有全局开关也没有环境变量。
|
||||
|
||||
**因此本版的 peer 下限是刻意收紧的**:`0.21.0-alpha.1` 从未发布到 npm(真实用户为零),而修掉 `DiffBlockLabels` 之后同一份代码在 alpha.1 上会崩(alpha.1 的 `DiffBlock` 仍读已被上游删除的 `labels.files`)。声明与真机验证过的宿主一致,比声明一条跑不通的支持线更安全;rc.1 起「声明过宽」的代价还从「可能报错」变成了「静默不加载」。
|
||||
|
||||
## 5. 真机升级(把 3080 的 web 实例从 0.1.7-alpha.1 升到 0.1.7-rc.1)
|
||||
|
||||
改动四处,全部带 `.bak-20260923-141956-pre-rc1` 备份:启动器 `~/.dsh/dsh-web.sh` 的 npx 钉版、profile 的 `dsh-better-sidebar` tarball 指向、`@deepseek-ai/dsh-experimental-agent-team-profile` 0.1.7-alpha.1 → 0.1.7-rc.1、profile 的 `pnpm-workspace.yaml` override(`@deepseek-ai/dsh-settings` → 0.1.7-rc.1)。随后在 profile 目录跑**纯 `pnpm install`**(不能走 `dsh plugin install`,它对内容变化会报「Already up to date」短路),再重启 pm2 app `dsh-web`。
|
||||
|
||||
**`@deepseek-ai/dsh-experimental-agent-team-web-profile` 保持 0.1.6-alpha.2 不动**——计划阶段曾打算移除它,核对发布元数据后推翻:它唯一的 peer 是 `@deepseek-ai/cordis ^4.0.2`,被预检的**名称过滤器直接跳过**,不会被 disable;其 `dependencies` 的 `^0.1.6-alpha.2` 今天就已经在解析一份独立的 0.1.6-alpha.2 副本,与 alpha.1 时的状态同构。实测 boot 日志确认它没有被跳过。
|
||||
|
||||
**boot 日志的实测结论**:只有一行 stderr,且不是我们的插件——
|
||||
|
||||
```
|
||||
dsh: skipping profile bundle "@huanlin/dsh-plugin-better-sidebar-plugin-office": Error: Plugin
|
||||
@huanlin/dsh-plugin-better-sidebar-plugin-office@0.1.2 is incompatible with dsh 0.1.7-rc.1:
|
||||
peerDependencies {"@deepseek-ai/dsh-client-runtime":"^0.0.1-rc.1"}. …
|
||||
```
|
||||
|
||||
`@deepseek-ai/dsh-client-runtime` 是 0.1.7 早就删掉的包,所以这个三方 Office 预览插件在 alpha.1 上本来就是「加载了但跑不对」(上一轮真机排查时那个拖进旧 `dsh-settings@0.0.1-rc.1` 的影子副本也来自它)。rc.1 现在把它**干净地跳过**而不是带着坏 peer 加载,属于状态改善;**它没有 `allow-version` 豁免之外的自愈路径**。npm 上已有 `0.2.0`,其 peer 面(`react` / `dsh-better-sidebar ^0.17.0` / `@deepseek-ai/cordis ^4.0.1`)不含死包,升级即可恢复——**这一条留待用户拍板,本轮未动**。
|
||||
|
||||
重启计数 22334 → 22335(只 +1,无崩溃循环)。
|
||||
|
||||
## 6. 验证证据
|
||||
|
||||
**仓库门禁**(全部退出码 0):`pnpm peers check`(No peer dependency issues found)、`pnpm typecheck`、`pnpm lint`、`pnpm build`、`pnpm check:consumer-types`、`pnpm test` = **1132 passed | 9 skipped / 113 文件**。
|
||||
|
||||
`tests/fs-watch.spec.ts` 的 `treats a repeat add as already-watched` 在并行跑全量时超时过一次;单跑与该 spec 连跑三次都是 ~1.2s 通过(预算 15s),判为 FSEvents 在满负载下的既有抖动,随后重跑全量即绿。
|
||||
|
||||
**挂载冒烟**:`DSH_CMD='npx -y --package @deepseek-ai/dsh@0.1.7-rc.1 dsh' pnpm test:mount` → 真实 rc.1 宿主上 **7/7 通过**(含「挂载 + 内建 tab 全扫」「无错误条 / pageerror / console 错误」「经原生指南逐个打开插件 tab」「经文件树打开 seed 文件强制加载 editor chunk」「mermaid / README 预览」「sidechat 宿主路由」以及两条 perf 度量)。
|
||||
|
||||
⚠️ **这一条差点变成假证据**:`scripts/e2e-common.sh` 的 `e2e_resolve_tarball` 是从仓库根 glob 里**选 mtime 最新的 tarball**、而不是自己打包;第一次跑时根目录还留着上一版的 `dsh-better-sidebar-0.21.0-alpha.1.tgz`,于是那一轮其实是**拿旧产物做的冒烟**(输出里 `tarball:` 一行会写出版本号,现在知道要看它)。删掉旧包、`pnpm build && pnpm pack` 出 `0.21.0-rc.1` 的包后重跑,才是上面这份证据。
|
||||
|
||||
**CI**:`ci` / `ci-windows` / `plugin-mount` 三个 job 全绿(`35874792197`)。这是本分支**第一次** CI 全绿——上一轮那两份提交(09-22 与 09-23)在 `Test` 步红,而本地 `pnpm test` 一直是绿的。根因是上一版新增的 `tests/primitives-exports.spec.ts` 用 `execFileSync('rg', …)` 取文件清单:**ripgrep 在开发机上装了、CI runner 上没有**,于是整个 spec 在**收集阶段**就 `spawnSync rg ENOENT`。已换成 `readdirSync` 走一遍 `src/` + `tests/`(几百个小文件,无外部二进制依赖)。
|
||||
|
||||
**真机(3080)**:宿主跑 DSH 0.1.7-rc.1、插件 0.21.0-rc.1;一次性 token 交换 303 + 签名 cookie 正常;`[data-dsh-better-sidebar]` 挂载;**零 pageerror**;浏览器实际加载的 bundle 里含新的 `codeBlockUnwrap` 且**不含**已删除的 `sideChatBlockFiles`(证明是真机在跑新产物,不是旧缓存)。
|
||||
|
||||
**用户设置的 volatile 提交在 rc.1 上仍然成立**(这是上一轮最难的一处,而本轮抬了 schemastery / cordis):贴边设置表单读到 15 个偏好键、9 键 `tabsEnabled`、用户自己的 `pluginSettings.editor.openWith.pinned = ["vscode"]` 全部保留;把 `autoOpenJobs` 由 `false` 翻成 `true` → `settings.update` 200、revision 0 → 1、重新 `settings.get` 读到新值,再写回 `false` 复原。**一个真机观察(未改)**:表单里仍有 `viewersEnabled.{pdf,binary-download}` 这两个已被删除的 viewer 的键,属于历史遗留的配置面。
|
||||
|
||||
## 7. 落地偏差与未做
|
||||
|
||||
- **回收扩展名的条数**:侦察报告一处写「9 个」、列举却是 10 项;亲自比对宿主渲染器表后确认是 **9 个**(`fods` 会被宿主当纯文本显示,不算死路),最终按 9 个回收、`fods` 保留让出。
|
||||
- **`@deepseek-ai/dsh-experimental-agent-team-web-profile` 未移除**(计划里曾打算移除,核对发布元数据后推翻,理由见 §5)。
|
||||
- **未采用** rc.1 新增的 markdown `fileImages` 委托 / `ImageLightbox` / 本地图片悬浮预览:插件自绘的图片 URL 一律带 `?sessionId=`,而 `parseFileLink` 拒绝含 `?` 的目标,宿主这条新分支拦不到我们的 URL;要用就是新做 UI,不属于适配。
|
||||
- **未把宿主 primitives 抄进插件**:rc.1 新增的官方插件实践文档(`packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md`)明确建议插件不要 import 宿主 client 包、而是「抄一份并只依赖设计令牌」。我们**有意保留 import**(25 个 icon + 13 个组件)并在 AGENTS.md §3 记下这条分歧:该建议的理由之一是「纯 JS 插件没有类型检查、组件抛错会静默清空槽位」,而本仓库是 TS + `pnpm typecheck` + `check:consumer-types`,并且 `tests/primitives-exports.spec.ts` 已经把「符号消失」从静默失败变成红测试。
|
||||
- **未按同一份实践文档把 `jobs` 路由重构成 `ctx.sessionProjections` 单元**:那是行为等价重构,超出本轮范围。
|
||||
- **`src/client/conversation-draft.ts` 的锚点缺陷未动**:它只认 `[data-slot="conversation"]`(`center-column.ts` 已经是 `main.conversation` 优先的双臂选择器)。经核对这是 **0.1.7-alpha.1 起就存在**的既有缺陷、不是 rc.1 引入,且与本轮变更不同源;记在这里待单独处理。
|
||||
- **未重跑真机 Plugins 页的图标/文案断言**:那条路径(`readPluginMeta` + `ui-plugin-manager` 渲染)在本轮逐字未变,且上一轮已真机验证过;本轮的真机证据集中在「升级后插件仍挂载、无错误、跑的是新产物、设置 volatile 提交仍成立」。
|
||||
Reference in New Issue
Block a user