Compare commits

..
Author SHA1 Message Date
figmar 0aafa94c4d chore(gen1): 第一代版本封板 — DSH 2.0.17 兼容 + settings API 迁移 + React #130 修复
- peerDeps 升级到 0.2.0-rc.2
- settings API 迁移: register() → describe() + settings/document-updated
- turnTail slots.register 补 id 字段
- EditorHost viewer.component undefined guard
- 56/56 测试全绿, typecheck/build 通过

tag: v1.2.0-gen1
2026-10-11 16:52:48 +08:00
figmar df6f99c4a3 chore(peer-deps): bump to 0.2.0-rc.2 for DSH 2.0.17 compatibility
PeerDependencies changed from ^0.1.5-rc.1 to ^0.2.0-rc.2 to match
DSH Desktop 2.0.17's built-in dsh packages (Harness v0.2.0-rc.2).

Rollback anchor: git revert this commit to restore 0.1.5-rc.1 peerDeps.

Context: DSH 2.0.17 release notes state '新版内核会检查插件声明的
兼容版本,不兼容的插件可能被跳过'. This is Plan D (force-install
via peerDeps bump) — if runtime API breakage occurs, fall back to
Plan A (rebase onto upstream dsh-better-sidebar 0.25.0).
2026-10-11 14:44:51 +08:00
figmar 40a05af9ba docs(wiki): 01 需求分析改口径——对比官方原生(不再把上游操作面单列一层)
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s
用户纠正:editor/git/subagent/sidechat/terminal/browser 也是 apes-sidebar
打包进来的,对外是一个完整需求整体,对比的另一端只能是 DSH 官方原生。

- 用官方包自带 README 取证:原生右列 = 容器(sidebar-right) + 唯一页「文件」
  (sidebar-files, 只读) + 唯一查看器(documentpreview, kind=text, 纯文本兜底)
- 新增官方原生做不到的九件事表,作为 user 处境的 before
- 洞察 0 改为「官方假设你只是看,而真实使用是在这儿干活」(只读→可写)
- 新增洞察 6:官方只有一个入口→罗盘不出现;入口一多罗盘才登场(单一工具→工作台)
- 附录补官方证据引文;上游/fork 的区别降为对内维护说明
2026-10-04 02:02:55 +08:00
figmar 2b88c85ea7 docs(wiki): 01-需求分析 改为「原生 vs 上游 vs 本 fork」对比式需求分析
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s
把用户贴的 10 行 tab 表按供给来源拆成三层,逐行追问没有它时他会怎么办:
- DSH 原生 = 右列容器 + 「文件」页 + documentpreview 文本兜底(证据 external-plugin-guide.md)
- 上游 = 六个操作面(文件/变动/子代理/侧边对话/终端/浏览器)
- 本 fork = 三个态势面(agents/apps/profile)

新增 7 条需求变化洞察(操作面→态势面、零切换棘轮、提问副作用归零、
看得见→敢放手、心智模型外化、价值随并行度放大、增量成本≈0),
U1-U6 收敛为由分析推出的需求表;实现/根因只留附录索引。
2026-10-04 02:00:25 +08:00
figmar 2224991047 docs(wiki): 需求分析改为使用者视角重写
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s
原稿按「现象/根因(含证据)/需求/验收标准」组织,实质是在讲我们怎么修的;
现在从「用户为什么会需要」写起:谁在用 → 他会怎么说 → 为什么难受 → 他想要什么
→ 怎样算满意(全部是用户能亲手点到、亲眼看到的行为)。

- 五条实现导向的需求 → U1~U6 用户问题(U5 拆成两套侧边栏 / 弹窗被切)
- 新增:不做什么(省得期待错位)、已知的暂时满足不了(应用层 feed、完整子代理树、
  沙箱态相对资源),如实交代边界
