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 线。
110 lines
6.3 KiB
Markdown
110 lines
6.3 KiB
Markdown
# 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
|
||
|
||
```yaml
|
||
- insert:
|
||
- id: better-sidebar
|
||
name: 'dsh-apes-sidebar'
|
||
config:
|
||
shell: /bin/zsh
|
||
shellArgs: ['--noprofile', '--no-rc']
|
||
```
|