Menghuan1918
ddb66c9c08
fix(market): 移除公开版 cordis peer 并迁移类型基底到 @deepseek-ai/cordis
...
DSH 市场(dsh-community-market)预览硬拒依赖字段出现 'cordis'
(dependencies/peerDependencies/optionalDependencies 任一字段、
optional 均无效),导致 dshfind/1024Store 目录拿不到
repository_backlink 验证目标,点击安装报
"This catalog item has no verified install target"。
- package.json: 删除 cordis peer + peerDependenciesMeta;版本 0.15.2
- context-types.ts: Context 基底改 @deepseek-ai/cordis,结构服务面改
交集(避免 DS host/client 对同一成员类型不同导致的 TS2717 merge
冲突),仅保留 betterSidebar 的 module augmentation;删除
declare module 'cordis'
- client/index.tsx: 4 处 effect 体失败分支改返回 no-op disposer
(vendored cordis effect 契约拒绝 undefined 形状)
- 新增 tests/market-manifest.spec.ts:无 cordis 依赖字段、打包产物
无生命周期脚本、bundle patch 安全路径、仓库身份、精确稳定版本
- 消费者检查扩展:@deepseek-ai/cordis 路径的 Context augmentation
断言;文档示例同步迁移
2026-08-23 00:26:39 +08:00
NuperAki and Menghuan1918
6cea4bdd6f
fix(subagent): 子代理页实时预览改为批量接口,避免 O(N²) history 请求风暴 ( #298 )
...
* fix(subagent): 子代理页实时预览改为批量接口,避免 O(N²) history 请求风暴
## 背景
DSH Web UI 中,当主代理同时运行多个子代理时,`dsh-better-sidebar` 的「任务管理/子代理」页面会出现明显卡顿。经调查,卡顿根因不在页面渲染,而在实时预览的请求模式。
## 根因
旧实现中,每个 running 子代理卡片都独立轮询 `subagents.history`:
- N 个 running 子代理 → 每 3 秒产生 N 次 `subagents.history` 请求;
- 每次 `subagents.history` 都会在 host 侧触发一次完整的 `listChildren` 全量子代理目录枚举;
- 子代理数量越多,服务端重复扫描越严重,近似 O(N²) 放大;
- 请求超过 3 秒时,客户端还会 abort 旧请求并重发,进一步形成请求风暴。
## 改动内容
1. **新增 host 批量接口 `POST /sidebar/api/subagents.live`**
- 请求 `{ rootSessionId }`;
- 通过 `ctx.subagents.listDescendants(rootSessionId)` 一次枚举整棵子代理树;
- 仅对 running 且非 Side Chat 的子代理,从 session events 尾部提取最新 `text/tool` 活动;
- 返回 `{ live: Record<childId, { text?, tool? }> }`;
- 缺 `subagents`/`agents` 服务或枚举失败时返回 503;单个子代理日志异常只跳过该子代理。
2. **客户端改为单轮询 + 单飞行请求**
- 删除每个 running 子代理独立的 `subagents.history` 定时器;
- 在 `SubagentView` 中合并为一个 `useSubagentLive` 轮询 hook;
- 使用递归 `setTimeout` 和单在途请求,慢请求不再被 abort/重发;
- 页面隐藏或 root 变化时停止轮询并中止在途请求。
3. **解析器优化**
- `lastActivity` 改为接收原始 `SidebarSessionEvent[]`;
- 从事件尾部向前扫描,找到最新 text 和 tool 后提前停止,避免复制/遍历完整历史。
4. **UI 保持不变**
- 实时预览的展示逻辑、文案、截断规则均未改变。
## 测试
- 新增 `tests/subagent-live-route.spec.ts`:覆盖批量接口成功聚合、只返回 running、跳过 Side Chat、缺服务 503、枚举失败 503、`ctx.get` 回退、bad-request。
- 新增 `tests/subagent-live-polling.spec.tsx`:覆盖每轮只发 1 次 `subagents.live`、不再调用 `subagents.history`、单在途不并发。
- 更新 `tests/subagent-activity.spec.ts` 与 `tests/subagent-jobs-view.spec.tsx`。
- `pnpm typecheck` ✅
- `pnpm build` ✅
- 相关测试 29 个全部通过 ✅
> 本机完整 `pnpm test` 仍有与本改动无关的环境性失败(node-pty 超时、Windows CRLF 断言、pty-deps 路径断言),不影响本 PR 逻辑。
* fix(subagent): live 预览以 catalog activity 为准,删除 agents 第二事实源 (#298 )
- host 路由 running 门改回 entry.activity === 'running'(与客户端卡片渲染门一致),
恢复 PR 承诺的 UI 不变:turn 间 idle 的 continuable 子代理仍显示最后活动
- 删除 ctx.agents 依赖与 SidebarAgent.status 新增(agents 缺失时不再静默 200 空 map;
503 契约收窄为只涉及 subagents,与文档/测试一致)
- service 解析统一为 ctx.get('subagents')(兄弟路由惯例;插件未 inject subagents,
直接属性访问有抛错风险)
- buildSubagentLiveApi 签名改收完整 Context,删除 SidebarSubagentLiveContext 窄接口
- api.ts 复用 LastActivity,删除重复类型 SubagentLiveEntry
- 测试:route spec 删除 agents 相关用例;polling spec 新增页面隐藏停止轮询、
root 变化清空 live 并重启轮询两个用例
* fix(subagent): live 预览恢复最近 12 条消息窗口,排除陈旧活动 (#298 )
CR 反馈:新批量接口把完整 session event log 喂给 lastActivity,
- 长时间只输出文本、早期调用过工具的 running 子代理会持续显示陈旧 tool
- 无 tool 的长会话每次轮询反向扫描整个事件数组,重新引入与历史长度
相关的 CPU 成本
修复(与旧 subagents.history({ maxMessages: 12 }) 窗口语义一致):
- lastActivity 增加可选 maxMessages 参数:反向扫描按表面消息
(user/message + assistant/message)计数,窗口满后更老事件一律跳过
- 路由传 LIVE_WINDOW_MESSAGES = 12(导出常量)
- 回归测试:窗口外旧 tool 不返回;窗口内 tool 保留;非消息事件不消耗配额
---------
Co-authored-by: Menghuan1918 <menghuan2003@outlook.com >
2026-08-21 18:15:49 +08:00
Atlas Zeng
7f4f84c4cf
feat(sidechat): 侧边对话——每对话一 Tab(Codex 对齐)+ 完整上下文继承 + 保存为新会话 ( #286 )
...
三轮实测驱动迭代:种子信封透传(surfaceOp 校验)、每线程一 Tab 交互重做完、四连修(fork 丢 this / 自绘 history+save 图标 / collectOwnEvents 大页回源修重开丢工具行 / descriptor 入种子修目录 corrupt 行 + 前缀过滤保拓扑零噪音)。739 单测 + 挂载冒烟 12/12 全绿。
2026-08-21 15:41:14 +08:00
Atlas Zeng
6c891514b5
feat(injection): 统一面板宿主注入重构——含块层+几何写路径+chunk缓存+锚点弱化+桌面/移动适配 ( #232 )
...
* feat(injection): 统一面板宿主——固定含块层 + 挂载自检降级 + body 锚点守卫
- Sidebar 渲染根包 [data-dsh-panel-host](fixed inset-0 pointer-events:none)
- 面板/开关簇由 fixed 改 absolute(层内视口坐标等价),免疫套壳中间层 transform 劫持
- 挂载后一次性几何自检:页面级 transform 时降级 absolute + rAF 视口同步
- MutationObserver(body childList)守卫锚点被宿主清空时重挂
* perf(injection): 几何写路径统一为 writeGeometry + 面板 layout 隔离
- 拖拽帧与打开态共用单一推挤写入器(--dsh-sidebar-width/height)
- .panel/.bottomPanel contain: layout style——内部重排不外泄
- 拖拽期(body[data-dsh-sidebar-dragging])才挂 will-change: transform
* perf(chunks): HMR 激活保留未变 chunk 的已解析 exports + ETag HEAD 重验证
- 新增 revalidateChunksOnReactivate():激活时 HEAD 每个已加载 chunk 对比 ETag,
未变保留内存缓存(跳过重注入/重执行),变更或不可达则 fail-open 重取
- 测试夹具与孤儿缓存条目不跨激活存活
- index.tsx 激活路径由 resetChunks() 改为 revalidateChunksOnReactivate()
* fix(layout): 推挤锚点改 data 属性 + #root calc 宽度防桌面壳溢出
- nth-child(2) → #root [data-dsh-frame] > [data-pane="conversation"](实证同元素)
- #root 宽度 calc(100% - var) 与 margin 同步过渡:web 视觉不变(实测 1140+300=1440 无溢出),
Desktop 壳(#208)width:100% 的加性溢出根因消除
* feat(desktop): 桌面信号自动探测 + win32 顶栏 overlay 自动避让 + 键盘/safe-area 适配
- 新增 desktop-env.ts:解析 dsh-desktop-mode/platform URL 信号与 preload 标记
- win32 advanced 壳自动启用 titleBarCompat(32px overlay),手动 pref 仍可覆盖
- visualViewport 键盘 inset:底部面板/窄屏抽屉键盘弹起时上移
- 面板与开关簇 safe-area-inset 适配(env() 桌面端为 0)
- 单测 7 例(含 URLSearchParams 前导 ? 剥除修复)
* docs+e2e: 注入方案实施记录(路线B关闭、偏差记录、基线数据)+ 契约同步 + e2e 新断言
- 设计文档:路线 B 标记关闭、§8.1 改单 PR 步骤(含 commit 对照)、拖拽基线数据、实施偏差记录
- AGENTS.md §8:data-dsh-panel-host 含块层、推挤锚点契约(禁 nth-child)、桌面信号
- mount.e2e:data-dsh-panel-host 断言 + win32 advanced 桌面信号场景
* fix(cr): 响应 #232 CR 三条 findings
- P1 降级同步:按未修正几何判定(跟踪自身补偿量),祖先 transform 消失才退出循环——
修正后矩形不再被误判为无需修正(自清除缺陷)
- P1 chunk 重验证成为 loadChunk 屏障:重验证挂起期间不提供缓存,杜绝 HMR 竞态陈旧 exports;
测试夹具加载不再被误记为生产加载
- P2 键盘 inset:innerHeight - (vv.height + vv.offsetTop),并监听 scroll(offsetTop 变化)
- 新增屏障单测 1 例;设计文档偏差记录更新
* fix(chunks): 屏障 HEAD 加超时兜底 + resetChunks 清 revalidation
- revalidateChunksOnReactivate 的 HEAD 与 recordEtag 均带
AbortSignal.timeout(5s):路由挂起时 fail-open(drop + 重取),
屏障不再可能无限期阻塞所有懒加载 chunk(CR #232 P1 修复的健壮性缺口)
- resetChunks 同步清 revalidation:重验证挂起期间重置后,
loadChunk 不再等待已丢弃状态的孤儿任务(finally 身份判断 no-op)
- 单测 +2:HEAD 挂起超时 fail-open(fake AbortSignal.timeout 触发中止)、
resetChunks 清屏障后 loadChunk 立即放行
* fix(deps): align @deepseek-ai/* peers with DSH 0.1.0-rc.8
- peer/devDependencies: 13 个 @deepseek-ai/* 从 ^0.1.0-rc.7 升至
^0.1.0-rc.8;删除随 rc.8 消失的 dsh-client-web-react / dsh-client-schema-form
(无 rc.8 发布、rc.8 依赖树与壳 bundle 零引用、插件 src 零引用);
cordis peer/devDep 同步升 ^4.0.0-rc.8
- 版本 0.13.1 -> 0.14.0(package.json / dsh.plugin.json /
SIDEBAR_SERVICE_VERSION 三处同步)
- CHUNK_EXTERNALS / CLIENT_EXTERNALS / CLIENT_REQUIRE_ALLOWED 三处镜像
同步删除两个死包(primitives/slots 仍是 rc.8 壳静态模块表种子,保留)
- CI 挂载冒烟钉版 @deepseek-ai/dsh@0.1.0-rc.7 -> rc.8
- pnpm clean --lockfile 全量重解析:lockfile 内 @deepseek-ai/* rc.7 残留
清零(传递链同升 rc.8,杜绝 #206 式混用树);pnpm-workspace.yaml
minimumReleaseAgeExclude 按 #207 模式整体换为 rc.8 列表
- 文档同步:README 安装说明、AGENTS.md CI 钉版、外部插件指南与设计文档
cordis 示例、issue 模板版本示例
* feat(prefs): editorExplorer 默认独立(关)——文件各自新开 tab
- SIDEBAR_PREFS_DEFAULTS 与 host PrefsSchema 的 editorExplorer 默认
true -> false:新会话树点击/打开文件按 path 新开 tab,无路径窗口即
纯资源管理器;合并模式保留为可选手动开启(持久化过的用户设置不受影响)
- 测试同步:prefs.spec 默认断言翻转、plugin-shape.spec 与 smoke.spec
默认对象翻转;editor-host 合并模式用例显式开启 editorExplorer(split
用例本已显式);side-card-section-rows 的 select 行用例固定选中 Merged
- e2e 重写:mount.e2e 文件打开流程从 in-place 断言改为独立模式
(新开 hello.txt tab、Files home tab 保留),文件头注释同步
- 契约文档同步:AGENTS.md §3.4 editor 行默认描述翻转 + CI 冒烟描述、
README/README_EN v0.13.0 特性描述 + v0.14.0 changelog
* fix(client): rc.8 模块系统经 ctx.modules 注入 + chunk 副本全局共享
rc.8 不再暴露 window.__DSH_MODULES__ 页面全局(改由 ctx.modules 服务
提供),chunk 外部依赖解析全面失效(terminal/editor/mermaid 全部
"client module system unavailable")。修复:
- src/client/index.tsx: inject 增加 'modules'(Cordis 服务访问守卫,
此前直接读 ctx.modules 抛 "cannot get property modules without
inject");apply() 激活时 setChunkModuleSystem(ctx.modules)
- package.json dsh.client.inject 增加 @deepseek-ai/dsh-client-modules
- chunk-loader: 注入写插件自有页面全局 __dshSidebarModuleSystem__——
懒加载 chunk bundle 各自内联一份 loader(rc.7 靠官方全局回退工作,
rc.8 全局消失后副本注入变量恒空);moduleSystem() 按
注入变量 → 插件全局 → rc.7 全局回退解析
- context-types: Context 镜像补 modules 服务声明(client half)
- e2e: assertNoCrash 失败时输出错误条文本;独立模式断言修正
(Files 数量按存在性、mermaid 流程先切回 Files、md 预览 locator 去掉
重复的 [data-dsh-better-sidebar] 嵌套)
验证:typecheck / 639 测试全绿;本地 rc.8 CLI + Chromium 挂载冒烟 3/3
通过(drag-layout、mount 深扫含 editor/mermaid chunk、桌面信号)
* feat(settings): 终端 shell/shellArgs 可在设置页配置(bash 管理)
- SidebarPrefs 新增 terminalShell / terminalShellArgs(默认空 = 保持
yaml config.shell → $SHELL / 登录 shell / powershell.exe 的既有解析)
- 终端卡齿轮二级页面新增两行 text 配置(与字体行同列)
- host 侧生效链路:UI 终端 WS 打开与 agent terminal_create 均读取
设置文档覆盖(ptyManager.open / AgentPtyRegistry.create 增加可选
shell 覆盖参数;shellOverridesOf 解析设置文档);设置页写入即时
影响之后打开的终端(既有 pty 保持原 shell)
- locales zh/en 文案;parsePrefs 校验新字段;测试同步
* feat(settings): 侧边卡片设置页加 DSH-better-sidebar 版本徽标
- 设置页 intro 下新增身份徽标:名称 + v{service.version}(服务实例
版本,与 package.json 由 tests/service.spec.ts 保持同步)
- token 驱动样式(--dsw-alias-*),名称/版本 pill 布局
* fix(drag): 快速拖动提交最后位置 + HMR 后中心列重定位兜底
快速释放(浏览器合并/丢失 pointermove 突发,超快速 flick 甚至可能
完全无 move)时的回退问题:
- pointerup 优先采用最后一次已知拖动值(rAF pending),而非 up 位置
(事件合并时可能等于按下位置)
- pointercancel / lostpointercapture 中断时同样提交最后已知位置;
无 move 时用中断事件自身的坐标计算(clamp 后提交)——只有真正
未产生位移的拖动才回滚
- commitDrag 统一 flush + 同值提交 + 立即重测中心列(消除提交后
React 用旧 centerRect 覆盖底栏 right 的中间帧)
HMR 重激活后底栏空白(输入框被推挤上移、强制刷新恢复):
- 根因:新组件实例重跑 locate 时壳的 centerCol 尚未就绪,而壳重建
复用 #root 子节点(childList 观察器不触发)→ centerRect 卡 {0,0}
→ 底栏 visibility:hidden 永久空白
- 修复:额外观察 <html> 的 style 属性(layout push 写回 --dsh-sidebar-*
时重定位重测);底栏打开时 effect 重跑 locate/measure 兜底
- 底栏未测量时由「不渲染」改为 visibility:hidden(渲染链不被几何
门控,jsdom 测试不回归)
e2e 新增:极快拖动(单 move 立即 up)提交拖动位置、稳定后不回退
* feat(plugins): 添加插件目录支持搜索/分组/独立滚动(多插件场景)
- PluginListBody 顶部加实时搜索框(按名称/id/描述过滤,空结果提示)
- PluginEntry 增加可选 category 分组字段(i18n 友好),目录条目按组
渲染(未分类条目保持平铺);数量徽标跟随过滤结果
- 条目列表 max-height + overflow-y 独立滚动,插件多时弹窗不再无限
增长;渲染数量由搜索天然收敛
- locales zh/en(搜索占位、无匹配);测试文件固定英文环境
(vitest 4.1.11+ jsdom 跟随系统 locale,本机 zh-CN 导致英文文案
断言漂移)
* chore(deps): 适配 pnpm 11.8 supply-chain 校验(exclude 通配)
pnpm 11.8.0 起对 lockfile 既有条目强制 minimumReleaseAge 校验,
且精确 exclude(@scope/pkg@version)对带 peer 依赖后缀的解析条目
匹配失效(44 条误报违规,CI 全红)。@deepseek-ai/* scope 为官方
可信 scope,minimumReleaseAgeExclude 改为 '@deepseek-ai/*' 通配
(保留 rc.1 历史与 stable 条目);通配经实测通过全部 504 条校验。
* docs: v0.14.0 changelog 补全(自 v0.13.1 全部更改 + 特别声明 rc.8 适配)
新增条目:终端 shell/shellArgs 设置页配置、设置页版本徽标、
添加插件目录搜索/分组/滚动、rc.8 模块系统迁移、拖拽健壮性修复;
版本说明块醒目声明本版适配 DSH 0.1.0-rc.8(rc.7 及更早无法解析依赖)
2026-08-20 02:09:36 +08:00
Menghuan1918
c0aeefc936
fix: 回应审查保留意见 — 测试钉住跨站分支、删死接口、修正注释措辞
...
- tests/trusted-hosts.spec.ts:用例 4 改为受信 origin + cross-site marker
以隔离拒绝分支(原同时踩 marker 与 origin 两条路径,删除 marker 检查
测试依旧通过——变异验证现仅该用例失败);接受侧断言从 not.toBe(403)
收紧为 toBe(200),请求体补 sessionId(session.cwd 的真实契约)
- src/context-types.ts:删除已无引用的 SidebarLoader/SidebarLoaderEntry
死接口(loader 成员移除后残留)
- src/index.ts:修正 "same list / 无需重启" 过承诺注释,改为与 /api 网关
同源的准确表述(boot 采样快照 + --trusted-host 权威,读 live 服务值)
2026-08-14 23:03:26 +08:00
Rookie_Zoe
ea250c9e87
fix: /sidebar 信任栅栏改用 webRuntime.trustedHosts,修复远程访问全部 403
...
根因:trustedHostsOf 按 entry.options.name === 'connection' 查找 connection
行,但该行 name 是模块标识符(@deepseek-ai/dsh-client-connection,id 才是
connection),查找永远落空 → trustedHosts 为空 → 栅栏只放行回环 Host → 通过
域名或局域网 IP 访问时 /sidebar/bundle chunk 加载失败、资源管理器/代码管理器
全部 403 forbidden(/api 不受影响,它读的是 apply 时已求值的配置)。
修复(按 review 建议):host half 直接注入 webRuntime 服务,栅栏每请求实时
读取 ctx.webRuntime.trustedHosts —— 与 /api 网关同一信任列表(启动时采样的
LAN IP 字面量 + --trusted-host 权威),不再依赖 Loader entry / fiber /
!!js 节点求值;自定义信任域名由 dsh web --trusted-host 提供。
新增 tests/trusted-hosts.spec.ts 回归:域名/局域网放行、空列表仅回环、
跨站标记拒绝、每请求实时读取;plugin-shape 断言同步更新。
2026-08-14 23:03:26 +08:00
Menghuan1918
82a69546d2
feat: 公共 API 基座化(v0.12.0,纯增量)— 类型/能力/设置 seam 全面补齐
...
- 类型生态:service 模块 re-export SidebarTab/SidebarState/SidebarStore/
SidebarSnapshot/SidebarDiffRef/TabType/SessionScope/SidebarPrefs 等公共
状态词汇(此前 TS2459 无法命名);context-types 去 Node 依赖(结构镜像
SidebarHttpRequest/Response/UpgradeSocket/Head),client 可达声明图零
node:* 引用,外部消费者无 @types/node + skipLibCheck:false 可编译
(scripts/check-consumer-types.sh 守护)
- 服务能力:version/features 版本与能力探测(单调只增)、getSnapshot/
subscribeState 状态订阅、updateTab(title/path/meta)、activateTab、
openFile(路径派生 id 与内置拦截一致)、openTab(seed, scope?) 定向到
指定 session(store.reduceFor 不扰动 UI)
- TabDescriptor:badge 角标(99+ 封顶,抛错吞掉)、onOpen/onActivate/
onClose 生命周期回调(service 路径派发,dedupe 聚焦触发 onActivate
而非 onOpen,抛错不打断流程);SidebarTab.meta JSON 可序列化跨刷新
持久化(sanitize 宽松保留)
- 设置 seam 开放:PrefsSchema 增 pluginSettings 开放嵌套 map(z.dict),
settings.pluginToggles(插件自有行,同 switch/text/number 控件)与
settings.render(自定义面板,含 store/service/prefs/updatePluginSetting/
close props);viewer 卡片 v0.12.0 起也有齿轮设置弹窗
- FileViewerDescriptor.load 增第三参 AbortSignal(EditorHost 生命周期中止)
- UI 接线:tab 激活/关闭改走 service(跨树激活修复 + 回调触发)、+ 菜单
传 scope、TabBar badge pill 渲染;active-session scope 走原 reduce 路径
保证 notify
- 测试 +23:生命周期/定向打开/updateTab/activateTab/openFile/meta 持久化/
reduceFor/能力常量(与 package.json 锁步)、consumer-types.ts 编译门、
api-surface.spec.ts(client 图零 node 依赖守护);既有 430 测试全绿
- 文档:AGENTS.md 修 available 三参示例并补全部新 API;external-plugin-
guide.md 刷新至 v0.12.0(7 tab + 9 viewer、设置 seam 开放、类型导入
路径建议);README×2 服务化小节同步
未发版 npm(用户决定);分支 feat/plugin-api-v012。
2026-08-14 20:44:43 +08:00
Menghuan1918
64c6aa477e
chore: v0.10.0 npm 发布准备
...
- @deepseek-ai/* 依赖换为实际发布版本(dsh-* ^0.1.0-rc.6、cordis ^4.0.1),
补齐 dsh-client-locale peer/dev 声明(对齐 dsh.client.inject)
- pnpm-lock.yaml 重新生成(移除旧 0.0.1-rc.1 图;锁文件不再引用未公开的 dsh-type-meta)
- pnpm-workspace.yaml 补 minimumReleaseAgeExclude 新版本条目
- src/context-types.ts 增加 @deepseek-ai/cordis 双 augmentation
- package.json 发布脚手架:publishConfig.access、prepublishOnly、files 含 README_EN/LICENSE
- README 版本注释同步(^0.1.0-rc.6 / dsh@0.1.0-rc.6)
2026-08-13 22:25:20 +08:00
Menghuan1918
1bfabbbfc2
feat: 适配 DSH 命名契约重命名(jobs/terminal/webServer)并处理 Session log 按钮位置
...
- tasks→jobs:ctx.jobs / job_output / job_id / session/jobs / jobsBySession / Job* 词汇
- httpServer→webServer(inject + augmentation + register/registerUpgrade)
- autoOpenTasks→autoOpenJobs 偏好键
- 右上角开关簇回到角落,注入 CSS 挤开 header 的「Session log」胶囊
2026-08-13 09:06:55 +08:00
Menghuan1918
9c5293c94b
feat: 界面文案跟随 DSH 的 i18n(ctx.locale 语言偏好、实时切换、词典入注册表)
2026-08-13 00:43:28 +08:00
Menghuan1918
6e4474cd2e
fix: 任务输出回放合并活事件镜像,修复重启后 store 会话滞后导致新读取不可见
...
- host 半挂 ctx.on('session/event')(api-proxy 同款 API),镜像 task_output
的 tool/call + tool/result 活事件(每会话 200 条有界环,无关结果不缓存)
- tasks.output 回放合并「store 事件日志 + 活事件镜像」,按 seq 去重排序配对
- 零 DSH 写入:会话 store 在宿主重启后可能冻结在再水合边界(持久化文件
停在重启时刻),活事件只走 append 推送链;镜像绕开该滞后
- 测试:新增镜像用例(live 事件、跨会话隔离、种子+镜像合并不双计),
全量 373 通过
2026-08-12 23:04:30 +08:00
Menghuan1918
b90251cce5
fix: 遵守仓库硬约束(禁止修改 DSH 源码)——tasks.output 改为会话事件回放
...
- 回退对 harness peek 缝隙的依赖:输出查看不再调用注册表,改为从属主
会话事件日志回放 task_output 的 tool/call+tool/result 对(模型已读内容)
- read:false 时面板提示「模型尚未读取」;'(no new output)' 增量与错误
结果过滤;截断上限不变;kill 走注册表原生 API(缺席时 503)
- AGENTS.md 新增 §0 硬约束:禁止修改 DSH 源码、挂载只走 cordis.patch.yml
+ profile 机制;设计文档同步实施偏差
- 测试:tasks-routes 重写为回放语义(拼接/过滤/read 标志/截断/503),
视图新增 read:false 提示用例;全量 369 通过
2026-08-12 23:04:30 +08:00
Menghuan1918
8c521be26e
chore: v0.8.0 — 任务管理页(子代理拓扑 + 后台命令底部输出 Dock、两击确认终止)
...
- tab 更名为任务管理:同页显示当前树全部后台命令(bash/pwsh 徽标、状态、时长、属主、退出码)
- 点击任务行在侧边栏底部共享 Dock 显示输出(sticky 终端式、自动跟随、单一轮询实例)
- 运行中任务两击确认强制终止;大量任务时列表保持紧凑、排序变动不跳动
- 新增 /sidebar/api tasks.output(非消费 peek,不偷模型 task_output 字节)与 tasks.kill 路由
- 修复任务镜像清空时的 React #300 hook 顺序崩溃(useCallback 移到提前 return 之前)+ 回归测试
2026-08-12 23:04:30 +08:00
Menghuan1918
67ec136e98
feat: 拦截聊天区文件打开 — 聊天里的文件点击默认开进侧边栏编辑器
...
包装 ctx.workspaces.openPath(聊天区文件打开的唯一漏斗),接管时
经 openSidebarFile 开进 sidebar 编辑器而非系统默认应用;由
interceptOpenPath pref(默认开)与 editor tab 启用态双重门控,
拒接时原样放行,dispose 还原原始方法引用(HMR 安全)。
- prefs-shared/config/prefs: 新增 interceptOpenPath 字段(默认 true)
- openpath-intercept.ts: 零依赖包装器,纯插件层面实现,不改 DSH
- intercept.tsx: registerOpenPathInterception 接线(当前会话 scope)
- SideCardSection: 常规区新增开关卡片(zh/en 文案)
- 测试: 包装器单测 6 个 + 接线集成测试 + pref 解析/设置页断言更新
2026-08-11 16:48:59 +08:00
HuanLinOTO
291158a3ba
feat: 服务化改造 — ctx.betterSidebar 注册表(registerTab/registerFileViewer),内置 6 tab + 6 viewer 迁移到 registry,v0.4.0
...
- 新增 src/client/service.ts: BetterSidebarService 接口 + createBetterSidebarService 工厂
- registerTab/registerFileViewer 返回 disposer(HMR-safe,挂到 cordis fiber)
- matchFileViewer 三段匹配: priority desc → detect(内容嗅探) → exts
- openTab 走 descriptor.dedupeKey 统一去重(替代 isSingle/editor-path/diff-id 三分支)
- createTab 回调支持自定义 tab 创建(terminal 的 nextTerminal 递增)
- 新增 src/client/builtins.tsx: 6 内置 tab + 6 内置 viewer 自我注册(吃狗粮)
- tab: editor(hidden) / explorer / git / subagent / terminal / diff(hidden)
- viewer: image / pdf / docx / xlsx / pptx / binary-download
- code/markdown 保持 EditorView 内联兜底(matchFileViewer 返回 undefined 时走 fsRead+CodeMirror)
- 新增 src/client/OrphanedTab.tsx: 未注册 type 的占位组件(插件未加载时降级)
- 改造 src/client/index.tsx: ctx.provide('betterSidebar') + registerBuiltins
- 改造 src/client/Sidebar.tsx: TabContent/buildNewTabOptions/onNewTab 查表替代 switch
- 改造 src/client/EditorView.tsx: 预览路由查 matchFileViewer 替代 if/else 链
- 改造 src/client/state.ts: TabType 联合字面量→string,sanitizeNode 接受所有 string type
- 改造 src/context-types.ts: declare module 'cordis' 加 betterSidebar 字段
- 改造 src/index.ts: re-export Context + 服务类型(consumer import type 触发 augmentation)
- package.json: 加 ./client/service exports 子路径,version 0.4.0
- tests/service.spec.ts: 12 个新测试覆盖 register/dispose/matchFileViewer/dedupe/createTab
- tests/unit.spec.ts: sanitizeState 测试更新(未知 type 不再被拒绝,渲染 OrphanedTab)
2026-08-11 00:31:23 +08:00
HuanLinOTO
6f62d19905
feat: 为 agent 暴露 8 个终端工具(terminal_create/list/send/read/wait_for/resize/signal/close),侧边栏自动同步 agent 终端 tab,v0.2.0
2026-08-10 19:08:58 +08:00
Menghuan1918
61b18cbefe
feat: Subagent 拓扑页面(主代理根节点 + 分层树 + 实时工具调用 + 自动激活设置),v0.1.9
2026-08-10 17:24:42 +08:00
Menghuan1918
9b00135de4
feat: DSH-native flat chrome + Side card settings (plugin-owned settings wire)
...
- Remove every box-shadow; panel uses the native sidebar fill surface
(--dsw-specific-sidebar-fill) with a hairline border, the collapse
control becomes the native 36px circular rail button, the active tab
uses the native interactive-bg-active fill, and rows/typography follow
the native 34px/14px session-row recipe.
- New 'Side card' settings section in the DSH Settings shell: open-by-
default for new conversations (boolean) and default width share as a
percent of the window (20-60). New sessions seed from these prefs;
existing per-session layouts stay untouched.
- The settings namespace is read/written through the plugin's own fenced
/sidebar routes calling the settings seam in-process: the DSH settings
RPC domain only serves allowlisted namespaces to configuration clients,
so third-party namespaces cannot use connection.api.settings (reads are
silently filtered, writes refused with 'not exposed'). The seam still
persists to the user settings document with revision-guarded writes.
2026-08-09 23:49:58 +08:00
Menghuan1918
e2ee427ea3
feat: per-session store + configurable host limits; fix divider drag runaway
...
- state: side-store per conversation, injected as a prop instead of a module singleton
- host: schemastery Config (read/media/list/terminal limits) resolved from cordis config
- shape: types/exports/peerDependencies for the web profile + plugin-shape spec
- fix: split divider emits incremental deltas so drags track the cursor 1:1
- docs: README refresh
2026-08-09 22:07:03 +08:00
Menghuan1918
c81de3374f
fix: @-reference button no-ops — read conversation via ctx.get, not the ctx property
...
Cordis only grants property reads for services declared in the plugin's
inject list; every other read throws "cannot get property X without
inject" (the app's own plugins read 'conversation' through ctx.get for
this reason). referenceInChat now resolves the conversation service lazily
via ctx.get('conversation') and no-ops when absent. Verified end-to-end in
headless Chrome: clicking the @file button on root/dir/file rows now
appends the at-relative-path mention to the composer draft with no
console errors.
2026-08-09 00:01:56 +08:00
Menghuan1918
6e36a99c88
feat: explorer copy-path & @-reference actions; icons on tabs and + menu
...
- Tabs, the + menu, and empty-pane cards carry per-type icons (folder /
branch / terminal / code file); a terminal glyph joins the icon set
- Hovering an explorer row reveals an @文件 button at the far right that
appends @<relative path> to the composer draft (session-scoped input
service, space-separated append)
- Right-clicking a row opens a context menu: copy relative / absolute
path (writeClipboard + transient in-row "copied" label)
- Rows become div role=button (Enter/Space) to host the inner button;
relativeTo helper unit-tested
2026-08-08 23:46:14 +08:00
Menghuan1918
63e2988ef1
dsh-better-sidebar: VSCode-like right sidebar plugin for the DSH web GUI
...
Host half (src/index.ts): /sidebar/api JSON API (session cwd, fs tree/read/
write, git status/diff/stage/commit/branch/log/show), /sidebar/file media
route, /sidebar/ws/terminal WebSocket over node-pty; routes share the /api
trust fence (Host-header loopback or connection.trustedHosts).
Client half (src/client): portal-mounted right panel with a per-session
split-pane workbench (recursive row/col splits, draggable dividers, tab
drag-move), tab bar with max-width 160px + plus-menu (explorer/git/terminal
multi-open rules), lazy file explorer rooted at the session cwd, editable
text editor (dirty dot, Ctrl/Cmd+S), image + Markdown preview, xterm
terminal with reconnect, and a VSCode-style git panel. Per-session state
persists to localStorage (dsh-sidebar:v1:<sessionId>). Intercepts the chat
turn-tail produced-files row (priority -1 chain entry) to open files in the
sidebar. UI styled with the dsh --dsw-* theme tokens and ui-primitives.
Build: tsdown emits the host lib plus the __ModuleLoader__ client bundle
(externals = module table words; xterm/css inlined). Tests: 19 unit + smoke
specs (pure state/tree/git parsers + real git/fs integration).
2026-08-08 01:02:24 +08:00