- 新增:验收总表(动作 → 应看到)与优先级/状态表
- 实现机制与提交号全部移入附录 A「根因档案」索引,指向 02/03/05/06
2026-10-04 01:55:35 +08:00
figmar 63bcb47ed0 docs(wiki): 建立项目百科(需求分析 → 架构 → 功能 → 部署 → 运维 → 排障 → 开发与测试)
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s
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
16 changed files with 1813 additions and 273 deletions
+3
View File
@@ -11,6 +11,9 @@
> `apes:profile` 画像),按 DSH 标准 `TabDescriptor` 接口注册——因此它们会自动获得上游原生适配层
> 的全部待遇(进原生 guide、tab 芯片图标、开合与分栏)。
> - 版本线独立于上游:`1.2.0`(fork)。上游历史版本见其 CHANGELOG。
> - **📚 项目百科**(需求分析 → 系统架构 → 功能说明 → 部署指南 → 运维手册 → 故障排查 → 开发与测试):
> <https://gitea.apescale.com/figmar/apes-sidebar/wiki> 源文件在仓库 `docs/wiki/`,
> 改完用 `bash scripts/push-wiki.sh` 一条命令发布。
> [!IMPORTANT]
> **已适配 DSH 原生侧边栏 API**(v0.19.0 起,DSH `0.1.5-rc.1+`):右列就是 DSH 自己的右侧栏——插件的每个 tab 类型与 tab 体通过 `ctx.sidebarRightTabs` / `ctx.sidebarRight` 注册与打开,聊天里的文件打开统一走 `ctx.sidebarRight.openResource('dsh-resource://file/…')`,插件**不再自绘右侧面板**(旧的浮窗能力同步移除)。自绘的底部工作台与开放给其他插件的 `ctx.betterSidebar` 服务保持不变,接入方式见[插件接入指南](docs/external-plugin-guide.md)。
+185
View File
@@ -0,0 +1,185 @@
# 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 与附录索引里。 -->
+154
View File
@@ -0,0 +1,154 @@
# 02 · 系统架构
> 本篇说明插件的**分层、接口面、层叠契约与关键不变量**。
> 与源码一一对应,可直接当作改动前的「雷区地图」使用。
## 一、总体分层
```
┌──────────────────────────────────────────────────────────────────────────┐
│ DSH 宿主(Desktop Electron 壳 / Web profile) │
│ ├─ 原生右侧栏 ctx.sidebarRight / sidebarRightTabs(tab 类型注册表) │
│ ├─ 会话与任务 ctx.sessions.list(会话摘要、子代理、投影)、ctx.tools │
│ ├─ webServer 路由挂载点(插件用 /sidebar/* 前缀注册) │
│ └─ 桌面壳层 webserver 外层的请求围栏 + #root 的 content-viewport 标记 │
└───────────────┬──────────────────────────────────────────────────────────┘
│ ① 宿主 → 插件:cordis 服务注入(inject)
│ ② 插件 → 宿主:原生 tab / 资源打开 / 路由
┌───────────────┴──────────────────────────────────────────────────────────┐
│ 插件 HOST 半(Node,lib/index.js) │
│ · src/index.ts 路由注册(/sidebar/*)、信任围栏、会话/文件数据、HTML 交付 │
│ · src/trust-fence.ts 请求信任围栏(Host 头 / 令牌) │
│ · src/invariant.ts 依赖零的断言与 semver 工具(host/client 共用) │
└───────────────┬──────────────────────────────────────────────────────────┘
│ 浏览器侧模块(__ModuleLoader__ bundle,非 CJS)
┌───────────────┴──────────────────────────────────────────────────────────┐
│ 插件 CLIENT 半(浏览器,lib/client.js + 懒加载 chunk) │
│ · src/client/index.tsx 应用入口:装配 store/service/原生适配/信息层 │
│ · src/client/native/ 原生右侧栏适配(tab 记录、tab 体、tab 芯片标题) │
│ · src/client/builtins/ 内置面板:文件 / 文件变动 / 子代理 / 侧边对话 / │
│ 终端 / 浏览器 + 文件预览器 │
│ · src/client/sidebar/ 自绘底部工作台与开合控件(原生侧边栏之外的部分) │
│ · src/client/apes/ 信息层三 tab(本 fork 的增量) │
│ · src/client/service.ts ctx.betterSidebar 服务(供其他插件注册) │
└──────────────────────────────────────────────────────────────────────────┘
```
## 二、构建产物
| 产物 | 角色 | 备注 |
| --- | --- | --- |
| `lib/index.js` | host 半(ESM,Node) | 路由、围栏、数据面 |
| `lib/invariant.js` | 不变量面(零依赖) | host/client 都要 import,**不得**引入 Node 内置或宿主包 |
| `lib/client.js` | client 主 bundle | 浏览器 `window.__ModuleLoader__.load({...})` 形态,**不是** CJS/ESM,Node 里 `require` 会因 `window is not defined` 抛错 |
| `lib/client-registry.js` | 懒加载 chunk | 高开销能力(图标/预览库)按需加载 |
| `lib/client-editor.js` | 懒加载 chunk | 编辑器(CodeMirror 系) |
| `lib/client-locale.js` | 懒加载 chunk | 语言包 |
| `lib/client-mermaid.js` | 懒加载 chunk | Mermaid 渲染 |
| `lib/client-terminal.js` | 懒加载 chunk | 终端 |
| `lib/types/**/*.d.ts` | 类型声明 | 供消费方类型检查 |
> 懒加载动机:主 bundle 不应静态 import 重型预览库;chunk 通过宿主 `ctx.modules` 解析外部依赖
> (入口在 `src/client/index.tsx` 里先 `setChunkModuleSystem(ctx.modules)`)。
## 三、三层接口面
### 3.1 宿主 → 插件(cordis 注入)
```ts
// src/index.ts
export const name = 'dsh-apes-sidebar'
export const inject = ['webServer', 'sessions', 'webRuntime', 'tools']
export function apply(ctx: Context, config?: SidebarConfig): void
```
客户端侧读取的宿主面(结构化镜像,运行时由宿主提供):
`ctx.sessions.list`(`getSnapshot/subscribe`)、`ctx.sidebarRight`(原生右列与 `openResource`)、
`ctx.slots`、`ctx.settings`(挂载行 `config`)、`ctx.modules`(懒加载 chunk 的模块系统)。
### 3.2 插件 → 宿主
| 方向 | 手段 |
| --- | --- |
| 注册 tab 类型与 tab 体 | `src/client/native/registerNativeSurface()` → 原生右侧栏注册表 |
| 打开会话内文件 | `ctx.sidebarRight.openResource('dsh-resource://file/…')` |
| 暴露 HTTP 能力 | `/sidebar/` 前缀路由:`api` · `file` · `html` · `upload` · `ws/terminal` · `ws/agent-opens` · `ws/agent-terminals` |
### 3.3 插件 → 其他插件(对外服务)
`ctx.betterSidebar`(`src/client/service.ts`)对外开放 `registerTab` / `registerFileViewer` 等,
并按「能力清单」做前向兼容门控(能力只增不减)。对外契约见仓库内
[docs/external-plugin-guide.md](../blob/main/docs/external-plugin-guide.md)。
服务版本常量 `SIDEBAR_SERVICE_VERSION` 必须与 `package.json` / `dsh.plugin.json` 的版本三方一致
(有单元测试断言这一对)。
## 四、面板宿主与层叠契约(重点雷区)
插件的所有面板渲染在一个 **body 级(或壳层 viewport 级)的宿主层**里:
```css
[data-dsh-panel-host] { position: fixed; inset: 0; z-index: 25; pointer-events: none }
```
`z-index: 25` 不是随手取的,它要同时满足:**在 app 内容与壳层 overlay 之上、在宿主交给插件用的
overlay 槽之下**。完整取义:
| 层级 | 对象 |
| --- | --- |
| `z-index: auto` | app 的流内内容、`.dshDesktopFrame` |
| **25** | **本插件的面板宿主** |
| 30 | 宿主的动态插件面板(ui-cordis) |
| 100+ | app 的 overlay 栈(Toast / onBoarding 等) |
| 1000 | `.dshDesktopOverlay[data-shell-overlay]`(宿主给 `shell.overlay` 槽的容器,第三方弹窗在此) |
**陷阱(已修,`4422001`)**:DSH 桌面壳的有框模式会给上游 `#root` 打标
`data-dsh-desktop-content-viewport` 并施加 `isolation: isolate`,使 `#root` 成为一个**层叠上下文**。
宿主自己的 overlay 层就在这个上下文内;若插件宿主挂在 `document.body`(上下文之外),
它是「带正 z-index 的定位元素」,会画在整个上下文**之上**——把宿主 overlay 里的弹窗(如社区插件市场)盖住。
```ts
// src/client/desktop-env.ts —— 修法:挂进壳层的 content viewport
export function panelHostParent(doc: Document = document): HTMLElement {
return doc.querySelector<HTMLElement>('#root[data-dsh-desktop-content-viewport]') ?? doc.body
}
```
进入该上下文后,25 恢复原意(在 app frame 之上、在 overlay 层 1000 之下);无该标记的部署
(纯网页 / 未打标的壳)仍挂 `document.body`,行为不变。重新锚定守卫同时监听
`document.body` 的 `data-dsh-desktop-mode`(壳层打标与它是同一个 effect),因此壳层在插件挂载**之后**
才框住 `#root` 的情况也能被搬到正确位置。
## 五、数据流示例
**会话 → 信息层**
```
ctx.sessions.list.getSnapshot() → { byId, projectionsBySession? }
useSyncExternalStore(subscribe) (uSES 安全订阅)
├─ apes:agents → rootAncestor(byId, scope.sessionId) 找主代理
│ → projectionsBySession[rootId].values.subagentCatalog 取直系子代理
│ (无投影时回退 byId 里的 durable 子会话)
└─ apes:profile / apes:apps → byId[scope.sessionId](标题 / cwd / running)
```
**文件 → 预览**(HTML 为例)
```
编辑器/diff 面板 → /sidebar/html/<session>/<path> (路由负责路径围栏与体积上限)
主框架 fetch 取回文档文本 → 注入 <base href="<该文件的路由目录>">
→ iframe srcDoc + sandbox(不透明源)
取失败时回退为 iframe src=路由 URL,把路由的答复原样透出
```
## 六、关键不变量(改动前必读)
1. **host / client 拆分是结构性的**:client bundle 在浏览器运行,不得 import Node 内置;
`src/invariant.ts` 两侧共用,必须保持零依赖。
2. **`dsh-better-sidebar` 是 peer,永不打包**:一旦被内联,client 会带上第二份侧边栏注册表,
tab 注册进死实例,界面上永不出现。
3. **tab id 前缀归本 fork**:信息层用 `apes:*`;不得占用上游/宿主内部 id。
4. **HTML 预览的沙箱令牌不得放宽**(不加 `allow-same-origin` 等);交付方式只能是「主框架取文档 + `srcDoc`」。
5. **颜色只用宿主设计令牌**(`--dsw-alias-*`),不写硬编码色值;几何量(字号/间距/圆角)无公开令牌,内联即可。
6. **所有面向用户的字符串走 i18n**,`zh` / `en` 必须同时存在。
7. **变更后必须重新同步到 profile**:构建产物非字节确定性,且 profile 的 `file:` 依赖是复制语义,
不能假定旧副本可用(见 [04-部署指南](04-部署指南))。
+109
View File
@@ -0,0 +1,109 @@
# 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']
```
+163
View File
@@ -0,0 +1,163 @@
# 04 · 部署指南
> 目标:在一台机器上把本插件挂进 DSH,并确认它**真的在跑**。
> 关键前提:**先确认宿主版本,再选版本线**——选错线的唯一症状是「静默失效」。
## 一、前置条件
| 项 | 要求 |
| --- | --- |
| Node | ≥ 20(`engines.node`);本机验证用 22.x |
| pnpm | 11.x(`pnpm install` 会自动触发 `prepare: tsdown` 构建) |
| DSH | 见下面的版本矩阵 |
| 终端可用性 | 仅 v0.19.1 线需要额外放行 `node-pty` 原生构建(见 §五) |
### 1.1 宿主版本矩阵(先读这张表)
| 版本线 | 分支 | 插件版本 | peer 声明 | 适用宿主 |
| --- | --- | --- | --- | --- |
| 旧宿主线 | `main` | 1.2.0 | `^0.1.5-rc.1` | DSH `0.1.5-rc.1+`(含 `0.1.5-rc.2`,即 **DSH Desktop 2.0.10** 内置版本) |
| 新宿主线 | `sync/v0.24.1` | 1.3.0 | `^0.2.0-rc.1` | DSH `0.2.0-rc.1+` |
**怎么查宿主版本**(扩展模式桌面版):
```bash
# 内置的 dsh 版本
grep -m1 '"version"' "/Applications/DSH Desktop.app/Contents/Resources/app/node_modules/@deepseek-ai/dsh/package.json"
# 或看 profile 里装的宿主包
grep -m1 -A2 '"@deepseek-ai/dsh"' ~/.dsh/profiles/desktop/package.json
```
**选线决策**
```
宿主 ≥ 0.2.0-rc.1 ? ── 是 ──▶ sync/v0.24.1(1.3.0)
└─ 否 ──▶ main(1.2.0)
```
> ⚠️ **peer 不匹配不会报错。** 宿主以 `semver.satisfies(host, peerRange, { includePrerelease: true })` 预检,
> caret 跨 minor 判 false 后**整行静默禁用**:不加载、无日志、界面上「像没装」。
> 因此「装完没反应」的第一件事永远是核对宿主版本 ↔ peer 范围。
## 二、安装方式(本 fork 未发布 npm 包)
`npm view dsh-apes-sidebar` 返回 404 —— **本 fork 不在 npm 上**(README 里的 npm 徽章/命令是沿用上游文档)。
实际部署使用「本地源码 + `file:` 链接依赖」:
### 步骤 1:构建
```bash
cd <插件仓库绝对路径>
git checkout main # 或 sync/v0.24.1(按宿主版本选)
pnpm install # 会顺带跑 prepare: tsdown
pnpm typecheck && pnpm build && pnpm test # 门禁三连
```
产物(`lib/`):`index.js` / `invariant.js`(host)+ `client.js` + 懒加载 chunk
(`client-registry` / `client-editor` / `client-locale` / `client-mermaid` / `client-terminal`)+ `types/`。
### 步骤 2:接进 profile
编辑 `~/.dsh/profiles/<profile>/package.json`(桌面版为 `desktop`,网页版通常为 `web`):
```jsonc
{
"dependencies": {
"dsh-apes-sidebar": "file:/绝对路径/dsh-apes-sidebar" // ← 必须是绝对路径
},
"dsh": {
"profile": {
"bundles": [
"…",
"dsh-apes-sidebar" // ← 加入 bundle 栈
]
}
}
}
```
> 也可以在 profile 自己的 `cordis.patch.yml` 里手写挂载行(老方式)。**两种方式不要同时用**:
> 会双挂载成两个 Node 半、两个侧边栏。包内自带的 `cordis.patch.yml` 是 `dsh.bundle.patch` 层,
> 由官方 CLI 安装时自动追加 bundle,并带「聚合包双挂载退让」守卫。
### 步骤 3:让 profile 重新安装依赖
```bash
cd ~/.dsh/profiles/<profile> && pnpm install
```
**为什么必须重装**:pnpm 对 `file:` 依赖是**复制**语义(不是软链)。源码 `pnpm build` 之后,
profile 的 `node_modules/dsh-apes-sidebar/lib` **仍是旧副本**——这就是「改了代码但界面没变」的头号原因。
DSH 启动时也会 reconcile profile 的 pnpm workspace,但不要假定它一定帮你刷新。
### 步骤 4:完整重启
**⌘Q 完全退出 DSH,再重新启动**(不是关窗口)。client 半有热加载,但 host 半与依赖变更必须走完整重启。
## 三、验收清单
重启后逐条核对(每条都对应一个可观察事实):
- [ ] **右列只有一套侧边栏**、一个开合控件(不再出现自绘的第二套开关)
- [ ] 原生 guide 里能看到本插件的 tab 芯片,且**带图标**
- [ ] 三个信息层 tab 存在:**智能体 / 应用 / 画像**(order 在原生面板之后)
- [ ] `apes:agents` 打开后:有主代理卡片;有子代理时列出直系子代理(标签 + 模式 + 运行态)
- [ ] 打开一个 HTML 文件:**沙箱态下自包含 HTML 能正常渲染**(不再是 `forbidden`)
- [ ] 打开「社区插件市场」:弹窗**完整盖在**本插件面板之上(面板不切弹窗角)
- [ ] 页面左下角**没有**红色诊断条(有的话说明 client 生命周期某处抛错)
- [ ] 开发者控制台**没有** `[dsh-apes-sidebar] … error` 前缀的错误
## 四、网页 profile 与桌面 profile 的差异
| 项 | 桌面版(DSH Desktop) | 网页版 |
| --- | --- | --- |
| profile 目录 | `~/.dsh/profiles/desktop` | 通常 `~/.dsh/profiles/web` |
| 外壳 | Electron 壳,有「扩展模式/兼容模式」与请求围栏 | 浏览器直连宿主端口 |
| 预览 iframe | 受渲染器围栏约束(因此必须走 `srcDoc` 交付) | 无该围栏,但仍受路由 CSP/沙箱约束 |
| 面板宿主层级 | 壳层会给 `#root` 打 content-viewport 标记 → 宿主挂进 `#root` | 无标记 → 宿主挂 `document.body` |
| 刷新方式 | ⌘Q 完整退出再启动 | 硬刷新(Cmd/Ctrl+Shift+R) |
## 五、v0.19.1 线特有:放行 node-pty 原生构建
`main`(上游 v0.19.1 基线)在 `package.json` 中仍有 `node-pty` 依赖;pnpm 11 默认**拦截依赖的构建脚本**,
于是首次安装会失败或终端不可用:
```bash
cd ~/.dsh/profiles/<profile>
pnpm approve-builds # 选中 node-pty,回车确认
pnpm rebuild node-pty # 必要时
```
`sync/v0.24.1`(1.3.0)**不含** `node-pty`(终端交由宿主内置承担),无需此步。
(`main` 与 `sync/v0.24.1` 的 `node-pty` 引用数:1 / 0。)
## 六、切换与卸载
同一条线只能装一个(两条线都注册 `ctx.betterSidebar`,entry id 冲突,第二个被丢弃)。
仓库自带切换脚本:
```bash
bash scripts/switch.sh --status # 只看当前是哪条线
bash scripts/switch.sh aps # 切到本 fork 线(本地 file: 安装)
bash scripts/switch.sh upstream # 切回上游 dsh-better-sidebar
bash scripts/switch.sh upstream 0.18.0 # 指定上游版本
bash scripts/switch.sh aps --profile web # 指定 profile
```
**完全卸载**:从 profile 的 `dependencies` 与 `dsh.profile.bundles` 中移除 `dsh-apes-sidebar`,
`pnpm install`,⌘Q 完整重启。若曾手写过 `cordis.patch.yml` 挂载行,一并删除(否则会留下悬空 entry)。
> 若同时装了聚合包(如 `@linxin666/dsh-web-ui-all`)且它内部也挂载了本包,
> 包内 bundle patch 的守卫会让**本行退让**;此时请确认聚合包在 bundle 栈中位于本行之前。
## 七、变更后的重新部署
```bash
# 插件仓库
pnpm typecheck && pnpm build && pnpm test
# profile
cd ~/.dsh/profiles/<profile> && pnpm install
# ⌘Q 退出 DSH 再启动
```
改完代码**必须**走完这三步:产物构建非字节确定性,profile 的 `file:` 副本也不会自动跟随。
+133
View File
@@ -0,0 +1,133 @@
# 05 · 运维手册
> 本篇是**日常运维、升级与回滚**的操作手册。所有命令都以「先留锚点、再动手、改完回读验证」为原则。
## 一、版本线与分支策略(当前远端实况)
| ref | 指向 | 含义 / 用途 |
| --- | --- | --- |
| `main` | `4422001` | **旧宿主线**:插件 1.2.0,上游基线 v0.19.1,peer `^0.1.5-rc.1`。本机 DSH Desktop 2.0.10 正在跑这条 |
| `sync/v0.24.1` | `e5bbef1` | **新宿主线**:插件 1.3.0,上游基线 v0.24.1,peer `^0.2.0-rc.1`。待 ≥0.2.0 宿主实机验证 |
| `backup/pre-sync-v0.19.1` | `96cc334` | v0.19.1 re-base **之前**的状态(旧 fork 三角色 tab 版) |
| `backup/pre-sync-v0.24.1` | `4422001` | v0.24.1 re-base 之前的 `main`(等价于当前 main,作为下次升级的锚点) |
| `tags/apes-v1.1.0-pre-sync` | `96cc334` | 与上面第一支 backup 同一提交,tag 形式的锚点 |
| `tags/apes-v1.2.0` | `4422001` | 当前已验收的 1.2.0 线 |
**纪律**:任何 re-base / 大改之前,先建 `backup/pre-sync-<新基线>` 分支 + `apes-v<版本>` tag,
并**推送**到远端(本地锚点在多人/多机场景等于不存在)。
## 二、回滚剧本
### 场景 A:某次提交引入回归(单点回退)
```bash
cd <插件仓库>
git log --oneline -5 # 定位可疑提交
git revert <sha> # 保留历史的回退(推荐)
# 或整体丢弃:git reset --hard <上一提交>
pnpm typecheck && pnpm build && pnpm test
cd ~/.dsh/profiles/<profile> && pnpm install # file: 是复制语义,必须重装
# ⌘Q 完全退出 DSH → 重启
```
### 场景 B:整条线回退(例如新线在真机上不可用)
```bash
git checkout main # 或 backup/pre-sync-v0.24.1
pnpm install && pnpm build
cd ~/.dsh/profiles/<profile> && pnpm install
# ⌘Q 重启
```
### 场景 C:profile 依赖/config 被改坏
```bash
cd ~/.dsh/profiles/<profile>
cp package.json package.json.bak.$(date +%s) # 先备份
bash <插件仓库>/scripts/switch.sh aps # 或 upstream,脚本会重写依赖与 bundle 行
pnpm install
# ⌘Q 重启
```
**回滚验收**:重启后按 [04-部署指南](04-部署指南) §三 的验收清单逐条核对(至少「右列一套侧边栏」
与「三个信息层 tab 存在」两条)。
## 三、发布 / 变更纪律
1. **版本三元组必须一致**:
- `package.json` 的 `version`
- `dsh.plugin.json` 的 `version`
- `src/client/service.ts` 的 `SIDEBAR_SERVICE_VERSION`
三者不一致会被单元测试(`tests/service.spec.ts`)直接拦下——**不要改其中一个而忘了另一个**。
2. **门禁三连必过**:`pnpm typecheck && pnpm build && pnpm test`。当前基线:`main` 131 个测试文件 /
1367 通过;`sync/v0.24.1` 141 个文件 / 1515 通过(另有 9 个 skip)。
3. **产物非字节确定性**:两次构建的字节数可能相同但 **sha 不同**。因此「改完代码 → 让 profile 用旧副本」
永远不成立;必须重新 `pnpm build` + 让 profile 重新安装。
4. **发布方式**:本 fork 未发布 npm 包,发布 = 推分支/tag + 目标机器 `git fetch && checkout && pnpm build`
+ profile 重装。发布前把 `README.md` 与 `docs/wiki/` 一并更新(wiki 见 §六)。
5. **不要顺手改无关文件**:re-base 时保持「只带自己的增量」,避免下次升级冲突面扩大。
## 四、日常巡检清单
| 频率 | 检查项 | 命令 / 判据 |
| --- | --- | --- |
| 每次部署后 | 版本三元组一致 | 见 §三.1 |
| 每次部署后 | 产物标记齐全 | `grep -c 'apes:agents' lib/client.js`(>0)、`grep -c 'dsh-desktop-content-viewport' lib/client.js`(>0) |
| 每次部署后 | profile 副本已刷新 | 比对 `lib/client.js` 与 `~/.dsh/profiles/<p>/node_modules/dsh-apes-sidebar/lib/client.js` 的 sha256 |
| 每次升级宿主/插件 | 宿主版本 ↔ peer 范围 | 见 [04-部署指南](04-部署指南) §1.1(不匹配 = 静默禁用) |
| 每月/大改前 | 锚点是否已推远端 | `git ls-remote <remote> \| grep -E 'heads/(main\|sync)\|tags/apes'` |
| 异常时 | 诊断条与控制台 | 页面左下角红条;控制台 `[dsh-apes-sidebar]` 前缀 |
## 五、备份与配置铁律
- **改任何 profile 配置前先备份**,改完**回读验证**(不要假定写入即生效):
```bash
cp ~/.dsh/profiles/<profile>/package.json{,.bak.$(date +%s)}
# 改完:
python3 -c "import json;json.load(open('$HOME/.dsh/profiles/<profile>/package.json'));print('JSON OK')"
```
- **DSH 应用配置的类型陷阱**:部分字段(如材质/透明度类的 `macosMaterial`)必须是**字符串**
(`"off"` / `"transparent"`)。若被写成 YAML 布尔(`false`),DSH 会启动进**恢复模式**。
改完务必回读校验类型:
```bash
python3 -c "import yaml;d=yaml.safe_load(open('$HOME/.dsh/settings.yaml'));v=d.get('macosMaterial');print(v, type(v).__name__)"
```
- **不要回滚/手工编辑** profile 的 `pnpm-lock.yaml`:由 pnpm 重建;手工改会导致解析错乱。
- **凭据不进仓库**:远端推送用系统凭据助手(`git credential fill`),仓库内不写 token。
## 六、百科(wiki)本身的维护
百科源文件版本化在仓库 `docs/wiki/`,通过脚本推送到 Gitea wiki:
```bash
bash scripts/push-wiki.sh # 推送/更新全部页面(幂等:有则 PATCH,无则 POST)
bash scripts/push-wiki.sh 05-运维手册 # 只推一页
```
凭据来自 `git credential fill`(与推送代码同一套,不落盘)。修改文档的推荐流程:
**改 `docs/wiki/*.md` → 提交到仓库 → 跑脚本推送**,这样 wiki 与代码同源可回溯。
## 七、诊断与日志
| 信号 | 含义 | 位置 |
| --- | --- | --- |
| 左下角红色诊断条 `[dsh-apes-sidebar] <phase> error: …` | client 生命周期某阶段抛错(mount / native / 懒加载等) | 页面左下角(`z-index: 2147483000`),同时 `console.error` 打前缀 |
| 控制台 `[dsh-apes-sidebar] …` | 同上,且带上具体阶段名 | 开发者工具 Console |
| 「插件像没装」且**无任何日志** | 宿主兼容性预检失败(peer 不匹配)→ **静默禁用** | 只能靠版本矩阵排查,见 [06-故障排查](06-故障排查) §1 |
| 界面正常但面板层级错乱 | 面板宿主挂载点/层叠上下文问题 | 见 [02-系统架构](02-系统架构) §四 |
## 八、性能与容量
| 项 | 观察值 | 说明 |
| --- | --- | --- |
| `lib/client.js` | ≈ 0.9 MB | 主 bundle,始终加载 |
| `lib/client-mermaid.js` | ≈ 7 MB(+12 MB map) | 懒加载,仅在需要渲染 Mermaid 时拉取 |
| `lib/client-editor.js` | ≈ 2 MB | 懒加载,仅打开编辑器时 |
| `lib/client-terminal.js` | ≈ 0.5 MB | 懒加载,仅打开终端时 |
| 全量测试 | 约 3–4 分钟 | 变更后按需跑全量,日常可只跑相关 spec |
主 bundle 不应静态引入上述重型库;新增重型依赖一律走 `src/client/chunks/`(懒加载 chunk)。
+208
View File
@@ -0,0 +1,208 @@
# 06 · 故障排查
> 每条都给出**症状 → 根因(机制)→ 处置 → 验证**。标注 ✅ 的条目是在真机上定位并验证过的案例。
## 速查表
| 症状 | 最可能根因 | 跳到 |
| --- | --- | --- |
| 装完「像没装」,界面无变化且**无任何日志** | peer 范围与宿主版本不匹配 → 静默禁用 | §1 |
| 页面出现**两个侧边栏** / 两套开合按钮 | 双挂载(两条线同装,或残留挂载行) | §2 |
| HTML 预览只显示 `forbidden` | 桌面壳渲染器围栏 + 不透明源 iframe | §3 |
| 插件面板盖住宿主/第三方弹窗(如插件市场) | 面板宿主挂在层叠上下文之外 | §4 |
| 终端打不开 / `node-pty` 加载失败 | pnpm 拦截原生构建(仅 v0.19.1 线) | §5 |
| 改了代码,界面没变 | 产物未重建 / profile 副本未刷新 / 浏览器缓存 | §6 |
| DSH 拒绝加载插件、entry pending | 插件声明(`dsh.plugin.json` / bundle patch)不合法 | §7 |
| DSH 启动进**恢复模式** | profile 配置被写成错误类型(如 YAML 布尔) | §8 |
---
## §1 装完「像没装」:静默禁用 ✅
**症状**:profile 里依赖装了、文件也在,但界面没有任何变化;日志里也没有插件相关报错。
**根因**:宿主启动时做兼容性预检,判定 `peerDependencies` 与自身版本是否满足:
```
semver.satisfies(hostVersion, peerRange, { includePrerelease: true })
```
caret 范围**跨 minor 必然为 false**(例如 `^0.1.5-rc.1` 对 `0.2.0`)。判定失败后宿主的处理是
**跳过这一行**——不抛错、不打日志、不加载。
**处置**:核对宿主版本,改用匹配的版本线(见 [04-部署指南](04-部署指南) §1.1)。
```bash
grep -m1 '"version"' "/Applications/DSH Desktop.app/Contents/Resources/app/node_modules/@deepseek-ai/dsh/package.json"
grep -n 'dsh-client-ui-sidebar-right' <插件仓库>/package.json # 看 peer 范围
```
**验证**:重启后右列出现插件 tab;`lib/client.js` 里能 grep 到 `apes:agents`。
**教训**:这一条没有日志可查,因此**部署前先看版本矩阵**是唯一可靠的预防手段。
## §2 两个侧边栏 / 两套开合按钮 ✅
**症状**:窗口里出现两套右侧面板与两组开合控件。
**根因**:两个方向都可能:
1. **旧版遗留**:v0.18.0 基线时插件自绘右侧面板与开关(`toggleCluster`)。升级后自绘部分应已移除。
2. **双挂载**:同一条线被挂两次(profile 自己的 `cordis.patch.yml` 里还留着旧挂载行,
与 bundle patch 同时生效),或者本 fork 线与上游线同时安装(两者都注册 `ctx.betterSidebar`,
entry id 冲突,第二个被丢弃)。
**处置**:
```bash
# 确认产物里已经没有自绘开关
grep -c toggleCluster <插件仓库>/lib/client.js # 期望 0
# 检查是否双挂载:profile 里是否同时存在 bundle 行 与 手写挂载行
grep -n "dsh-apes-sidebar\|dsh-better-sidebar" ~/.dsh/profiles/<profile>/cordis.patch.yml ~/.dsh/profiles/<profile>/package.json
```
- 有残留手写挂载行 → 删除它,只保留一条通道。
- 两条线同装 → `bash scripts/switch.sh aps`(或 `upstream`)二选一。
- 装了聚合包(如 `@linxin666/dsh-web-ui-all`)→ 确认聚合包在本包之前,让包内守卫生效。
**验证**:右列只剩一套面板与一个开合控件。
## §3 HTML 预览显示 `forbidden` ✅
**症状**:预览 HTML 文件时 iframe 里只有一行裸文本 `forbidden`;而「临时解锁」后又能看。
**根因(三层)**:
1. DSH Desktop 在**扩展模式**下给所有路由套了一层请求围栏:`ordinaryBrowserEnabled` 恒为 false,
不带 Electron 注入的 `x-dsh-desktop-renderer` 头的请求一律 `403 + "forbidden"`;
2. 该头只注入给 **mainFrame** 与**同源**子框架;
3. 预览 iframe 的 sandbox 令牌不含 `allow-same-origin`,请求时其源为 `null` → 拿不到头 → 403。
与「是否升级了插件基线」无关(v0.18.0 起行为一致)。
**处置**:插件已在 1.2.0+ 用 **`srcDoc` 交付**修复(主框架取文档 → 注入 `<base>` → 注入 iframe),
`main` 上对应提交 `4c242ac`。**不要**通过给 iframe 加 `allow-same-origin` 来"修"——那是安全降级。
**验证**:
- 沙箱态下自包含 HTML(含内联脚本)能正常渲染;
- 有外链资源的 HTML 在沙箱态下缺资源属**已知限制**,点「临时解锁」后应完整显示。
**排查命令**(确认宿主围栏在起作用):
```bash
lsof -nP -iTCP -sTCP:LISTEN | grep -i dsh # 找宿主端口(每次启动可能不同)
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:<端口>/" # 无渲染器头 → 403
```
## §4 插件面板盖住宿主/第三方弹窗 ✅
**症状**:打开「社区插件市场」(宿主自带 `dsh-community-market`)时,弹窗左下角被本插件的
文件面板整齐切掉一块。
**根因**:桌面壳的有框模式会给上游 `#root` 打标 `data-dsh-desktop-content-viewport` 并施加
`isolation: isolate`,使 `#root` 成为**层叠上下文**;宿主的 overlay 层(`.dshDesktopOverlay`,
`z-index: 1000`)位于其中。插件面板宿主若挂在 `document.body`(该上下文之外)且是定位元素,
就会画在整个上下文之上,把 overlay 里的弹窗盖住。
**处置**:已修(`4422001`)——面板宿主改为挂进 `#root[data-dsh-desktop-content-viewport]`,
无标记时回退 `document.body`。**不要**通过调大 `z-index` 解决(25 的取义见
[02-系统架构](02-系统架构) §四;乱调会破坏与宿主其他层级的关系)。
**验证**:插件市场弹窗完整盖住本插件面板,同时本插件面板仍在对话内容之上。
## §5 终端不可用 / `node-pty` 加载失败(仅 v0.19.1 线)✅
**症状**:终端面板报 shell 启动失败或提示 `node-pty` 加载失败;`pnpm install` 阶段报
"ignored build scripts"。
**根因**:pnpm 11 默认**拦截依赖的构建脚本**,`node-pty` 的原生二进制没被编译。
(`main` 依赖 `node-pty`;`sync/v0.24.1` 已移除该依赖,终端由宿主内置承担。)
**处置**:
```bash
cd ~/.dsh/profiles/<profile>
pnpm approve-builds # 选中 node-pty
pnpm rebuild node-pty # 必要时
# ⌘Q 完整退出 DSH 再启动
```
**验证**:终端能开出 shell;`node_modules/node-pty/build/Release/*.node` 存在。
## §6 改了代码,界面没变 ✅
**症状**:源码已改、`pnpm build` 也跑了,但界面行为仍是旧的。
**根因(三个叠加因素)**:
1. 产物**非字节确定性**,且 profile 的 `file:` 依赖是**复制**语义 → profile 里仍是旧副本;
2. `lib/client.js` 是浏览器的 `window.__ModuleLoader__.load({...})` bundle,**不是 CJS/ESM**,
在 Node 里 `require` 会因 `window is not defined` 报错——因此不能用「在 Node 里试跑」来验证前端改动;
3. host 半的改动必须重启进程(client 半有热加载,host 半没有)。
**处置**:
```bash
cd <插件仓库> && pnpm build
cd ~/.dsh/profiles/<profile> && pnpm install # 刷新 file: 副本
# ⌘Q 完整退出 DSH → 重启
```
**验证**:比对两边产物 sha:
```bash
shasum -a 256 <插件仓库>/lib/client.js \
~/.dsh/profiles/<profile>/node_modules/dsh-apes-sidebar/lib/client.js
```
## §7 DSH 拒绝加载插件 / entry pending
**症状**:插件目录存在,但宿主不加载,或 loader 报 entry pending / 恢复模式。
**根因**:插件的声明面不合法或不被接受,常见于:
- `dsh.plugin.json` 的 `engines.dsh` 与宿主不符;
- bundle patch / 挂载行的 `insert` 结构不合法(例如把声明写成宿主无法解析的形态);
- 同 id 重复挂载(`duplicate loader entry id` / `duplicate prefix route`)。
**处置**:
```bash
cat <插件仓库>/dsh.plugin.json # 检查 id / engines / main
cat <插件仓库>/cordis.patch.yml # 检查 insert 结构与守卫表达式
grep -n "cordis.patch\|dsh-apes-sidebar" ~/.dsh/profiles/<profile>/package.json
```
确保只有一条挂载通道、`name` 与实际包名一致(本 fork 为 `dsh-apes-sidebar`),
`engines.dsh` 与宿主版本相容。改完 `pnpm install` + **完整重启**。
**验证**:启动日志无 loader 报错;右列出现插件 tab。
## §8 DSH 启动进「恢复模式」
**症状**:DSH 启动后进入恢复/安全模式,插件与侧边栏都不正常。
**根因**:profile 或应用配置被写成**错误类型**。典型是材质/透明度字段要求**字符串**
(`"off"` / `"transparent"`),但被 YAML 序列化成了布尔 `false` —— 宿主按类型校验失败即进恢复模式。
**处置与验证**:
```bash
python3 -c "import yaml;d=yaml.safe_load(open('$HOME/.dsh/settings.yaml'));v=d.get('macosMaterial');print(repr(v), type(v).__name__)"
# 期望:'off' str(或 'transparent' str);若为 False bool → 改回字符串
```
改配置前**先备份**,改完**回读校验类型**(见 [05-运维手册](05-运维手册) §五)。
---
## 附:定位手法(本次会话验证有效)
1. **先按用户可见文案 grep 找归属**:`grep -rl "<界面上的中文短语>" <app>/lib <profile>/node_modules`。
若两边都搜不到,说明它来自**运行时下载/缓存**(例如市场插件),再按 `NSUserData` 缓存或
`desktop-market/state.json` 之类线索去找提供方。
2. **再读提供方自己的 CSS/DOM 结构**:拿到它声明的 z-index、定位方式与所在槽位
(如 `renderSlot("shell.overlay")`),据此判断是「它太高」还是「我们太高」。
3. **层叠问题先找 `isolation` / `transform` / `filter` / `contain`**:这些才是层叠上下文与包含块的真正来源,
比 z-index 数值更关键。
4. **像素证据要用原图量**:交给视觉模型的截图会被缩放(1920→1280),裁剪坐标 ≠ 屏幕坐标;
用 PIL 在原图上量边界、比对 RGB 剖面,再下结论。
+164
View File
@@ -0,0 +1,164 @@
# 07 · 开发与测试
> 面向改代码的人(与 agent)。**先读 [02-系统架构](02-系统架构) §六「关键不变量」**,
> 再动手改,能省掉大部分回退。
## 一、工程约定
| 项 | 约定 |
| --- | --- |
| 语言 | TypeScript **strict**(含 `noUncheckedIndexedAccess`)、ESM、导入写 `.ts` 扩展名 |
| 构建 | `tsdown`(rolldown),host/client 双产物;懒加载 chunk 走 `src/client/chunks/` |
| 包管理 | `pnpm`(11.x);`pnpm install` 会触发 `prepare` 构建 |
| 测试 | `vitest`;默认 node 环境,需要 DOM 的 spec 用 `// @vitest-environment jsdom` |
| 宿主 peer | `dsh-better-sidebar`(本仓库已改名)**永不打包**,必须留在 peer/neverBundle 一侧 |
| 命名 | 信息层 tab id 前缀 `apes:`;插件名 `dsh-apes-sidebar` |
| 颜色 | 只用 `--dsw-alias-*` 设计令牌(`var(--token, <回退>)`),不写死色值 |
## 二、目录结构(`main` 实况)
```
src/
index.ts HOST 入口:name / inject / apply(ctx, config),路由与围栏装配
invariant.ts 零依赖不变量面(host/client 共用)
context-types.ts cordis 服务面契约(ctx.sessions / sidebarRight / …)
trust-fence.ts 请求信任围栏(Host 头 / 令牌)
html-route.ts /sidebar/html 路由(路径围栏 + 体积上限)
config.ts 挂载行配置 schema 与默认值(readLimit / mediaLimit / …)
fs-*.ts git.ts … 文件系统、Git、会话、任务、终端等 host 能力
client/
index.tsx CLIENT 入口(apply):装配 store/service/native/apes
service.ts ctx.betterSidebar 服务实现(对外 API + 能力清单)
state.ts 侧边栏状态存储(store)
native/ 原生右侧栏适配(tab 记录、tab 体、tab 芯片标题)
builtins/ 内置面板:editor / git / subagent / sidechat / terminal / browser + 预览器
sidebar/ 自绘底部工作台与开合控件
apes/ 信息层三 tab(本 fork 增量:tabs.tsx / icons.tsx / locales.ts)
changes/ diff/ 文件变动与 diff 视图
chunks/ 懒加载 chunk:editor / locale / mermaid / terminal
locales*.ts i18n(`locales.ts` + 19 个语言覆盖文件)
*.module.css 组件样式(含 sidebar.module.css:面板宿主层契约)
tests/ vitest specs(131 个文件,含 e2e/ 的挂载脚本型用例)
scripts/ install / switch / e2e 挂载 / 发布辅助
docs/ external-plugin-guide.md(对外契约)+ plans/(上游历史设计)+ wiki/(本百科源文件)
```
## 三、门禁(提交前必跑)
```bash
pnpm typecheck # tsc --noEmit(strict)
pnpm build # rm -rf lib && tsc(d.ts) && tsdown
pnpm test # vitest run
```
当前基线(本次会话实测):`main` = 131 文件 / **1367 通过** + 9 skip;
`sync/v0.24.1` = 141 文件 / **1515 通过** + 9 skip。全量 test 约 3–4 分钟。
**任何一条不过就不要提交**;三条全绿才算完成。
## 四、测试体系(按层次)
| 层次 | 环境 | 手法 | 代表 spec |
| --- | --- | --- | --- |
| 宿主插件形状 / 对外契约 | node | 断言导出面与语义(含与 `package.json` 的版本一致性) | `smoke.spec.ts` · `plugin-shape.spec.ts` · `service.spec.ts` · `consumer-types.ts` |
| 原生侧边栏适配 | node | 用「类型为真、运行时为假」的 mock 注册表 | `native-surface.spec.ts` |
| 面板宿主与层叠契约 | node + jsdom | CSS 断言 + DOM 挂载点解析 | `panel-host-css.spec.ts` · `panel-host-parent.spec.ts` |
| 预览交付 | node + jsdom | 纯逻辑(`<base>` 注入)+ 客户端挂载(stub `fetch`,`createRoot` + `act`) | `html-preview.spec.ts` · `html-preview-frame.spec.tsx` |
| 沙箱契约 | node | 对渲染结果做**字符串断言**(服务端渲染把 `srcDoc` 输出为 camelCase `srcDoc=""`,与客户端设置的真实属性 `srcdoc` 不同 —— 断言方式随之不同) | `sandbox-views.spec.tsx` |
| 信息层 tab | node | mock `ctx.sessions.list` 与投影 | `apes-tabs.spec.ts` |
| 桌面环境探测 | node | stub 全局(URL stamp / preload 标记) | `desktop-env.spec.ts` |
约定:
- **不引入 jsdom 到默认环境**:需要 DOM 的 spec 在文件头写 `// @vitest-environment jsdom`。
- **不依赖真实 DSH 宿主**:需要真宿主的用例归到 `tests/e2e/`(脚本型挂载),不进单元门禁。
- 新增「契约」必须**同时新增 pin 它的 spec**(例如本文档提到的 25 层级、沙箱令牌、`srcDoc` 交付方式,
都有对应断言)。改契约 = 改代码 + 改 spec,两者必须一起提交。
## 五、扩展点(对外服务)
其他插件通过 `ctx.betterSidebar` 接入:
```ts
// 注册一个 tab 类型
await ctx.betterSidebar.registerTab(descriptor)
// 注册一个文件预览器
await ctx.betterSidebar.registerFileViewer(viewer)
```
- 服务按**能力清单**做前向兼容门控(能力只增不减),消费方应据此判断可用性而非版本号比较。
- 完整契约、字段表与示例见仓库内 [docs/external-plugin-guide.md](../blob/main/docs/external-plugin-guide.md)。
- 改服务面时:**只能新增**;删除或改语义需同步更新能力清单、指南与本百科。
## 六、上游同步:测量式 re-base(本项目的方法论)
**不 merge 上游**。上游每个版本差距可达数百文件,直接合并会引入无关变更并放大冲突面;
本项目改用「先测量、再重建、后补增量」:
### 步骤
**① 测出自己的增量(把改名归一化掉)**
```python
# 对每个变更文件:取出两边 blob,把改名归一化后比较
old = git('show', f'{base}:{path}'); new = git('show', f'HEAD:{path}')
rename_only = old.replace('dsh-better-sidebar', 'dsh-apes-sidebar') == new
```
→ 得到三张清单:**仅改名**(自动处理)/ **真改动** / **新增**。数量级参考:v0.19.1→v0.24.1 为
78 / 11 / 10。
**② 确定改名的精确范围(不要重新推断)**
```bash
# 仍保留上游名字的文件 = 有意保留(本仓库为 README.md、package.json、docs/plans/*)
comm -12 <(git grep -l 'dsh-better-sidebar' <旧基线> | cut -d: -f2 | sort) \
<(git grep -l 'dsh-better-sidebar' HEAD | cut -d: -f2 | sort)
```
其余文件只做子串替换 `dsh-better-sidebar` → `dsh-apes-sidebar`;**camelCase 服务名 `betterSidebar` 必须保留**。
**③ 造一个"改名归一化基座",让增量与改名解耦**
```bash
git checkout -B tmp/norm-<旧基线> <旧基线 tag>
# → 套同一口径改名 → commit
git diff tmp/norm-<旧基线> HEAD -- . ':(exclude)pnpm-lock.yaml' > /tmp/apes-delta.patch
# 校验:这条 diff 的文件清单必须恰好等于 ① 的「真改动 + 新增」
```
**④ 在新基线上重建 + 三点合并**
```bash
git checkout -B sync/<新基线 tag> <新基线 tag>
# → 套同一口径改名 → commit("rename only")
git apply -3 /tmp/apes-delta.patch # 冲突会以 <<<<<<< ours / >>>>>>> theirs 留存(命令本身不失败)
```
**⑤ 逐条判读冲突(只有五种形态)**
| 形态 | 判定 |
| --- | --- |
| 版本/身份 JSON | 取**新基线**侧,再改成本 fork 的版本;两侧各自新增的元数据取**并集**(依赖、files 条目、`forkedFrom` 块) |
| 上游搬走了某个 import | 取上游的新路径,保留本 fork 的新 import |
| 上游新环境里的注册块 | 保留本 fork 的块,放进上游的新上下文 |
| 同一函数两边都定义(上游上移/下移了它) | 删除本 fork 那份;用 `grep -c 'const <name>'` 断言只剩 1 处 |
| 长文档(README) | 整体取上游原文,再机械套上本 fork 的两处增量:顶部 fork notice + 包名替换(**跳过** `github.com/<上游 org>` 与徽章域名行) |
**⑥ 迁移检查(API 漂移)+ 门禁**
- 先**解完所有冲突标记再** `pnpm install`(`prepare: tsdown` 会因为语法错误直接失败),
并**删掉 lockfile 重新生成**(不要把旧 lockfile 带过来)。
- 逐条跑 `pnpm typecheck` 修类型漂移。经验:漂移通常集中在**本 fork 自己新增的模块**里。
上游会在 `context-types.ts` 的注释里写清迁移路径(例:0.1.6 的 `subagentsByParent`
→ 0.1.7 的 `projectionsBySession[id].values.subagentCatalog`,`list.current` 被删除),照注释做即可。
- 最后跑门禁三连,并且**用 `grep` 核对关键标记**(tab id、`srcDoc`、`dsh-desktop-content-viewport` 等)。
**⑦ 收尾(纪律)**
- 安全锚点:`backup/pre-sync-<新基线>` 分支 + `apes-v<版本>` tag,**推送远端**。
- **不要把新线同步进正在使用的 profile**:peer 范围可能已跨 minor,同步过去只会「静默失效」,
同时把本机环境弄脏。保持 profile 在已验证的线上。
## 七、提交与分支纪律
- 提交信息用 `type(scope): 摘要`(`feat` / `fix` / `chore` / `docs` / `refactor`),正文说明**为什么**与验证方式。
- 一个提交一件事;re-base 类改动拆成「rename only」+「增量移植」两个提交,便于回溯与回滚。
- 分支命名:`sync/<上游 tag>`(跟随上游)、`backup/pre-sync-<基线>`(锚点)、其余按需。
- 提交前:门禁三连 + 关键标记 grep + (若涉及部署)提醒 profile 重装与完整重启。
+82
View File
@@ -0,0 +1,82 @@
# apes-sidebar 项目百科
> DeepSeek Harness(DSH)的**服务化右侧边栏工作台** + **apes 信息层**。
> 本项目是 [`dsh-better-sidebar`](https://github.com/omdsh-dev/DSH-better-sidebar)(MIT)的 fork,
> 在其「文件 / 文件变动 / 任务 / 侧边对话 / 终端 / 浏览器」工作台之上,追加三个信息层标签页:
> **智能体(agents)/ 应用(apps)/ 画像(profile)**。
## 一、项目速览
| 项 | 值 |
| --- | --- |
| 仓库 | `figmar/apes-sidebar`(公开) |
| 默认分支 | `main` |
| 许可证 | MIT(fork 自 `omdsh-dev/DSH-better-sidebar`) |
| 语言 / 构建 | TypeScript(strict)· `tsdown`(rolldown)· `pnpm` |
| 宿主 | DSH Desktop(Electron 壳)或 DSH Web profile |
| 上游跟随方式 | 不合并上游提交,而是**测量式 re-base**(见 [07-开发与测试](07-开发与测试)) |
## 二、两条版本线(重要)
本仓库同时维护两条互相独立、**不能同时挂载**的版本线(两条线都注册 `ctx.betterSidebar`,
cordis entry id 冲突,第二个会被丢弃):
| 分支 | 版本 | 上游基线 | peer / 宿主要求 | 状态 |
| --- | --- | --- | --- | --- |
| **`main`** | 1.2.0 | `dsh-better-sidebar` **v0.19.1**(`8753096`) | `^0.1.5-rc.1`(DSH **0.1.5-rc.1+**) | 已在本机 DSH Desktop 2.0.10(`dsh 0.1.5-rc.2`)实机运行 |
| **`sync/v0.24.1`** | 1.3.0 | `dsh-better-sidebar` **v0.24.1**(`a2751cf`) | `^0.2.0-rc.1`(DSH **0.2.0-rc.1+**) | 构建与测试全绿,**待具备 0.2.0 宿主实机验证** |
> ⚠️ **宿主的兼容性预检是「静默禁用」,不报错、不加载、无日志。**
> 宿主用 `semver.satisfies(host, peerRange, { includePrerelease: true })` 判定;caret 范围跨 minor
> 不成立(`^0.1.5-rc.1` 在 `0.2.0` 宿主上为 false),于是整行被跳过。
> **现象 = 插件"好像没装"**。选线请先看宿主版本,见 [04-部署指南](04-部署指南)。
## 三、文档地图
| 页面 | 内容 |
| --- | --- |
| [01-需求分析](01-需求分析) | **官方原生 vs 装了本包**:官方右列只有「文件树 + 只读文本预览」(附官方包证据),九个 tab 是一个整体需求;7 条需求变化洞察、U1–U6、已知限制 |
| [02-系统架构](02-系统架构) | host/client 拆分、三层接口面、面板宿主层级契约、关键不变量 |
| [03-功能说明](03-功能说明) | 全部标签页与预览器、信息层数据来源、i18n、主题令牌、安全边界 |
| [04-部署指南](04-部署指南) | 环境矩阵、选线、profile 接线、构建、验收清单、卸载 |
| [05-运维手册](05-运维手册) | 版本线与分支策略、回滚剧本、发布纪律、巡检、备份铁律 |
| [06-故障排查](06-故障排查) | 症状 → 根因 → 处置(含全部实机验证过的案例) |
| [07-开发与测试](07-开发与测试) | 工程约定、目录、门禁、测试体系、扩展点、上游 re-base 方法 |
## 四、快速开始(TL;DR)
```bash
# 1) 构建(Node ≥ 20,pnpm)
pnpm install && pnpm typecheck && pnpm build && pnpm test
# 2) 接到 DSH profile(以桌面 profile 为例,使用 file: 链接依赖)
# 在 ~/.dsh/profiles/desktop/package.json 中:
# "dsh-apes-sidebar": "file:/绝对路径/dsh-apes-sidebar"
# 并在 dsh.profile.bundles 列表里加入 "dsh-apes-sidebar"
# 3) 让 profile 重新安装依赖,然后 ⌘Q 完整退出 DSH 再启动
```
完整步骤与坑见 [04-部署指南](04-部署指南)。
## 五、仓库内的事实源
| 位置 | 说明 |
| --- | --- |
| `README.md` | 面向用户的功能与安装说明(主体沿用上游文档,顶部有 fork notice) |
| `AGENTS.md` | 面向 agent/协作者的工程约定(构建、布局、硬性规则、测试约定)⚠️ 注意:本文件当前描述的是**另一套 from-scratch 实现**,与 `main` 的 fork 树不一致,以源码为准 |
| `docs/external-plugin-guide.md` | 插件接入指南:`ctx.betterSidebar.registerTab / registerFileViewer` 的对外契约 |
| `docs/plans/` | 上游历史设计文档(保持上游原样,未随 fork 改名) |
| `docs/wiki/` | **本百科的源文件**(Gitea wiki 页面的可版本化副本,由 `scripts/push-wiki.sh` 推送) |
| `scripts/switch.sh` | 两线切换脚本(`aps` ↔ `upstream`),含 `--status` |
## 六、谱系说明(如实交代)
`figmar/apes-sidebar` 这个仓库先后承载过同一产品族的三代实现:
1. **v1**:早期 JS bundle 版侧边栏插件(仓库描述里提到的「可配置显示名 / 预设 feyOS」即出自那一代);
2. **v2**:from-scratch 重写(`src/index.ts` + `src/client/index.tsx` 结构,五个 `apes:*` tab),
即 `AGENTS.md` 所描述的那一套,其产物不在当前 `main` 上;
3. **当前线(v0.19.1 / v0.24.1 fork)**:即 `main` 与 `sync/v0.24.1` 上的代码——本百科描述的对象。
若需要把本百科改写成描述 v2 重写版,请告知,源文件在 `docs/wiki/` 可直接替换。
+22 -22
View File
@@ -94,21 +94,21 @@
},
"license": "MIT",
"peerDependencies": {
"@deepseek-ai/cordis": "^4.0.2",
"@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.1",
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.1",
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.1",
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
"@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.5-rc.1",
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
"@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.1",
"@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
"@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
"@deepseek-ai/dsh-subagent": "^0.1.5-rc.1",
"@deepseek-ai/dsh-tools": "^0.1.5-rc.1",
"@deepseek-ai/cordis": "^4.0.4",
"@deepseek-ai/dsh-agent": "^0.2.0-rc.2",
"@deepseek-ai/dsh-client-locale": "^0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-conversation": "^0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-settings": "^0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-sidebar-right": "^0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-slots": "^0.2.0-rc.2",
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.2",
"@deepseek-ai/dsh-invariants": "^0.2.0-rc.2",
"@deepseek-ai/dsh-llm": "^0.2.0-rc.2",
"@deepseek-ai/dsh-session": "^0.2.0-rc.2",
"@deepseek-ai/dsh-settings": "^0.2.0-rc.2",
"@deepseek-ai/dsh-subagent": "^0.2.0-rc.2",
"@deepseek-ai/dsh-tools": "^0.2.0-rc.2",
"@huanlin/dsh-plugin-better-locale": "^0.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
@@ -178,6 +178,7 @@
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
"@deepseek-ai/dsh-user-approval": "0.1.5-rc.2",
"@deepseek-ai/dsh-util-time": "0.1.5-rc.2",
"@eslint/js": "^10.0.1",
"@huanlin/dsh-plugin-better-locale": "^0.1.0",
"@playwright/test": "^1.62.1",
"@shikijs/langs": "^4.3.1",
@@ -190,6 +191,9 @@
"@xterm/xterm": "^5.5.0",
"anser": "^2.3.5",
"cordis": "^4.0.0-rc.8",
"eslint": "^10.9.1",
"eslint-plugin-react-hooks": "^7.1.1",
"globals": "^17.12.0",
"jsdom": "^29.1.1",
"katex": "^0.16.47",
"lightningcss": "^1.32.0",
@@ -205,18 +209,14 @@
"micromark-util-sanitize-uri": "^2.0.1",
"micromark-util-symbol": "^2.0.1",
"micromark-util-types": "^2.0.2",
"shiki": "^4.3.1",
"react": "^18.2.0",
"react-dom": "18.2.0",
"shiki": "^4.3.1",
"tsdown": "^0.22.2",
"typescript": "^5.6.0",
"typescript-eslint": "^8.69.0",
"unrun": "^0.2.39",
"vitest": "^4.1.8",
"@eslint/js": "^10.0.1",
"eslint": "^10.9.1",
"eslint-plugin-react-hooks": "^7.1.1",
"globals": "^17.12.0",
"typescript-eslint": "^8.69.0"
"vitest": "^4.1.8"
},
"forkedFrom": {
"name": "dsh-better-sidebar",
+372 -188
View File
@@ -72,8 +72,8 @@ importers:
specifier: ^6.43.8
version: 6.43.9
'@deepseek-ai/cordis':
specifier: ^4.0.2
version: 4.0.2
specifier: ^4.0.4
version: 4.0.4
'@lezer/highlight':
specifier: ^1.2.3
version: 1.2.3
@@ -107,79 +107,79 @@ importers:
version: 1.0.0-rc.5(cordis@4.0.0-rc.8)
'@deepseek-ai/dsh-agent':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a)
version: 0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765)
'@deepseek-ai/dsh-agent-loop':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(3614e6173b88412acd7a4d68327c2643)
version: 0.1.5-rc.2(d06a42c4c143d9351ce4bfa1fb05b381)
'@deepseek-ai/dsh-attachment':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-client-locale':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-conversation':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-primitives':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-settings':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-sidebar-right':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-slots':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-code-runtime':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-host-webserver':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-session-persistence':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session-projection':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-settings':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/schemastery@3.18.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/schemastery@3.18.2)
'@deepseek-ai/dsh-subagent':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(e0403b2ed6d0ea9742dca77442b144e6)
version: 0.1.5-rc.2(07f8536edd4a93b233faed911be382ff)
'@deepseek-ai/dsh-system-prompt':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-tools':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(7f9e302786cf21e030eafe960666842c)
version: 0.1.5-rc.2(7b8079e0198c17ecc10c45cf34f5a1d1)
'@deepseek-ai/dsh-user-approval':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-agent@0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-agent@0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-util-time':
specifier: 0.1.5-rc.2
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
version: 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@eslint/js':
specifier: ^10.0.1
version: 10.0.1(eslint@10.11.0)
'@huanlin/dsh-plugin-better-locale':
specifier: ^0.1.0
version: 0.1.0(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-client-locale@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-primitives@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-slots@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
version: 0.1.0(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-client-locale@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-client-ui-primitives@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-client-ui-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-client-ui-slots@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@playwright/test':
specifier: ^1.62.1
version: 1.62.1
@@ -509,20 +509,20 @@ packages:
resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==}
engines: {node: '>=20.19.0'}
'@deepseek-ai/cordis@4.0.2':
resolution: {integrity: sha512-asOnXP1TzFSFQlHb1iegDZp0z/8WD1c7YNrwJR/Tx2bzNuMXfcekE/I67Iv6SQXeLB4csxqCngzQKANP7gdw0g==}
'@deepseek-ai/cordis@4.0.4':
resolution: {integrity: sha512-obgyxqWAmFn3Re8kvsuUnyW+ihrz6eJCnJO4fh1cQzDtmPYz/zzVeUkH9R94I0OwSVOocK67Kgakm04j/oQXzg==}
hasBin: true
peerDependencies:
'@deepseek-ai/cordis-plugin-include': ^1.0.7
'@deepseek-ai/cordis-plugin-loader': ^1.0.3
'@deepseek-ai/cordis-plugin-include': ~1.0.9
'@deepseek-ai/cordis-plugin-loader': ~1.0.5
peerDependenciesMeta:
'@deepseek-ai/cordis-plugin-include':
optional: true
'@deepseek-ai/cordis-plugin-loader':
optional: true
'@deepseek-ai/cosmokit@1.8.3':
resolution: {integrity: sha512-qBo+ronVM6Eu2WNVJXi8JcMiqZ19T9BRIpV+5qJUFPXjGH/Z0QKcQMC/IZJ7L394YTOtJgcovbk9qP0w2GsBXQ==}
'@deepseek-ai/cosmokit@1.8.5':
resolution: {integrity: sha512-LXsrlem9z8dq4sLflj2yuCuYX7KqhdzF5hZly3eZyuTo8d6oDSOXuEgC5DbQWKW+lksm6zmOutQLsP/ma6wR6A==}
'@deepseek-ai/dsh-agent-loop@0.1.5-rc.2':
resolution: {integrity: sha512-24wvqVlqFmdqJ2Bhcku/vKeNy+qWSmeEeN7lvcUB+WkhcF0/Ra2G3WwcVmnahJA4+w0AKdW3W7v+YYcO/jKJpg==}
@@ -963,6 +963,9 @@ packages:
'@oxc-project/types@0.146.0':
resolution: {integrity: sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==}
'@oxc-project/types@0.153.0':
resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==}
'@playwright/test@1.62.1':
resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==}
engines: {node: '>=20'}
@@ -971,6 +974,12 @@ packages:
'@quansync/fs@1.0.0':
resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==}
'@rolldown/binding-android-arm-eabi@1.2.13':
resolution: {integrity: sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@rolldown/binding-android-arm-eabi@1.2.5':
resolution: {integrity: sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -983,6 +992,12 @@ packages:
cpu: [arm64]
os: [android]
'@rolldown/binding-android-arm64@1.2.13':
resolution: {integrity: sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@rolldown/binding-android-arm64@1.2.5':
resolution: {integrity: sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -995,6 +1010,12 @@ packages:
cpu: [arm64]
os: [darwin]
'@rolldown/binding-darwin-arm64@1.2.13':
resolution: {integrity: sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@rolldown/binding-darwin-arm64@1.2.5':
resolution: {integrity: sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1007,6 +1028,12 @@ packages:
cpu: [x64]
os: [darwin]
'@rolldown/binding-darwin-x64@1.2.13':
resolution: {integrity: sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@rolldown/binding-darwin-x64@1.2.5':
resolution: {integrity: sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1019,6 +1046,12 @@ packages:
cpu: [x64]
os: [freebsd]
'@rolldown/binding-freebsd-x64@1.2.13':
resolution: {integrity: sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@rolldown/binding-freebsd-x64@1.2.5':
resolution: {integrity: sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1031,6 +1064,12 @@ packages:
cpu: [arm]
os: [linux]
'@rolldown/binding-linux-arm-gnueabihf@1.2.13':
resolution: {integrity: sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@rolldown/binding-linux-arm-gnueabihf@1.2.5':
resolution: {integrity: sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1044,6 +1083,13 @@ packages:
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-arm64-gnu@1.2.13':
resolution: {integrity: sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-arm64-gnu@1.2.5':
resolution: {integrity: sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1058,6 +1104,13 @@ packages:
os: [linux]
libc: [musl]
'@rolldown/binding-linux-arm64-musl@1.2.13':
resolution: {integrity: sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rolldown/binding-linux-arm64-musl@1.2.5':
resolution: {integrity: sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1072,6 +1125,13 @@ packages:
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-ppc64-gnu@1.2.13':
resolution: {integrity: sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-ppc64-gnu@1.2.5':
resolution: {integrity: sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1086,6 +1146,13 @@ packages:
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-s390x-gnu@1.2.13':
resolution: {integrity: sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-s390x-gnu@1.2.5':
resolution: {integrity: sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1100,6 +1167,13 @@ packages:
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-x64-gnu@1.2.13':
resolution: {integrity: sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-x64-gnu@1.2.5':
resolution: {integrity: sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1114,6 +1188,13 @@ packages:
os: [linux]
libc: [musl]
'@rolldown/binding-linux-x64-musl@1.2.13':
resolution: {integrity: sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@rolldown/binding-linux-x64-musl@1.2.5':
resolution: {integrity: sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1127,6 +1208,12 @@ packages:
cpu: [arm64]
os: [openharmony]
'@rolldown/binding-openharmony-arm64@1.2.13':
resolution: {integrity: sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@rolldown/binding-openharmony-arm64@1.2.5':
resolution: {integrity: sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1144,6 +1231,12 @@ packages:
cpu: [arm64]
os: [win32]
'@rolldown/binding-win32-arm64-msvc@1.2.13':
resolution: {integrity: sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@rolldown/binding-win32-arm64-msvc@1.2.5':
resolution: {integrity: sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1156,6 +1249,12 @@ packages:
cpu: [x64]
os: [win32]
'@rolldown/binding-win32-x64-msvc@1.2.13':
resolution: {integrity: sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
'@rolldown/binding-win32-x64-msvc@1.2.5':
resolution: {integrity: sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2471,8 +2570,8 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
nanoid@3.3.18:
resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
nanoid@3.3.20:
resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
@@ -2551,6 +2650,10 @@ packages:
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
engines: {node: '>=12'}
picomatch@4.0.7:
resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
engines: {node: '>=12'}
playwright-core@1.62.1:
resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==}
engines: {node: '>=20'}
@@ -2567,8 +2670,8 @@ packages:
points-on-path@0.2.1:
resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==}
postcss@8.5.26:
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
postcss@8.5.29:
resolution: {integrity: sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==}
engines: {node: ^10 || ^12 || >=14}
prelude-ls@1.2.1:
@@ -2646,6 +2749,11 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
rolldown@1.2.13:
resolution: {integrity: sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
rolldown@1.2.5:
resolution: {integrity: sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2704,6 +2812,10 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
source-map-js@1.2.2:
resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==}
engines: {node: '>=0.10.0'}
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@@ -3404,228 +3516,228 @@ snapshots:
'@csstools/css-tokenizer@4.0.0': {}
'@deepseek-ai/cordis@4.0.2':
'@deepseek-ai/cordis@4.0.4':
dependencies:
'@deepseek-ai/cosmokit': 1.8.3
'@deepseek-ai/cosmokit': 1.8.5
'@standard-schema/spec': 1.1.0
'@deepseek-ai/cosmokit@1.8.3': {}
'@deepseek-ai/cosmokit@1.8.5': {}
'@deepseek-ai/dsh-agent-loop@0.1.5-rc.2(3614e6173b88412acd7a4d68327c2643)':
'@deepseek-ai/dsh-agent-loop@0.1.5-rc.2(d06a42c4c143d9351ce4bfa1fb05b381)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a)
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-session-persistence': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session-projection': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
'@deepseek-ai/dsh-settings': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/schemastery@3.18.2)
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-tools': 0.1.5-rc.2(7f9e302786cf21e030eafe960666842c)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765)
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-session-persistence': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session-projection': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-settings': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/schemastery@3.18.2)
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-tools': 0.1.5-rc.2(7b8079e0198c17ecc10c45cf34f5a1d1)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/schemastery': 3.18.2
zod: 4.4.3
'@deepseek-ai/dsh-agent@0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a)':
'@deepseek-ai/dsh-agent@0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-session-projection': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-typert-protocol': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-session-projection': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-typert-protocol': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-attachment@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))':
'@deepseek-ai/dsh-attachment@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-chunked-list@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-chunked-list@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
zod: 4.4.3
'@deepseek-ai/dsh-client-locale@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-client-locale@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-client-ui-conversation@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-client-ui-conversation@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-client-ui-primitives@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-client-ui-primitives@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-client-ui-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-client-ui-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-client-ui-sidebar-right@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-client-ui-sidebar-right@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-client-ui-slots@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-client-ui-slots@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-code-runtime@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-code-runtime@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-host-webserver@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-host-webserver@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/schemastery': 3.18.2
compression: 1.8.1
negotiator: 1.1.0
transitivePeerDependencies:
- supports-color
'@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-timeout': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-typert-protocol': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-util-crypto': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-timeout': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-typert-protocol': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-util-crypto': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/schemastery': 3.18.2
zod: 4.4.3
'@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))':
'@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-session-persistence@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))':
'@deepseek-ai/dsh-session-persistence@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-timeout': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-timeout': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-session-projection@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))':
'@deepseek-ai/dsh-session-projection@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
zod: 4.4.3
'@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))':
'@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/schemastery@3.18.2)':
'@deepseek-ai/dsh-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/schemastery@3.18.2)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-subagent@0.1.5-rc.2(e0403b2ed6d0ea9742dca77442b144e6)':
'@deepseek-ai/dsh-subagent@0.1.5-rc.2(07f8536edd4a93b233faed911be382ff)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a)
'@deepseek-ai/dsh-attachment': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-chunked-list': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-tools': 0.1.5-rc.2(7f9e302786cf21e030eafe960666842c)
'@deepseek-ai/dsh-typert-protocol': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-util-time': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765)
'@deepseek-ai/dsh-attachment': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-chunked-list': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-tools': 0.1.5-rc.2(7b8079e0198c17ecc10c45cf34f5a1d1)
'@deepseek-ai/dsh-typert-protocol': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-util-time': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
zod: 4.4.3
optionalDependencies:
'@deepseek-ai/dsh-session-persistence': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session-projection': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
'@deepseek-ai/dsh-user-approval': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-agent@0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
'@deepseek-ai/dsh-session-persistence': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session-projection': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-user-approval': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-agent@0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))':
'@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-timeout@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-tools@0.1.5-rc.2(7f9e302786cf21e030eafe960666842c)':
'@deepseek-ai/dsh-tools@0.1.5-rc.2(7b8079e0198c17ecc10c45cf34f5a1d1)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a)
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-code-runtime': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-user-approval': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-agent@0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765)
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-code-runtime': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-user-approval': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-agent@0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))
'@deepseek-ai/dsh-util-values': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-typert-protocol@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-typert-protocol@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-user-approval@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-agent@0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))))':
'@deepseek-ai/dsh-user-approval@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-agent@0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765))(@deepseek-ai/dsh-brand@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))(@deepseek-ai/dsh-session@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-system-prompt@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))))':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(6df6622855b87cb7fde1fe609a6d039a)
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)))
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-agent': 0.1.5-rc.2(fb2f634a54103f233e11aabe0c89c765)
'@deepseek-ai/dsh-brand': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-llm': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-scope': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))
'@deepseek-ai/dsh-session': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/dsh-system-prompt': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)))
'@deepseek-ai/schemastery': 3.18.2
'@deepseek-ai/dsh-util-crypto@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-util-crypto@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-util-time@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-util-time@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/dsh-util-values@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)':
'@deepseek-ai/dsh-util-values@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
'@deepseek-ai/schemastery@3.18.2':
dependencies:
'@deepseek-ai/cosmokit': 1.8.3
'@deepseek-ai/cosmokit': 1.8.5
'@standard-schema/spec': 1.1.0
'@emnapi/core@1.10.0':
@@ -3680,15 +3792,15 @@ snapshots:
'@exodus/bytes@1.15.1': {}
'@huanlin/dsh-plugin-better-locale@0.1.0(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-client-locale@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-primitives@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-slots@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.2))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
'@huanlin/dsh-plugin-better-locale@0.1.0(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-client-locale@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-client-ui-primitives@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-client-ui-settings@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-client-ui-slots@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.1.5-rc.2(@deepseek-ai/cordis@4.0.4))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@deepseek-ai/cordis': 4.0.2
'@deepseek-ai/cordis': 4.0.4
optionalDependencies:
'@deepseek-ai/dsh-client-locale': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-client-ui-primitives': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-client-ui-settings': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-client-ui-slots': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.2)
'@deepseek-ai/dsh-client-locale': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-primitives': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-settings': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-client-ui-slots': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
'@deepseek-ai/dsh-invariants': 0.1.5-rc.2(@deepseek-ai/cordis@4.0.4)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
@@ -3847,6 +3959,8 @@ snapshots:
'@oxc-project/types@0.146.0': {}
'@oxc-project/types@0.153.0': {}
'@playwright/test@1.62.1':
dependencies:
playwright: 1.62.1
@@ -3855,78 +3969,117 @@ snapshots:
dependencies:
quansync: 1.0.0
'@rolldown/binding-android-arm-eabi@1.2.13':
optional: true
'@rolldown/binding-android-arm-eabi@1.2.5':
optional: true
'@rolldown/binding-android-arm64@1.0.0-rc.17':
optional: true
'@rolldown/binding-android-arm64@1.2.13':
optional: true
'@rolldown/binding-android-arm64@1.2.5':
optional: true
'@rolldown/binding-darwin-arm64@1.0.0-rc.17':
optional: true
'@rolldown/binding-darwin-arm64@1.2.13':
optional: true
'@rolldown/binding-darwin-arm64@1.2.5':
optional: true
'@rolldown/binding-darwin-x64@1.0.0-rc.17':
optional: true
'@rolldown/binding-darwin-x64@1.2.13':
optional: true
'@rolldown/binding-darwin-x64@1.2.5':
optional: true
'@rolldown/binding-freebsd-x64@1.0.0-rc.17':
optional: true
'@rolldown/binding-freebsd-x64@1.2.13':
optional: true
'@rolldown/binding-freebsd-x64@1.2.5':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.2.13':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.2.5':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.2.13':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.2.5':
optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-arm64-musl@1.2.13':
optional: true
'@rolldown/binding-linux-arm64-musl@1.2.5':
optional: true
'@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-ppc64-gnu@1.2.13':
optional: true
'@rolldown/binding-linux-ppc64-gnu@1.2.5':
optional: true
'@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-s390x-gnu@1.2.13':
optional: true
'@rolldown/binding-linux-s390x-gnu@1.2.5':
optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-x64-gnu@1.2.13':
optional: true
'@rolldown/binding-linux-x64-gnu@1.2.5':
optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-rc.17':
optional: true
'@rolldown/binding-linux-x64-musl@1.2.13':
optional: true
'@rolldown/binding-linux-x64-musl@1.2.5':
optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-rc.17':
optional: true
'@rolldown/binding-openharmony-arm64@1.2.13':
optional: true
'@rolldown/binding-openharmony-arm64@1.2.5':
optional: true
@@ -3940,12 +4093,18 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17':
optional: true
'@rolldown/binding-win32-arm64-msvc@1.2.13':
optional: true
'@rolldown/binding-win32-arm64-msvc@1.2.5':
optional: true
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.17':
optional: true
'@rolldown/binding-win32-x64-msvc@1.2.13':
optional: true
'@rolldown/binding-win32-x64-msvc@1.2.5':
optional: true
@@ -5455,7 +5614,7 @@ snapshots:
ms@2.1.3: {}
nanoid@3.3.18: {}
nanoid@3.3.20: {}
natural-compare@1.4.0: {}
@@ -5520,6 +5679,8 @@ snapshots:
picomatch@4.0.5: {}
picomatch@4.0.7: {}
playwright-core@1.62.1: {}
playwright@1.62.1:
@@ -5535,11 +5696,11 @@ snapshots:
path-data-parser: 0.1.0
points-on-curve: 0.2.0
postcss@8.5.26:
postcss@8.5.29:
dependencies:
nanoid: 3.3.18
nanoid: 3.3.20
picocolors: 1.1.1
source-map-js: 1.2.1
source-map-js: 1.2.2
prelude-ls@1.2.1: {}
@@ -5618,6 +5779,27 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17
'@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17
rolldown@1.2.13:
dependencies:
'@oxc-project/types': 0.153.0
'@rolldown/pluginutils': 1.0.1
optionalDependencies:
'@rolldown/binding-android-arm-eabi': 1.2.13
'@rolldown/binding-android-arm64': 1.2.13
'@rolldown/binding-darwin-arm64': 1.2.13
'@rolldown/binding-darwin-x64': 1.2.13
'@rolldown/binding-freebsd-x64': 1.2.13
'@rolldown/binding-linux-arm-gnueabihf': 1.2.13
'@rolldown/binding-linux-arm64-gnu': 1.2.13
'@rolldown/binding-linux-arm64-musl': 1.2.13
'@rolldown/binding-linux-ppc64-gnu': 1.2.13
'@rolldown/binding-linux-s390x-gnu': 1.2.13
'@rolldown/binding-linux-x64-gnu': 1.2.13
'@rolldown/binding-linux-x64-musl': 1.2.13
'@rolldown/binding-openharmony-arm64': 1.2.13
'@rolldown/binding-win32-arm64-msvc': 1.2.13
'@rolldown/binding-win32-x64-msvc': 1.2.13
rolldown@1.2.5:
dependencies:
'@oxc-project/types': 0.146.0
@@ -5694,6 +5876,8 @@ snapshots:
source-map-js@1.2.1: {}
source-map-js@1.2.2: {}
space-separated-tokens@2.0.2: {}
stackback@0.0.2: {}
@@ -5863,9 +6047,9 @@ snapshots:
vite@8.2.2(@types/node@24.13.3):
dependencies:
lightningcss: 1.33.0
picomatch: 4.0.5
postcss: 8.5.26
rolldown: 1.2.5
picomatch: 4.0.7
postcss: 8.5.29
rolldown: 1.2.13
tinyglobby: 0.2.17
optionalDependencies:
'@types/node': 24.13.3
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env bash
# =============================================================================
# push-wiki.sh — 把 docs/wiki/*.md 推送/更新到本仓库的 Gitea wiki
#
# 为什么需要它:本项目的百科源文件**版本化在仓库里**(docs/wiki/),
# Gitea wiki 只是它的发布面。改文档 = 改仓库文件 + 跑本脚本,日志与回溯都在 git 里。
#
# 行为:
# · 幂等:页面不存在则 POST 新建,已存在则 PATCH 覆盖(标题 = 文件名去掉 .md)
# · 凭据来自 `git credential fill`(与推代码同一套),脚本自身不存任何 token
# · 凭据经临时 netrc 文件传给 curl(600 权限,退出即删),不进入 argv
#
# 用法:
# bash scripts/push-wiki.sh # 推送全部页面
# bash scripts/push-wiki.sh 05-运维手册 # 只推指定页面(按文件名/片段匹配)
# WIKI_REMOTE=origin bash scripts/push-wiki.sh # 指定 remote(默认 gitea,缺失则 origin)
# =============================================================================
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
WIKI_DIR="$ROOT/docs/wiki"
FILTER="${1:-}"
# ---- 解析 remote / owner / repo -------------------------------------------
pick_remote() {
for r in "${WIKI_REMOTE:-}" gitea origin; do
[ -z "$r" ] && continue
if git remote get-url "$r" >/dev/null 2>&1; then echo "$r"; return 0; fi
done
echo "无法找到可用的 git remote(试过: ${WIKI_REMOTE:-<空>} gitea origin)" >&2
return 1
}
REMOTE="$(pick_remote)"
URL="$(git remote get-url "$REMOTE")"
case "$URL" in
https://*) ;;
*) echo "本脚本只支持 https remote(当前: $URL)" >&2; exit 1 ;;
esac
HOST="$(printf '%s' "$URL" | sed -E 's#^https://([^/]+)/.*#\1#')"
SLUG="$(printf '%s' "$URL" | sed -E 's#^https://[^/]+/##; s#\.git$##')"
OWNER="${SLUG%%/*}"
REPO="${SLUG#*/}"
API="https://$HOST/api/v1/repos/$OWNER/$REPO/wiki"
echo "wiki 目标 : $OWNER/$REPO @ $HOST (remote: $REMOTE)"
echo "源目录 : docs/wiki"
echo
# ---- 凭据 -----------------------------------------------------------------
CRED="$(printf 'protocol=https\nhost=%s\n\n' "$HOST" | git credential fill 2>/dev/null || true)"
USER="$(printf '%s\n' "$CRED" | sed -n 's/^username=//p')"
PASS="$(printf '%s\n' "$CRED" | sed -n 's/^password=//p')"
if [ -z "$PASS" ]; then
echo "未从 git credential helper 取到 $HOST 的凭据(先确保 git push 能成功)" >&2
exit 1
fi
NETRC="$(mktemp)"
chmod 600 "$NETRC"
trap 'rm -f "$NETRC"' EXIT
printf 'machine %s\nlogin %s\npassword %s\n' "$HOST" "$USER" "$PASS" > "$NETRC"
json_body() { # $1 = file
python3 - "$1" <<'PY'
import base64, json, sys, pathlib
p = pathlib.Path(sys.argv[1])
print(json.dumps({
"title": p.stem,
"content_base64": base64.b64encode(p.read_text(encoding="utf-8").encode("utf-8")).decode("ascii"),
}, ensure_ascii=False))
PY
}
api() { # $1 = method, $2 = path, $3 = body(optional) -> 输出 HTTP 码
local method="$1" path="$2" body="${3:-}"
if [ -n "$body" ]; then
curl -s --netrc-file "$NETRC" -o /tmp/push-wiki-resp.json -w '%{http_code}' \
-X "$method" -H 'Content-Type: application/json' --data-binary "$body" "$API$path"
else
curl -s --netrc-file "$NETRC" -o /tmp/push-wiki-resp.json -w '%{http_code}' -X "$method" "$API$path"
fi
}
# ---- 逐页推送 -------------------------------------------------------------
shopt -s nullglob
files=("$WIKI_DIR"/*.md)
[ ${#files[@]} -gt 0 ] || { echo "docs/wiki 下没有 .md 文件" >&2; exit 1; }
ok=0; fail=0
for f in "${files[@]}"; do
title="$(basename "$f" .md)"
if [ -n "$FILTER" ] && [[ "$title" != *"$FILTER"* ]]; then continue; fi
body="$(json_body "$f")"
code="$(api POST /new "$body")"
if [ "$code" = "201" ]; then
echo " + $title (新建)"; ok=$((ok+1)); continue
fi
enc="$(python3 -c 'import sys,urllib.parse;print(urllib.parse.quote(sys.argv[1], safe=""))' "$title")"
code="$(api PATCH "/page/$enc" "$body")"
if [ "$code" = "200" ]; then
echo " ~ $title (更新)"; ok=$((ok+1))
else
echo " ! $title 失败(HTTP $code): $(head -c 200 /tmp/push-wiki-resp.json 2>/dev/null)" >&2
fail=$((fail+1))
fi
done
echo
echo "完成:成功 $ok 页,失败 $fail 页"
[ "$fail" -eq 0 ] || exit 1
echo "查看: https://$HOST/$OWNER/$REPO/wiki"
+1 -1
View File
@@ -483,7 +483,7 @@ export function EditorHost(props: {
? <FenceErrorNotice store={store} onDisabled={() => { setReloadSeq(sequence => sequence + 1) }} />
: <div className={css.editorError}>{load.message}</div>)}
{!showEmpty && load.status === 'binary' && <BinaryDownload scope={scope} path={path} />}
{!showEmpty && load.status === 'ready' && createElement(load.viewer.component, {
{!showEmpty && load.status === 'ready' && load.viewer.component !== undefined && createElement(load.viewer.component, {
ctx, store, scope, path, title,
viewerId: load.viewer.id,
content: load.content,
+1
View File
@@ -112,6 +112,7 @@ export function SidebarProducedFiles(props: {
export function registerTurnTailInterception(ctx: Context, store: SidebarStore): () => void {
return ctx.slots.inject('conversation.chat.turnTail', () => ctx.slots.register({
name: 'conversation.chat.turnTail',
id: 'dsh-apes-sidebar:turn-tail',
// Decline the takeover while the editor tab type is disabled in the side
// card settings: the produced-files row falls back to the default
// deliverables behavior instead of offering chips that cannot open. Also
+28 -13
View File
@@ -799,22 +799,28 @@ export function apply(ctx: Context, config?: SidebarConfig): void {
}
}
ctx.inject(['settings'], (sctx) => {
// DSH 0.1.2-alpha.2 validates namespaces at compile time
// (SettingsNamespaceInput); the 'dsh-apes-sidebar' literal passes, so the
// runtime helper this used to call (settingsNamespace) is gone upstream.
const ns = SIDEBAR_PREFS_NS
// The structural settings mirror types `schema` as unknown, so the
// generic is not inferred here; the real service resolves it from the
// schemastery schema (PrefsSchema) — narrow the owner scope explicitly.
const scope = sctx.settings.register(ns, PrefsSchema) as {
get(): SidebarPrefs
watch(callback: (next: SidebarPrefs, prev: SidebarPrefs) => void): () => void
// 0.2.0-rc.2: `settings.register()` is gone. The plugin's Config schema
// (config.ts → Config) is auto-registered by the loader under ns =
// entry.options.id (= package name). We read it through describe() and
// watch for changes via the `settings/document-updated` event.
const readPrefs = (): SidebarPrefs => {
const descriptor = sctx.settings.describe({ redactSecrets: true }).find(c => c.ns === ns)
const raw = descriptor?.value as Record<string, unknown> | undefined
return raw !== null && typeof raw === 'object'
? raw as unknown as SidebarPrefs
: SIDEBAR_PREFS_DEFAULTS
}
const scope = { get: readPrefs }
const viewOf = (): { value?: unknown; revision?: number } => {
const descriptor = sctx.settings.describe({ redactSecrets: true }).find(candidate => candidate.ns === ns)
return descriptor === undefined
? { value: undefined, revision: undefined }
: { value: descriptor.value, revision: descriptor.revision }
if (descriptor === undefined) return { value: undefined, revision: undefined }
// 0.2.0-rc.2: describe() may return value=undefined for a namespace that
// has no user-set document yet (the Config schema defaults are applied
// lazily). Fall back to the schema defaults so the client always gets a
// well-formed object (React #130 guard).
const value = descriptor.value ?? SIDEBAR_PREFS_DEFAULTS
return { value, revision: descriptor.revision }
}
// Mutual exclusion with the dsh-web-ui family right panel: the aionui
// panel's provider choice (`aionui-panel.rightPanel`) is the authority.
@@ -869,7 +875,12 @@ export function apply(ctx: Context, config?: SidebarConfig): void {
// ONE watch subscription drives both gates: settings commits re-evaluate
// the terminal tools AND the open tool together (each gate is idempotent
// and owns its own disposer).
scope.watch(() => { syncToolsGate(scope); syncOpenToolsGate() })
// 0.2.0-rc.2: `scope.watch()` is gone; use the `settings/document-updated`
// event emitted on the plugin context (ownerContext) by the SettingsForms
// service on every describe() call that detects a raw-value change.
ctx.on('settings/document-updated', (changedNs: string) => {
if (changedNs === ns) { syncToolsGate(scope); syncOpenToolsGate() }
})
})
// ── JSON API ────────────────────────────────────────────────────────────
@@ -880,6 +891,10 @@ export function apply(ctx: Context, config?: SidebarConfig): void {
// effect releases the listener on fiber disposal.
const assistantLive = createAssistantLiveBuffer(ctx)
ctx.effect(() => () => { assistantLive.dispose() }, 'dsh-apes-sidebar: live assistant stream buffer')
// NOTE: `buildApi` must come AFTER `ctx.inject(['settings'], ...)` so the
// closure captures the settingsFace value set inside the inject callback.
// 0.2.0-rc.2 removed `settings.register()`; settingsFace is now populated
// synchronously during inject, not lazily at first call.
const api = buildApi(ctx, ptyManager, agentPtyRegistry, resolved, terminalShell, () => settingsFace, assistantLive)
ctx.effect(() => ctx.webServer.register({
kind: 'prefix',
+75 -49
View File
@@ -11,6 +11,8 @@ import { join, resolve as resolvePath } from 'node:path'
import { SettingsConflictError, type SettingsNamespace } from '@deepseek-ai/dsh-settings'
import { apply, mediaTypeForPath, wsCloseReasonOf } from '../src/index.ts'
import { SidebarError } from '../src/wire.ts'
import { PrefsSchema } from '../src/config.ts'
import { SIDEBAR_PREFS_DEFAULTS } from '../src/prefs-shared.ts'
import { encodeHtmlUrl } from '../src/html-route.ts'
import * as git from '../src/git.ts'
import { listDirectory } from '../src/fs-tree.ts'
@@ -828,29 +830,31 @@ describe('session cwd resolution over the API route', () => {
})
describe('side card settings routes', () => {
/** A minimal settings seam: register/describe/update with the revision guard. */
/** A minimal settings seam: describe/update with the revision guard (0.2.0-rc.2 API). */
const createFakeSettings = (pre?: Record<string, Record<string, unknown>>) => {
const namespaces = new Map<string, {
schema: unknown
value: Record<string, unknown> | undefined
revision: number
}>()
// 0.2.0-rc.2: the plugin's Config schema is auto-registered by the loader.
// The mock pre-seeds the sidebar namespace so describe() returns it even
// when the plugin no longer calls register() explicitly.
if (!pre || !('dsh-apes-sidebar' in pre)) {
// Use SIDEBAR_PREFS_DEFAULTS as the resolved value for the sidebar ns:
// the real SettingsForms service applies the Config schema defaults
// when no stored value exists, which is exactly what this constant is.
namespaces.set('dsh-apes-sidebar', { schema: (input: unknown) => input ?? SIDEBAR_PREFS_DEFAULTS, value: undefined, revision: 0 })
}
for (const [ns, value] of Object.entries(pre ?? {})) {
namespaces.set(ns, { schema: (input: unknown) => input, value, revision: 0 })
namespaces.set(ns, { schema: (input: unknown) => input ?? {}, value, revision: 0 })
}
const resolve = (entry: { schema: unknown; value: Record<string, unknown> | undefined }): unknown => {
const schema = entry.schema as (input: unknown) => unknown
return entry.value === undefined ? schema(undefined) : schema(entry.value)
}
return {
register(ns: string, schema: unknown) {
// Preserve a pre-seeded value: tests stage prefs through the `pre`
// map before the plugin mounts and registers the same namespace.
const existing = namespaces.get(ns)
namespaces.set(ns, { schema, value: existing?.value ?? undefined, revision: 0 })
return { get: () => ({}), watch: () => () => {}, update: async () => {}, replace: async () => {} }
},
describe() {
describe(_options?: { redactSecrets?: boolean }) {
return [...namespaces.entries()].map(([ns, entry]) => ({
ns,
value: resolve(entry),
@@ -864,7 +868,9 @@ describe('side card settings routes', () => {
if (expectedRevision !== undefined && expectedRevision !== entry.revision) {
throw new SettingsConflictError(ns as SettingsNamespace, expectedRevision, entry.revision)
}
entry.value = { ...entry.value, ...patch }
// The real SettingsForms re-applies the full schema (with defaults)
// on every update, so the stored value is always a complete object.
entry.value = { ...SIDEBAR_PREFS_DEFAULTS, ...entry.value, ...patch }
entry.revision += 1
},
}
@@ -872,6 +878,9 @@ describe('side card settings routes', () => {
const mountWithSettings = (settings?: unknown): SidebarWebRoute => {
const routes: SidebarWebRoute[] = []
// Event bus: the 0.2.0-rc.2 settings service emits
// `settings/document-updated` on the plugin context after each update.
const eventHandlers = new Map<string, Array<(...args: unknown[]) => void>>()
const ctx = {
webRuntime: { trustedHosts: [] },
webServer: {
@@ -882,11 +891,30 @@ describe('side card settings routes', () => {
tools: { register: () => () => {} },
effect: (fn: () => void | (() => void)) => { fn() },
inject: (deps: string[], callback: (sctx: { settings: unknown }) => void) => {
if (deps.includes('settings') && settings !== undefined) callback({ settings })
if (deps.includes('settings') && settings !== undefined) {
const s = settings as { update: Function; describe: Function }
// Wrap update to emit `settings/document-updated` after each write,
// mirroring the real SettingsForms service behavior.
const origUpdate = s.update.bind(s)
s.update = async (ns: string, ...rest: unknown[]) => {
await origUpdate(ns, ...rest)
const handlers = eventHandlers.get('settings/document-updated') ?? []
for (const h of handlers) h(ns)
}
callback({ settings: s })
}
return () => {}
},
// The session/agent event feeds: nothing emits in these tests.
on: () => () => {},
on: (event: string, handler: (...args: unknown[]) => void) => {
const existing = eventHandlers.get(event) ?? []
existing.push(handler)
eventHandlers.set(event, existing)
return () => {
const handlers = eventHandlers.get(event) ?? []
const idx = handlers.indexOf(handler)
if (idx >= 0) handlers.splice(idx, 1)
}
},
// No jobs/agents services: the jobs routes degrade to a 503.
get: () => undefined,
}
@@ -1002,6 +1030,9 @@ describe('side card settings routes', () => {
workspaceFence: true,
terminalShell: '',
terminalShellArgs: '',
titleBarScheme: 'auto',
titleBarPresetId: '',
customCss: '',
titleBarCompat: false,
titleBarStripPx: 40,
htmlViewerNoSandbox: false,
@@ -1144,23 +1175,18 @@ describe('agent terminal tool gating', () => {
it('injects the eight tools only when the side-card setting is enabled (default off)', () => {
let registered = 0
let disposed = 0
// The tools currently registered (registered minus disposed).
const live = (): number => registered - disposed
// A ref container: the watch callback is only assigned inside a closure,
// which TypeScript's control-flow analysis ignores (the bare variable
// would narrow to null and refuse the optional call).
const watcherRef: { current: (() => void) | null } = { current: null }
// 0.2.0-rc.2: no more register()/watch(). The plugin reads settings via
// describe() and listens to `settings/document-updated` on ctx.on().
let enabled = false
const handlerRef: { current: ((ns: string) => void) | null } = { current: null }
const settings = {
register() {
return {
get: () => ({ agentTerminalTools: enabled }),
watch: (callback: () => void) => { watcherRef.current = callback; return () => {} },
update: async () => {},
replace: async () => {},
}
},
describe: () => [],
describe: () => [{
ns: 'dsh-apes-sidebar',
value: { ...SIDEBAR_PREFS_DEFAULTS, agentTerminalTools: enabled },
applies: 'live' as const,
revision: 0,
}],
async update() {},
}
const ctx = {
@@ -1176,9 +1202,10 @@ describe('agent terminal tool gating', () => {
if (deps.includes('settings')) callback({ settings })
return () => {}
},
// The session/agent event feeds: nothing emits in these tests.
on: () => () => {},
// No jobs/agents services: the jobs routes degrade to a 503.
on: (event: string, handler: (...args: unknown[]) => void) => {
if (event === 'settings/document-updated') handlerRef.current = handler as (ns: string) => void
return () => { handlerRef.current = null }
},
get: () => undefined,
}
apply(ctx as never)
@@ -1186,18 +1213,18 @@ describe('agent terminal tool gating', () => {
expect(live()).toBe(0)
// Flipping the setting on registers all eight tools.
enabled = true
watcherRef.current?.()
handlerRef.current?.('dsh-apes-sidebar')
expect(live()).toBe(8)
expect(disposed).toBe(0)
// Flipping it back off unregisters them (and releases any agent terminals).
enabled = false
watcherRef.current?.()
handlerRef.current?.('dsh-apes-sidebar')
expect(live()).toBe(0)
expect(disposed).toBe(8)
// And a redundant toggle registers them fresh (no double-registration per
// flip: the guard only skips when the tools are already live).
enabled = true
watcherRef.current?.()
handlerRef.current?.('dsh-apes-sidebar')
expect(live()).toBe(8)
expect(registered).toBe(16)
})
@@ -1208,18 +1235,15 @@ describe('agent sidebar-open tool gating', () => {
let registered = 0
let disposed = 0
const live = (): number => registered - disposed
const watcherRef: { current: (() => void) | null } = { current: null }
let enabled = false
const handlerRef: { current: ((ns: string) => void) | null } = { current: null }
const settings = {
register() {
return {
get: () => ({ agentOpenTools: enabled, tabsEnabled: {} }),
watch: (callback: () => void) => { watcherRef.current = callback; return () => {} },
update: async () => {},
replace: async () => {},
}
},
describe: () => [],
describe: () => [{
ns: 'dsh-apes-sidebar',
value: { ...SIDEBAR_PREFS_DEFAULTS, agentOpenTools: enabled },
applies: 'live' as const,
revision: 0,
}],
async update() {},
}
const ctx = {
@@ -1235,8 +1259,10 @@ describe('agent sidebar-open tool gating', () => {
if (deps.includes('settings')) callback({ settings })
return () => {}
},
// The session/agent event feeds: nothing emits in these tests.
on: () => () => {},
on: (event: string, handler: (...args: unknown[]) => void) => {
if (event === 'settings/document-updated') handlerRef.current = handler as (ns: string) => void
return () => { handlerRef.current = null }
},
get: () => undefined,
}
apply(ctx as never)
@@ -1244,17 +1270,17 @@ describe('agent sidebar-open tool gating', () => {
expect(live()).toBe(0)
// Flipping the setting on registers the single sidebar_open tool.
enabled = true
watcherRef.current?.()
handlerRef.current?.('dsh-apes-sidebar')
expect(live()).toBe(1)
expect(disposed).toBe(0)
// Flipping it back off unregisters it (and drains the undelivered queue).
enabled = false
watcherRef.current?.()
handlerRef.current?.('dsh-apes-sidebar')
expect(live()).toBe(0)
expect(disposed).toBe(1)
// And a redundant toggle registers it fresh (no double-registration).
enabled = true
watcherRef.current?.()
handlerRef.current?.('dsh-apes-sidebar')
expect(live()).toBe(1)
expect(registered).toBe(2)
})