# 01 · 需求分析:官方原生右列 vs 装了 apes-sidebar > 本篇只回答一个问题:**一个在 DSH 里干活的人,从"官方原生"换到"装了这个包",他的需求和处境发生了什么变化?** > 对比的两端只有两个:**官方原生的右侧栏**,和**装了 apes-sidebar 之后的右侧栏**(那个包是一个整体,九个 tab 一起算)。 > 机制与根因只在[附录 A](#附录-a--证据与实现索引)留索引,细节见 [02-系统架构](02-系统架构)、[06-故障排查](06-故障排查)。 ## 一、先钉住"谁在用、他在哪儿干活" 在 DSH 里,**右侧栏是使用者一天里盯得最久的一块地方**。它不是"偶尔打开的设置页",而是"工作台 + 仪表盘"。 一个典型使用者(在 DSH 里做项目的人): - 中间是对话主线——他和模型一起干活; - 右边是这块地方——看文件、看改动、看子代理、顺手追问、跑命令、看预览; - 他往往同时开着好几个会话、好几个项目。 这决定了本页所有需求的共同特征:**这些信息"看一眼就够,但要频繁看"。** 频繁看的东西必须常驻在视野里——不能要求他"跳出去看一眼,再跳回来"。 ## 二、官方原生的右列:一个「只读的文件浏览器 + 预览器」 本机宿主(`dsh@0.1.5-rc.2`)里,官方真正放进右列的东西只有三件: | 官方包 | 它给用户什么 | 官方原话 | | --- | --- | --- | | `dsh-client-ui-sidebar-right` | **容器**:每会话一块可停靠面板、两种形态(贴靠 / 全屏)、展开按钮在会话 header 角落、最多左右两格、拖拽与浮窗、tab 菜单、内置撤销历史 | "为每个会话持有一个停靠面……拥有导航控制器(`ctx.sidebarRight`)、tab 类型注册表" | | `dsh-client-ui-sidebar-files` | **唯一的页**:「文件」——把会话工作区根目录画成一棵**只读**的树 | "把会话的工作区根目录画成一棵树,逐层经线上列出,并把文件打开到 Sidebar 里" | | `dsh-client-ui-sidebar-documentpreview` | **唯一的查看器**(kind = `text`):预览 Markdown / 代码 / 图片 / PDF / HTML,认不出的扩展名走**纯文本兜底** | "在右侧 Sidebar 预览**可读文件**,无需另开 tab 即可切换已注册的渲染器" | 一个容易被忽略、但对"用户体验"影响很大的细节: > 引导页(罗盘)**只在注册了两个以上入口时才出现**——官方随包只有一个入口(Files), > 所以官方用户的右列**默认直接就是那棵文件树,罗盘从不露面**。 > (原文:"恰好一个入口时直接打开对应页面(随包组合中为 Files)"。) **一句话概括官方原生的取向:它假设你只是想「看」。** 它给你树和预览,都是只读的;**它不假设你要在这块地方「干活」**。 于是,官方原生用户在右列里**做不到**这些事(每一条都是他能直接感知的缺失): | 他想做的事 | 官方原生右列 | 他只能怎么办 | | --- | --- | --- | | 改一个文件 | ❌ 只有预览,没有可写的编辑器 | 跳出去,用外部编辑器打开 | | 知道刚才改了哪些东西 | ❌ 没有变更清单、没有 diff | 切终端敲 `git status` / `git diff`,或另开 diff 工具 | | 看某个子代理干了什么 | ❌ 右列里没有这个入口 | 翻会话树、翻聊天记录去认人 | | 追问一句又不想弄脏主线 | ❌ 没有旁路对话 | 硬着头皮在主对话里问,或另开一个窗口 | | 跑一条命令 | ❌ 没有终端 | 切到系统终端,还得先 `cd` 到对的目录 | | 看页面 / HTML 出来什么样 | ❌ 没有内嵌浏览器 | 切浏览器标签,或手动打开产物文件 | | 知道谁在替我干活、跑到哪了 | ❌ 完全没有 | 只能往上翻记录,翻到一半又忘了上下文 | | 知道这摊活是在哪儿干的 | ❌ 界面不写 | 靠脑子记,或敲 `pwd` 确认 | | 知道这个会话现在什么状态 | ❌ 界面不写 | 靠界面上的小细节猜 | ## 三、装了 apes-sidebar 之后:同一块地方,从「看」变成「干 + 心里有数」 apes-sidebar 把这九件事一次性放进右列。它们**是一个整体需求**:把右列从"文件浏览器"变成"工作台 + 仪表盘"。 | tab | 他真正想要的是什么 | 官方原生时他被迫怎么做 | 装了之后 | 需求被改变成 | | --- | --- | --- | --- | --- | | 文件(编辑器) | 看**和改**代码,而不丢掉当前上下文 | ⌘Tab 跳到外部编辑器;回来要重新找位置 | 右列里直接看、直接改 | 「看文件不该让我离开现场」 | | 文件变动(git) | 刚才到底改了哪些东西 | 切终端敲命令,或另开 diff 工具 | 变更清单 + 单文件 diff,就在旁边 | 「改了什么必须当场看得见」——**这是信任的前提** | | 子代理 | 进某个子代理,看它到底干了什么 | 翻会话树、翻记录去认人 | 右列里直接进入该子代理 | 「子代理是可进入的,不是只能干等的」 | | 侧边对话 | 追问一句,但不想污染主线 | 硬着头皮在主对话里问,或另开窗口 | 旁路开一个小对话,两边互不干扰 | 「提问不该有副作用」——**性质变了** | | 终端 | 跑一条命令 | 切到系统终端,常常还得先 `cd` | 右列里跑,工作目录天然就是对的 | 「命令的上下文应该跟着会话走」 | | 浏览器 / 预览 | 看这个页面出来是什么样 | 切浏览器标签,或手动打开产物 | 右列内嵌,当场看 | 「产出物要能当场验收」 | | **智能体** | 谁在替我干活、跑到哪了、哪个停了 | **基本没办法**——只能翻记录猜 | 主代理在最上,直系子代理一人一行,带运行/结束状态 | 「派了活之后,我要的是**扫一眼**,不是盯着守」(见 §四·洞察 4) | | **应用** | 这摊活到底是在哪儿干的 | **基本没办法**——靠脑子记或敲 `pwd` | 打开就看到当前会话锚定的工作区 | 「界面应该告诉我我在哪,而不是要我自己记住」 | | **画像** | 这个会话现在是什么状态 | 靠界面小细节猜(在跑?停了?哪一次?) | 标题 / 运行或空闲 / 工作区,写清楚 | 「离席回来,不用重建心智模型」 | 连**顺序**都在讲同一件事:`10…50` 是操作面(看/改/查/问/跑/验),`60…70` 是态势面(谁在干、在哪儿干、什么状态)。 先让"活能在这儿干完",再让"我心里有数"——这是这个包对用户的两级承诺。 ## 四、深度分析:需求到底发生了什么变化 ### 洞察 0 · 官方原生假设"你只是看",而真实使用是"在这儿干活" 这是整个需求空间的起点。官方原生不是做得不好,而是**取向不同**:只读预览是"查看器"的思路, 而使用者把它当"工位"用——他会在这里改一个文件、跑一条命令、瞄一眼改动。 **当一块地方被当成工位,只读就会立刻变成绕路。** 这就是这个包存在的全部理由。 ### 洞察 1 · 从「只读」到「可写」:补的不是功能,是主权的归还 官方只给预览,意味着**每一个"改一下"都要离开这块地方**。装上之后,改、查改动、跑、验四件事都在原地完成。 用户省下的不是几次点击,而是**每次离开都要付出的"上下文重建"成本**——回来要重新找到刚才的位置、重新想起来自己在干嘛。 需求因此从「我要能看」变成「我要在这儿把活干完」。 ### 洞察 2 · 「留在原地」会变成默认预期(棘轮效应) 一旦右列里能改文件、能跑命令、能看预览,他对"跳出去一下"的容忍度会**永久下降**。 他会开始说「为什么这个还要我切窗口?」——而这句话在他用官方原生时是说不出口的(因为原生本来就没有可切的东西)。 **这类需求只前进、不后退**,所以值得一次做对:它一旦被填好,就变成基础设施。 ### 洞察 3 · 消除副作用之后,他会开始"问"(侧边对话) 侧边对话的价值不在"多一个对话框",而在**把提问的代价从"可能污染主线"降到"零"**。 需求的性质变了:以前他的问题是「要不要问?」(一个决策),现在变成「顺手问一下」(一个动作)。 **当一件事的代价趋近于零,用户的行为频率会跳一个数量级**——这是需求分析里最值得警惕、也最值得利用的一条规律。 ### 洞察 4 · 看得见 → 敢放手(智能体 tab 的核心价值) 这是整个包里最值钱的一条。官方原生在这一点上是**彻底空白**: - 官方没有子代理视图,也没有任何"队伍"概念 → 他派了活之后**只能等**,或者不停往上翻记录确认; - 这个包的「子代理」让他能**进入**某一个;「智能体」让他**不必进去就看得到全局**——主代理 + 直系子代理,谁在跑、谁停了。 用户真正的痛点不是"我进不去子代理",而是**"我不敢派太多活"**: 因为看不见,他只能用"盯着"来对冲风险,而盯着就失去了并行的意义。 > **看得见 → 敢放手 → 真的并行 → 才配得上"多智能体"。** > 需求从「我要能看见」升级为「我要能放心」。 ### 洞察 5 · 心智模型从脑子里搬到界面上(应用 / 画像) 多项目、多会话的人切换时要重建一次"我这是在哪儿"——标题差不多的会话最容易看错, 而看错的代价是**写错文件**。官方原生在右列里一个字都不写这件事。 「应用」「画像」做的就是**把这份"我记得"外化成"界面写着"**。 需求的性质:从「我要记性好」变成「界面不该让我记」。 ### 洞察 6 · "引导页"第一次有了意义:从单一工具到工作台 官方原生只有一个入口(Files),所以它**默认直接开文件树,罗盘界面根本不会出现**。 入口一多,罗盘才登场——用户第一次能"一屏看见这块地方能干什么"。 这是**用户层面的分水岭**:官方是"一个工具",装了之后是"一个工作台的目录页"。 (对照 §二那个细节:入口数决定了这块地方的形态。) ### 洞察 7 · 价值随"并行度"放大;而成本几乎为零 - 单会话、单项目的用户:「应用」「画像」几乎用不上,「智能体」也只有一个主代理; - 一旦同时开几个会话、派几个子代理、换几个项目:这三个 tab 的边际价值**陡增**。 所以这套东西**不是人人需要,但接到的人离不开**。 同时它**不新增数据源、不新增进程、不引入新的失败面**——只是把宿主已经投影出来的信息换个视角呈现 (逐条列在 [03-功能说明](03-功能说明))。对使用者意味着:**低风险地换到确定性**,这是它最该守住的边界。 ## 五、由以上分析推出的需求(U1–U6) | # | 需求(用户口吻) | 怎么算他满意了 | 现状 | | --- | --- | --- | --- | | U1 | 「我要在这儿把活干完,别老让我跳出去」 | 改文件、查改动、跑命令、看预览、顺手追问,都在右列完成 | ✅ 操作面六个 tab | | U2 | 「我要看得见谁在替我干活」 | 右列点一下就有队伍表;人数/状态一眼可辨;没有子代理时明确说"没有",不是空白 | ✅ 智能体 tab | | U3 | 「我要知道我是在哪儿干的活、这会话什么状态」 | 打开就看到工作区与运行/空闲,不用敲 `pwd`;拿不到应用信息时如实说明 | ◑ 工作区/状态 ✅ · 应用层等宿主 | | U4 | 「我点开 HTML 就该看得见」 | 自包含 HTML 完整显示,而不是一行 `forbidden`;**但不许为此拆掉沙箱** | ✅(多文件需我本人点「临时解锁」) | | U5 | 「我的界面不许自己乱套」 | 右列只有一套侧边栏、一个开合入口;弹窗完整盖在面板之上、按钮点得到 | ✅ | | U6 | 「我敢升级,也退得回去」 | 有"宿主版本 ↔ 插件版本"对照表;每步升级都有分支/tag 可回滚 | ✅ 两条版本线;新宿主线待实机验证 | ## 六、我们不做的事(省得期待错位) - **不重造官方已有的东西。** 官方给了容器与文件树,我们在它里面长东西,不另起一套侧边栏。 - **不为"看得见"放宽安全边界。** 需要放宽必须由用户**本人显式点**「临时解锁」。 - **不做团队/房间/多智能体协作编排。** 那是宿主的另一类职责。 - **不承诺"装上立刻见效"。** 单会话用户可能几乎感觉不到差异(见洞察 7)。 ## 七、已知的「暂时满足不了」(诚实交代) | 他想要的 | 现状 | 为什么(一句话) | 何时会有 | | --- | --- | --- | --- | | 知道这摊活属于哪个**应用**、有哪些入口 | 「应用」只显示工作区 | 宿主目前没有向插件提供应用清单的通道 | 宿主提供 feed 后即可接上 | | 一次摊开**完整**子代理树(子代理的子代理) | 只显示**直系** | 宿主投影只给一层 | 同上 | | 沙箱状态下多文件 HTML 的相对资源 | 需点「临时解锁」 | 不透明源沙箱下子请求拿不到宿主信任头(安全边界的必然结果) | 不打算改——这是刻意保留的边界 | > 这三条说明同一件事:**需求跑在宿主能力前面**。写出来不是免责,是让读的人知道 > "不能用"和"还没做"是两回事。 ## 附录 A · 证据与实现索引 开发与排障看这里;其余读者可跳过。 **"官方原生到底有什么"的证据**(本机宿主 `dsh@0.1.5-rc.2`,官方包自带文档): - 容器:`@deepseek-ai/dsh-client-ui-sidebar-right/README.zh.md` —— 停靠面、两种形态、扩展席位、引导页。 - 唯一的页:`@deepseek-ai/dsh-client-ui-sidebar-files/README.zh.md` —— "文件树 tab 类型……把文件打开到 Sidebar 里"。 - 唯一的查看器:`@deepseek-ai/dsh-client-ui-sidebar-documentpreview/README.zh.md` —— "Sidebar tab 的 kind 为 `text`",未知扩展名纯文本兜底。 - "官方只有一个入口 ⇒ 罗盘不出现":同上 sidebar-right 文档「引导页」一节。 **本包一侧的对应实现**(`editor`/`git`/`subagent`/`sidechat`/`terminal`/`browser` 为随包操作面; `agents`/`apps`/`profile` 是本 fork 自增的态势面——对内维护用,对外它是一个包): | 需求 | 机制(去哪看) | 关键证据 | | --- | --- | --- | | U5-a 右列只有一套侧边栏 | 每个 tab 注册成原生 tab 类型(`kind = descriptor.id`)渲染进官方右列;自绘面板已移除 | [02-系统架构](02-系统架构)、[05-运维手册](05-运维手册) | | U5-b 弹窗不被面板切 | 宿主容器上的层叠上下文(`isolation`)导致;挂载点改挂 `#root` 而不再挂 `document.body` | [06-故障排查](06-故障排查) | | U4 HTML 预览 | 主框架 `fetch` → `srcDoc`,**`sandbox` 属性未动**;失败回退路由 URL | [06-故障排查](06-故障排查) | | 与官方 `text` 预览的关系 | 本包的编辑器类型以更高优先级接管 `dsh-resource://file/**`,卸载即恢复官方预览 | `docs/external-plugin-guide.md` §「内置类型接管」 | | U6 版本线 | 宿主版本不匹配时宿主**静默禁用**整行(不报错、无日志);`^` 跨 minor 判 false | [04-部署指南](04-部署指南)、[06-故障排查](06-故障排查) |