# 可行性分析:dsh-outline 日期:2026-08-14 · 证据来源:DSH 官方 reference 文档、deepseek-ai/deepseek-harness 仓库源码、`demo.htm`(DSH Web GUI 实际页面快照)、Ophel 仓库现网代码、DSH-better-sidebar 仓库。 ## 结论 **可行,且比浏览器扩展场景更顺**。DSH Web GUI 自带正式的客户端插件体系:官方 slot 扩展点、会话运行时对象、样式注入机制、插件安装 CLI,全部是一等公民能力。Ophel 的大纲核心逻辑(树构建、折叠、搜索、收藏、滚动定位)与宿主无关,可直接移植;需要重写的只有"数据从哪来"和"面板挂在哪"两件事,而这两件 DSH 都给了官方通道。 ## DSH 插件体系关键事实(文档 + 源码双重验证) ### 插件形态与安装 - 插件 = npm 包。包内 `dsh.plugin.json`(id/version/client 入口)+ `cordis.patch.yml`(挂载补丁),通过官方 CLI 安装挂载: `dsh plugin --profile web add ` (DSH-better-sidebar 即此模式,不改 DSH 源码。) - 浏览器半:在 `package.json` 声明 `dsh.client`(`platform: 'web'`、可选 `inject` 依赖边),并在 `exports["./client"]` 导出构建好的 bundle。host 扫描后组合 `window.__DSH_BOOT__` entry 图,经 `/plugins//client.js` 提供 bundle;client bundle 变更支持 HMR(`dsh-client-hmr`,SSE 广播 rev)。 - 客户端包用 tsdown 构建(DSH-better-sidebar 的现成配置可直接参考),dsh 系列包作为 peerDependency/external。 - 注意:插件 bundle 里 value import 必须用 `/client` 子路径(如 `@deepseek-ai/dsh-client-runtime/client`),裸包名会打进第二份模块实例导致 scope Symbol 不匹配(runtime README 明确警告)。 ### UI 扩展点(slot 系统) - `@deepseek-ai/dsh-client-ui-slots`:`ctx.slots.register({name, key?, ...}, Component)` 贡献组件;`ctx.slots.inject(name, cb)` 等声明就绪后注入,声明撤销自动 dispose。支持 keyed entry、chain 选择、子 slot 声明、`defineStore` store 席位。 - `demo.htm` 实测可用的 slot(节选,均带 `data-slot` 稳定属性): `details`(右侧详情栏)、`sidebar`、`sidebar.footer.action`、`shell.overlay`(全局浮层)、 `conversation.session.header.utilities`(会话头部按钮区)、`conversation.chat.node`(消息行,keyed)、 `conversation.composer.*`、`settings.trigger` 等。 - 大纲面板的目标位置有两条官方路径(见 technical-plan 的形态决策): 1. **右栏面板**:`details` slot(会话页右侧已有"详情"列,天然适合大纲); 2. **浮动面板**:`shell.overlay` + `conversation.session.header.utilities` 开关按钮(最接近 Ophel 的悬浮面板形态)。 ### 数据源(核心:不抓 DOM,吃会话事件流) - `@deepseek-ai/dsh-client-runtime`(浏览器半 cordis boot)暴露 `SessionRuntime` / `Session` 对象:每个 Session 持有连续事件窗口 + `ConversationNodeAssembler`,顶层有 `nodes`、`partial`、`runningCalls` 兼容字段与 `ConversationSnapshot`。 - 用户消息与 assistant 文本都是**持久 session 事件**,按 seq 有序、可回放、增量 append;append 路径是"每条事件对每个 Definition 匹配一次"的常数级热路径。大纲可以从会话数据直接构建:用户消息事件 → 大纲一级节点;assistant markdown 文本 → 解析 `#`~`######` 标题 → 挂到对应问答下。 - 这意味着"实时"是免费的:流式 token 到达即事件 append,插件订阅即可;且刷新/重连/历史分页都由 runtime 重建,插件不用自己处理 DOM 抖动。 - 备用/兜底路径:DOM 抓取(见下)。两路径可并存:数据以事件流为准,DOM 只用于滚动定位。 ### DOM 锚点(用于点击定位与 active 高亮) `demo.htm` 实测,聊天气泡带**稳定的 data 属性**(不依赖 hash class): - `data-chat-anchor-key` / `data-chat-flow-key`:节点 key(如 `9`、`14`、`13:input-message`); - `data-chat-flow-kind=user | assistant-step | tool-call | context | turn-tail`:节点类别; - `data-turn-start=true`:轮次起点。 点击大纲项 → 按 key 查 DOM(`[data-chat-flow-key="..."]`)→ `scrollIntoView`;assistant 标题再在该 step 块内按文本匹配 `h1`~`h6`(Ophel 的 `findHeadingByText` 直接可用)。 ### 样式与 i18n - 插件 CSS 有官方注入通道:`demo.htm` 中可见 `