HuanLinOTO
9a2c56eb42
test: 按 Copilot review 修测试健壮性(localStorage try/catch、动态 uuid);记录 pinned 跨会话限制
2026-09-09 14:29:44 +08:00
HuanLinOTO
993f7aaacd
feat(terminal): terminal_wait_for 增 skipped 结果与 agent-pty.skip-wait 路由
2026-09-09 13:26:36 +08:00
HuanLinOTO
3e408dbe48
feat(terminal): wait_for needle 支持 regex,found 返回实际匹配文本
...
needle 以 JavaScript 正则优先(编译失败回退字面匹配,旧字面 needle 完全兼容);found 结果新增 match 字段回报实际匹配文本——单个 needle 可覆盖多结局场景(如 (BUILD_OK|BUILD_FAIL) 同步构建成功/失败,match 区分命中分支);工具 description / needle 参数 / output schema / render 同步更新并写明多重匹配场景;新增 3 个 pty 级测试(alternation 命中分支、非法正则回退、元字符匹配);全量测试失败集合与干净 main 基线完全一致(27 个失败均为预存在 win32 非回归)
2026-09-08 23:07:07 +08:00
多玩幻灵qwq
d71261ace3
fix(cwd): resolve detached session cwd via persistence index, not host process cwd ( #372 )
...
* fix(cwd): resolve detached session cwd via persistence index, not host process cwd
sessionCwdOf fell back to process.cwd() when a session was not yet
attached and the client did not send a cwd — on Windows the host
process cwd is the DSH source root (dsh.cmd's pushd %DSH_ROOT%),
so every user-project path failed the workspace containment guard
with 'path "..." is outside workspace'. The bug surfaced when
clicking chat file links at first paint (session still hydrating)
or any flow that hit a sidebar route before the client's
fetchedCwd effect resolved.
Fix: thread ctx.get('sessionPersistence') as the fallback between
the client cwd and the host process cwd. The persistence index
holds every persisted session's header (including cwd), so a cold
(detached) session resolves its real project cwd instead of the
DSH source root. The host process cwd remains the final fallback
for deployments without persistence (tests / stripped-down hosts);
production always provides persistence.
sessionCwdOf is now async; all 8 call sites await it. The two tool
resolvers (registerTools / registerOpenTool) take an async
resolveCwd callback; the one execute path that used it
(terminal_create) is now async.
Tests: two new regression cases in smoke.spec.ts cover the cold
session via persistence path and the persistence-without-cwd
fallback. Existing stubs updated to the async resolveCwd signature.
* Address Copilot review: fix JSDoc accuracy and validate persistence cwd
- tools.ts / agent-opens.ts: correct the resolveCwd JSDoc — the resolver
does fall back to the host process cwd as a final tier (tests /
stripped-down hosts); the previous "never falls back" wording
contradicted the actual sessionCwdOf contract.
- index.ts: route the persistence meta.cwd through requireAbsolute,
matching the clientCwd path. A buggy/corrupt persistence layer that
stored a relative cwd would otherwise flow into the workspace guard,
be resolved against the host process cwd, and potentially recreate
the original "outside workspace" misclassification in a harder-to-
debug way.
- smoke.spec.ts: use resolvePath() for the cold-cwd fixture so it is
absolute on both POSIX and Windows; add a regression test for the
relative-cwd rejection path.
2026-08-27 21:44:04 +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
8edfbfde44
fix: 修复 agent 终端工具审查问题(terminal_list 输出契约、跨会话归属、UTF-8 截断边界等),工具注入改为设置面板开关(默认关闭)
2026-08-10 21:43:58 +08:00