Skip to content

fix(host): DSH Desktop 上主机半边无法加载——品牌戳改用类型断言,不再依赖运行时 SessionLogOffset 导出 - #641

Open
ZhangFengshun wants to merge 1 commit into
omdsh-dev:mainfrom
ZhangFengshun:fix/host-load-without-session-log-offset-runtime
Open

ZhangFengshun wants to merge 1 commit into
omdsh-dev:mainfrom
ZhangFengshun:fix/host-load-without-session-log-offset-runtime

Conversation

@ZhangFengshun

@ZhangFengshun ZhangFengshun commented Sep 12, 2026

Copy link
Copy Markdown

问题

DSH Desktop(打包版,实测 v2.0.9 / DSH 0.1.5-rc.1)上,插件主机半边整体无法加载

Error: dsh-plugin-desktop: plugin tree failed to load: failed to apply loader entry include
(cordis:include): failed to import loader entry better-sidebar (dsh-better-sidebar):
The requested module '@deepseek-ai/dsh-session' does not provide an export named 'SessionLogOffset'
file:///C:/Users/Administrator/.dsh/profiles/desktop/node_modules/dsh-better-sidebar/lib/index.js:16
import { SessionLogOffset } from "@deepseek-ai/dsh-session";

主机半边挂掉后 /sidebar/api/*(fs / git / terminal / jobs)全部缺失,DSH 原生右侧栏的文件页签只剩兜底文案「这类内容还没有可用的查看方式。」——本地工作区与远程工作区同样受影响。

受影响版本0.18.10.19.00.19.1(均含该值导入);0.18.0 及更早不含该导入,可正常加载。

原因

DSH Desktop 是打包可执行文件:它不通过 node_modules 符号链接给 profile 插件提供 @deepseek-ai/*,而是按 Node ESM 条件读取已安装包的 export map,写入重新导出的代理模块@deepseek-ai/dsh-app-boot 的 profile 模块后备机制;参见该包 README「Profile 模块后备机制」一节:「缺失 export 保持不可用」)。

@deepseek-ai/dsh-sessionSessionLogOffset带 brand 的数字类型

  • 类型export type SessionLogOffset = BrandedNumber<'SessionLogOffset'> —— 在 App 的 API 契约里存在;
  • 运行时:发布到 npm 的包额外导出一个恒等函数(断言非负安全整数后原样返回)——但桌面版代理面不提供该运行时符号

于是 import { SessionLogOffset } from '@deepseek-ai/dsh-session' 只在「npm 完整包」环境(CLI / CI 钉的 rc.2)成立,在桌面版上必然 ESM 实例化失败,并且是整个 entry 失败,不是单点降级。

修复

src/sidechat-routes.ts 是仓库内唯一的值用法:

// 之前
import { SessionLogOffset } from '@deepseek-ai/dsh-session'
...
inheritedEventCount: SessionLogOffset(seed.length),

// 现在
import type { SessionEvent, SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session'
...
inheritedEventCount: seed.length as SessionLogOffset,

brand 只在编译期存在,运行时戳是恒等函数 + 不变量断言;Array#length 天然是非负安全整数,正是该断言要求的值,因此这里用类型断言语义等价且无损失。改动后主机半边在两种环境(桌面版代理面 / npm 完整包)都能加载。

同时新增 tests/host-runtime-imports.spec.ts 守护:src/** 内任何对 @deepseek-ai/dsh-session值导入都会让测试失败,防止回归(测试自身仍可用 npm 包的值导出,vitest 树里该符号存在)。

验证

  • pnpm typecheck
  • pnpm exec vitest run tests/host-runtime-imports.spec.ts tests/sidechat-seed-validation.spec.ts tests/sidechat-routes.spec.ts29 passed
  • pnpm buildlib/index.jsSessionLogOffset 零出现(运行时导入已消失)✅
  • pnpm exec eslint src/sidechat-routes.ts tests/host-runtime-imports.spec.ts

复现方式(桌面版)

  1. DSH Desktop v2.0.9(或任何以代理面提供插件的打包版),profile 安装 dsh-better-sidebar@0.19.1
  2. 启动即见上述 import 报错(%APPDATA%\DSH Desktop\logs\dsh-<date>.error.log);
  3. 0.18.0 启动正常,可作为对照。

备选实现

若维护者更希望保留上游运行时不变量检查,可改为本地等价实现(不 import 该值):

function sessionLogOffset(value: number): SessionLogOffset {
  if (!Number.isSafeInteger(value) || value < 0 || Object.is(value, -0)) throw new TypeError(...)
  return value as SessionLogOffset
}

本 PR 采用更小的落点(唯一调用点的值可证明合法),两者都可,按仓库口味取舍。

…ntime SessionLogOffset export

DSH Desktop serves profile plugins a prebuilt module surface; for
@deepseek-ai/dsh-session that surface carries the SessionLogOffset *type*
but not the runtime stamp the published npm package also exports. A value
import therefore fails ESM instantiation:

  SyntaxError: The requested module '@deepseek-ai/dsh-session' does not
  provide an export named 'SessionLogOffset'   (lib/index.js:16)

and takes the whole host half down with it -- no /sidebar/api routes
(fs / git / terminal / jobs), so the native Files tab only renders the
'Nothing here can view this kind of content yet' fallback. Reproduced on
DSH Desktop v2.0.9 (DSH 0.1.5-rc.1): dsh-better-sidebar 0.18.1 / 0.19.0 /
0.19.1 all fail this way, while 0.18.0 (no such import) loads.

The brand is compile-time only -- the runtime stamp is an identity
function that asserts a non-negative safe integer, which Array#length
satisfies by construction -- so import the type and cast at the use site,
and pin the rule with tests/host-runtime-imports.spec.ts.
Copilot AI lite review requested due to automatic review settings September 12, 2026 09:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The reviewed changes resolve the startup failure and include regression coverage.

Pull request overview

Fixes DSH Desktop plugin loading by removing the runtime SessionLogOffset import.

Changes:

  • Uses a type-only import and cast.
  • Adds regression tests preventing incompatible runtime imports.
File summaries
File Summary
tests/host-runtime-imports.spec.ts Guards against runtime-import regressions.
src/sidechat-routes.ts Uses the compile-time-only offset brand.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ZhangFengshun ZhangFengshun changed the title fix(host): load on DSH Desktop — stamp the fork marker without the runtime SessionLogOffset export fix(host): DSH Desktop 上主机半边无法加载——品牌戳改用类型断言,不再依赖运行时 SessionLogOffset 导出 Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants