用户纠正:editor/git/subagent/sidechat/terminal/browser 也是 apes-sidebar 打包进来的,对外是一个完整需求整体,对比的另一端只能是 DSH 官方原生。 - 用官方包自带 README 取证:原生右列 = 容器(sidebar-right) + 唯一页「文件」 (sidebar-files, 只读) + 唯一查看器(documentpreview, kind=text, 纯文本兜底) - 新增官方原生做不到的九件事表,作为 user 处境的 before - 洞察 0 改为「官方假设你只是看,而真实使用是在这儿干活」(只读→可写) - 新增洞察 6:官方只有一个入口→罗盘不出现;入口一多罗盘才登场(单一工具→工作台) - 附录补官方证据引文;上游/fork 的区别降为对内维护说明
186 lines
15 KiB
Markdown
186 lines
15 KiB
Markdown
# 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-故障排查) |
|
||
|
||
<!-- 本页只讲"为什么需要"。实现细节、提交号、测试名一律留在 02–07 与附录索引里。 -->
|