Gitea 的 wiki 此前是空的。本次把百科的**源文件版本化进仓库**(docs/wiki/), 再用脚本发布到 wiki——文档因此与代码同源、可 review、可回溯,而不是只存在于网页上。 八页(Home 作为导航与项目速览): Home 项目速览 / 两条版本线的宿主兼容性差异 / 文档地图 / 谱系说明 01-需求分析 五条核心需求(现象·根因·验收标准·状态)+ 非目标与约束 + 需求→实现→锚点 02-系统架构 host/client 分层与产物、三层接口面、面板宿主层叠契约与 isolate 陷阱、关键不变量 03-功能说明 面板/预览器总表、信息层三 tab 数据来源、HTML 预览交付方式、i18n 与令牌、配置面 04-部署指南 宿主版本矩阵与选线决策、profile 接线(file: + bundles)、构建、验收清单、卸载与切换 05-运维手册 分支/tag 策略与回滚剧本、发布纪律(版本三元组/非确定性产物)、巡检、备份铁律、诊断 06-故障排查 8 类症状 → 根因 → 处置(含本会话实机定位过的全部案例)+ 定位手法 07-开发与测试 工程约定、目录、门禁基线、测试分层与契约 spec、扩展点、测量式 re-base 方法 脚本 scripts/push-wiki.sh:幂等发布(POST 新建 / PATCH 覆盖),凭据走 git credential helper (临时 netrc,600,退出即删),不落盘、不进 argv。已实测:8 页全部发布成功,复推为更新。 内容纪律:只写**本次会话实证过**的事实(提交号、行数、层级取值、产物大小、宿主版本矩阵、 静默禁用机制、re-base 步骤),未验证的部分明确标注为待验证或已知限制;并如实说明本仓库 历代承载过 v1 / v2 / 当前 fork 三代实现,本百科描述的是 main 上的 fork 线。
6.3 KiB
6.3 KiB
03 · 功能说明
本篇是功能清单与行为契约:有哪些面板、数据从哪来、文案与配色怎么走、安全边界在哪、能配什么。
一、面板与标签页总表
「来源」列:上游 = 来自 dsh-better-sidebar;宿主 = DSH 自身提供并占用该槽位;本 fork = 本项目的增量。
| id | 名称 | order | 来源 | 数据 / 行为 |
|---|---|---|---|---|
editor |
文件 | 10 | 上游 | 文件树 + 编辑器(CodeMirror 系,懒加载 client-editor) |
git |
文件变动 | 20 | 上游 | 工作区变更、单个 diff 视图 |
subagent |
子代理 | 30 | 上游 | 会话的子代理视图 |
sidechat |
侧边对话 | 35 | 上游 | 会话内旁路对话 |
terminal |
终端 | 40 | 上游 | PTY 终端(懒加载 client-terminal;v0.24.1 线起由宿主内置终端承担) |
browser |
浏览器 | 50 | 上游 | 内嵌浏览器/HTML 预览宿主 |
diff |
(内部) | -1 | 上游 | 非用户可见,供内部打开 diff |
apes:agents |
智能体 | 60 | 本 fork | 主代理 + 直系子代理拓扑 |
apes:apps |
应用 | 65 | 本 fork | 当前会话所属工作区(宿主暂无「应用」feed) |
apes:profile |
画像 | 70 | 本 fork | 当前会话摘要(标题 / cwd / 运行态) |
order 10–50 是上游/宿主既定带宽,apos 信息层取 60/65/70 留出余量,避免与原生面板抢占位置。
二、信息层三 tab(本 fork 的增量)
三个 tab 全部是单实例(single: true),且都按 DSH 标准 TabDescriptor 注册,
因此自动获得原生侧边栏的全部待遇:进入原生 guide、tab 芯片带图标、可开合与分栏。
| tab | 展示内容 | 数据来源 | 空态 |
|---|---|---|---|
apes:agents |
根(主代理)卡片 + 其直系子代理卡片;每行显示标签、one-shot/continuable、运行态圆点 |
① ctx.sessions.list 的 byId(durable 会话摘要);② 宿主的会话投影 projectionsBySession[sessionId].values.subagentCatalog(直系子代理清单) |
「当前会话没有子代理」提示 |
apes:apps |
当前会话的工作区(cwd) | byId[scope.sessionId].cwd,回退 scope.cwd |
明确写出「宿主今日无应用 feed」 |
apes:profile |
会话标题、运行/空闲、cwd | byId[scope.sessionId] |
「无 cwd」提示 |
实现要点:两个来源被归一化成同一种行形状 { id, label, mode },活动态统一从 byId 读,
于是「投影已就绪」与「仅有 durable 摘要」两种情况下渲染一致;这也是上游 0.1.6→0.1.7 会话 feed
迁移(subagentsByParent → projectionsBySession、list.current 删除)后的落地方式。
三、文件预览器
| id | 适用 | 说明 |
|---|---|---|
image |
图片 | 走媒体路由,受 mediaLimit 限制 |
pdf |
内嵌查看 | |
markdown |
Markdown | 渲染(Mermaid 走懒加载 chunk,可手动刷新) |
html |
HTML | 不透明源沙箱 iframe,见下节 |
code |
代码 | 高亮查看(编辑器懒加载) |
binary-download |
二进制 | 只提供下载 |
3.1 HTML 预览的交付方式(重要)
路由 /sidebar/html/<session>/<path> ← 路径围栏 + 体积上限(readLimit)
│
├─ 主框架 fetch(唯一同时被宿主围栏信任、又能带上 Electron 头的角色)
│
├─ 注入 <base href="<该文件的路由目录>"> ← 让 ./style.css 等相对引用解析回本文件所在目录
│
└─ iframe srcDoc=<文档> + sandbox=HTML_IFRAME_SANDBOX
| 状态 | 自包含 HTML | 多文件 HTML(外链 CSS/JS/图片) |
|---|---|---|
| 沙箱态(默认) | ✅ 完整可用 | 正文可用,相对资源不可用(iframe 源为 null,子请求同样被宿主围栏拒绝) |
| 临时解锁(无 sandbox 属性) | ✅ | ✅ 相对资源可用(iframe 继承 GUI 源,成为普通同源请求) |
设计取舍:沙箱令牌一个字符都不放宽。多文件 HTML 想要完整效果需用户显式点「临时解锁」—— 这是把「放宽边界」的决定权留给用户的显式动作,而不是插件默认降级。
四、安全边界(三层)
| 层 | 机制 | 说明 |
|---|---|---|
| 预览内容 | sandbox="allow-scripts allow-popups allow-downloads allow-modals" |
不含 allow-same-origin:预览文档运行在不透明源里。宿主路由另有 CSP sandbox 兜底 |
| 插件路由 | 请求信任围栏(src/trust-fence.ts) |
校验 Host 头/令牌,拒绝跨站或非授权来源对 /sidebar/* 的访问 |
| 桌面壳 | Electron 注入的 x-dsh-desktop-renderer 头 |
扩展模式下所有路由的前置围栏;只发给主框架与同源子框架。这正是「沙箱 iframe 发不出请求」的根源 |
五、i18n 与主题
- 语言包:
src/client/locales.ts+ 19 个src/client/locales-*.ts覆盖文件;默认zh,缺省回退en。 - 本 fork 文案:集中在
src/client/apes/locales.ts,每个 key 同时提供zh/en。 - 硬性约定:界面里不得出现裸字符串,一律
t('key')。 - 配色:只用宿主设计令牌
--dsw-alias-*(bg / border / label / state / interactive 系列), 写法为var(--dsw-alias-xxx, <字面回退>),保证在非 DSH 环境(单元测试)也能渲染。 无公开的--ds-*几何令牌,字号/间距/圆角内联即可。
六、配置面(挂载行 config)
配置写在插件挂载行上(profile 的 cordis.patch.yml 或 bundle patch 的 insert 行),设置页写的也是它:
| 字段 | 默认 | 含义 |
|---|---|---|
readLimit |
512 KiB |
单文件读取上限(超出截断并标记 truncated) |
mediaLimit |
20 MiB |
媒体(图片等)读取上限 |
uploadLimit |
128 MiB |
上传上限 |
listLimit |
1000 |
目录列举条目上限 |
terminalsPerSession |
3 |
每会话终端数上限 |
shell / shellArgs |
自动解析 | 终端 shell 与其启动参数(shellArgs 非空时替换默认 -l) |
例:在挂载行里指定 shell
- insert:
- id: better-sidebar
name: 'dsh-apes-sidebar'
config:
shell: /bin/zsh
shellArgs: ['--noprofile', '--no-rc']