Files
figmar 63bcb47ed0
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s
docs(wiki): 建立项目百科(需求分析 → 架构 → 功能 → 部署 → 运维 → 排障 → 开发与测试)
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 线。
2026-10-04 01:19:31 +08:00

6.3 KiB
Raw Permalink Blame History

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 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']