Repository navigation
dsh-coding-sidebar 1.0.36
dsh-coding-sidebar 1.0.36
「任务管理」tab 升级:对齐上游 v0.22.0 的重做方向——工作流图画布(新视图,与经典树共享同一视图模型与折叠状态)、两分组折叠聚合,以及 TeamView 的 0.1.7 投影迁移修复(此前所有受支持宿主上团队 tab 都是「服务缺失」空态)。
变更
工作流图(新视图,subagent-tasks-model + subagent-tasks-layout + WorkflowGraph)
- 会话树渲染为分层节点 + 三次贝塞尔连线的画布:拖拽平移、滚轮缩放到光标、
双击背景适配,右下控制条(放大 / 缩小 / 适配)。工具条新增 图/树切换
(宽屏默认图、窄屏默认树),两种模式共享同一视图模型与折叠状态。 - 节点卡:类型徽章(主代理 / 子代理 / 已完成聚合 / 待命聚合 / 占位)+ 名称 +
底部状态条(状态点 + 状态词);运行中节点扫过动画
(prefers-reduced-motion下关闭);当前会话 accent 描边。 - 未水合分支渲染为占位节点(直接子代理计数),并同时触发一次投影读取——
水合后自动替换为真实子树。
两分组折叠聚合
- 子代理按续接模式分两组:已完成(one-shot + 空闲)与 待命(continuable +
空闲,可再次唤起);组员数 ≥FOLD_MIN(6)时折叠为单行聚合(名字行取前两个
成员名),点击展开/收起。运行中行永不折叠。 - 取代旧的「展开更早的 N 个子代理」按时间切割(该键保留于语言包,暂未删除)。
TeamView:agentTeam 投影迁移(P0 修复)
- 故障:0.1.7 删除了服务面的
remoteView/remoteCreateTask/
remoteUpdateTask三方法;本插件团队 tab 仍调用remoteView——peer 下限
(>=0.1.7-rc.2)之后的所有宿主上,团队 tab 恒显「服务缺失」空态、零报错。 - 读路径:改读 Lead Session 的
agentTeamSession 投影
(projectionsBySession[leadId].values.agentTeam,推送式)——客户端订阅
sessions.list,纯派生模块team-projection.ts把投影映射到既有TeamView
形状(成员活跃态/lead 显示名从会话摘要富化;failure上浮为 notice)。
一次性refreshProjections(leadId)触发首次读取;删除team.view路由与
轮询刷新。 - 写路径:服务方法更名
remoteCreateTask/remoteUpdateTask→
createTask/updateTask(caller 仍为 Session 活 Agent;请求形状不变);
team.createTask/team.updateTask两条路由保留。 - 冲突语义不变:过期修订(CAS)提示
teamConflict,看板随投影推送自动回正。
样式表静默失效修复 + 选择条重做 + 样式门禁
- 真根因(比观感严重得多):
sidebar.module.css里.plansEmpty .plansHint
的闭合大括号在 1.0.14 提交中丢失(git log -S定位),其后所有追加规则被
lightningcss 编译成顶层嵌套(产物里是}& .S…_explorerSelectionBar{…}),
浏览器直接丢弃 —— 本轮"选择条样式完全不生效"就是这么来的。受影响规则共
11 条:tocFlash、变更页目录组(gitDir*)、多选组(explorerRowSelected/
explorerSelection*)。已补回大括号,产物中嵌套产物归零。 - 选择条重做:不再是一排 UA 默认灰按钮(
rgb(107,107,107)+2px outset),
改为胶囊式:细边框border-l2+ 分层背景bg-layer-2+ 阴影,左侧计数
label-secondary,右侧为文本按钮(默认无底色、hover 浮起interactive-bg-hover、
带focus-visible焦点环),11px 字号。选中行改为interactive-bg-hover底 +
左侧 2px 指示条。 - 门禁(防同类静默失效):
tests新增"仓库内每个.css去注释后必须大括号
平衡";smoke新增产物级断言"无顶层嵌套产物(}& .)+ 选择条规则以正常选择器
产出"——这类"少一个括号、后面全部失效"的缺陷从此会当场判红。
注册失败必须回滚(上游 v0.22.1「接管 id 孤儿化」的同构守卫)
- 问题同构:本仓库有两处
for (…) disposers.push(register(…))——内建
tab/viewer 注册(src/client/builtins/index.ts)与八个 agent 工具注册
(src/tools.ts)。中途任一步抛错时,前面已占用 id 的 disposer 随栈帧一起
丢失,这些 tab/工具永久无法再注册(下次激活一直 "already registered",
直到刷新页面)——正是上游 #770/#771 那类缺陷。 - 修法:新增纯模块
src/registration.ts的registerBatch():逐项注册并
立刻记录 disposer;任一步失败逆序释放已占用项后原样抛出,使重试真的
能重新注册;返回的 disposer 幂等,单个 disposer 抛错不拖住其余。两处注册
序列都改为整批原子(tab 与 viewer 视为同一批)。 - 附带加固:注册表的
notify()抽为notifyIsolated()——订阅者抛错不再
打断"注册 + 通知"链路(否则tabs.set已生效而 disposer 未返回,同样产生
孤儿 id),也不会跳过其后的订阅者。 - 测试:9 条断言钉在事件日志上——LIFO 释放、幂等、失败后无残留、失败点之后
不再尝试、回滚后重试成功、failed 释放事件可观测、dispose 抛错不拖累、
void 注册安全、订阅者抛错不中断注册且 disposer 仍能释放。
文件页四项(上游 v0.24.1 对应项:多选 / 压缩下载 / 打开方式双源 / fs.trees)
- 多选:
file-selection.ts纯语义(Cmd/Ctrl 加减、Shift 按可见行序取区间、
折叠后剔除不可见项、Cmd/Ctrl+A 全选、Escape 清空),行内aria-selected+
高亮,吸底选择条显示「已选择 N 项」并承载批量动作;配 20 条 node 单测。 - 压缩下载:新增
zip.ts(自研打包器:可压缩走 deflate、否则 store、
UTF-8 名标志位、目录项、Unix 权限、条目/字节双上限、RFC 5987 下载名)与
archive-routes.ts(archive.build立即返回任务、archive.status报
done/total 真进度、archive.result交付字节;并发 4、TTL 5 分钟、单次下载后
释放、48MB 传输上限)。客户端轮询进度并在按钮上显示「打包中 done/total」,
浏览器侧 Blob 保存。 - 打开方式双源:宿主
apps.list扫描/Applications、/System/Applications、
~/Applications(一分钟缓存、上限 200),open.external新增app动作
(open -a <app> <path>,argv-only 无 shell);客户端把本机应用并入菜单,
与内建编辑器同列,远程工作区自动隐藏(本地专用)。 fs.trees批量 + 性能:新增批量路由(一次 ≤32 条、单点失败只影响自己、
读并发 8),客户端展开一层后预取至多 8 个子目录(不递归、跳过隐藏目录);
listDirectory改为一次readdir批量取回再切片(原先opendir异步逐条
迭代)并按目录 mtime 做 LRU 缓存(上限 256,目录自身 mtime 变化即失效)。- 实测(1 万条目录):冷路径 29.4ms → 7.8ms(3.8×),命中缓存
0.05ms(约 160×);8 个子目录 1 次批量请求 3.81ms vs 8 次顺序 4.69ms
(省的是 8→1 次往返)。功能实测:多选 2 项 + 选择条、Shift 区间 4 项、
真实下载client.zip745KB(testzip无错、目录递归、命名正确)、含目录
超 48MB 时给出明确拒绝提示、打开方式子菜单同时列出内建编辑器与本机应用
(124 项,apps.list200)、扩展目录时观察到fs.trees批量请求。
变更页层级树(上游 v0.24.1 对应项)
- 新增纯模型
src/client/changes-tree.ts:扁平路径 → 目录树,含
单子链压缩(src/client/office/viewer合成一行,不占五级台阶)、
递归文件计数、目录优先 + 大小写不敏感排序、折叠展平
(flattenChangesTree)与目录路径收集。配套 node 单测 20+ 条
(压缩/计数/排序/折叠/空段容错/深度)。 - Git 视角:暂存区与未暂存区都改为层级树——目录行带 ▾ 折叠、递归计数徽标
与目录级暂存/取消暂存(git add -A -- <dir>,paths git 原生支持目录,
一次调用覆盖其下全部文件);文件行按层缩进,行内 +/− 统计与单文件操作不变。 - 会话视角:同一套树模型按目录分组会话文件操作(行内预览保持不变)。
- 实测(真实未提交变更):
.tmp-tree-check → a/b/c压缩链 indent 0/14/28px、
递归计数正确(src 6 / client 4 / tree-check-dir 2)、折叠后 8→7 目录且
36→32 行、点src目录的暂存按钮后 6 个文件整体移入「已暂存 (6)」且
未暂存区保留其余目录;无页面报错。
浮动窗(上游 v0.22.0 对应项 ③)
- 新增
FloatingPane(src/client/FloatingPane.tsx+ 同名 module.css):可拖拽
(标题栏)、可四边与四角拉伸、内容区自滚动(拉大把余量给内容,不给
留白),只有关闭按钮或 Escape 结束——外部点击、失焦、锚点离屏都不关;
几何按内容键记忆(重开回到上次位置/尺寸),窗口缩小后自动钳回可见区。
几何数学抽成纯函数floating-geometry.ts(默认右下角放置 / 视口钳制 /
八向拉伸 + 最小尺寸),配套 node 单测 12 条。 - 两个消费者:后台任务输出(原贴底坞改为浮窗,输出未读时给"等待模型读取"
提示)、共享任务详情/编辑(编辑表单移入浮窗,余量交给描述区)。 - 交互实现要点:不用 setPointerCapture(它会把随后的 click 重定向到浮窗,
正是工作流图那个"点不动"的根因),手势期间挂 window 指针监听;浮窗是交互
弹层,刻意不退出宿主拖拽域(app-region保持 blanket 的no-drag),
与 v0.22.1 那条修复的分工一致。 - 实机验证(dev 应用 + 真实后台作业
sleep 6000):打开浮窗(562×342,
底rgb(44,44,46)=bg-layer-2、描边border-l2、标题label-primary全部
解析正确)→ 拖拽 (-300,-200) 精确位移 → 右下角拉伸 562×342→782×482
(+220/+140 精确)→ 外部点击不关 → Escape 关闭 → 重开几何记忆一致
(1716,536,782,482);无页面报错。
轨迹图图例在窄侧栏不再竖排
- 故障:图例是一行可收缩且不换行的 flex,侧栏一窄,每个 chip 被压到小于内容
宽度,标签便逐字换行("输 入"竖排)。 - 修法:chip 自身
flex: none+white-space: nowrap(永不被压扁),整行改为
按 chip 换行(flex-wrap: wrap+ 行列间距),搜索框改为可收缩但有下限
(flex: 0 1 96px; min-width: 72px)。 - 实测:默认 479px 图例 2 行、单个 chip 高 16–18px;把面板压到 210px 后变为
4 行、chip 仍为 16–18px(单行),被压扁(scrollWidth > clientWidth)的 chip
数 = 0,不再出现竖排文字。
自动整理:树形 / 紧凑 / 网格三种排布
- 控制条新增
树形 | 紧凑 | 网格三枚芯片(data-wf-mode,aria-pressed标出
当前模式):点任意一枚 = 清掉手动偏移 + 按该模式重排 + 重新适配,一步把
"子代理太多看不清"拉回一张整齐的图;模式按树根缓存,切模式/重开标签不丢。 - 纯布局新增
TaskLayoutMode:tree(层级,父居中,间距 36/64)、compact
(同层级、间距 14/38)、grid(按深度分行并按列网格折行,每行至多 6 列
——宽扇出从一条无尽长条变成可读的块)。三种模式共用同一套连线与包围盒计算,
手动偏移在任一模式下都仍然生效。 - 实测(同一棵树,面板 467×819):内容盒 tree 1184×196 / compact 1096×170 /
grid 1080×158,适配后缩放 0.279 → 0.303 → 0.432,即网格模式下卡片实际
大 55%;点击任意模式都会把手动偏移清零(offsets 6 → 0);切换后仍可拖动、
可重置、可再整理;无页面报错。单测覆盖:紧凑行距更小、网格横向更窄且把宽行折成
多行、网格无重叠卡片、连线数量不变、偏移在网格模式同样生效。
节点级拖动(任务管理图:手动摆放卡片)
- 交互:直接拖动画布上的卡片即可移动。默认连同其子树一起走(拖动主代理
就是整棵树平移),按住 Alt/Option 只移动该卡片;Alt的语义写进代码注释,
手柄光标为grab/拖动态grabbing。 - 实现:手动位置以「相对自动布局的偏移」保存(
NodeOffsets),自动布局仍是
底座——layoutTasksViewModel(model, offsets)在放置之后应用偏移,连线与内容
包围盒都按拖动后的真实位置重算;偏移按树根缓存(与相机同族、切模式/重开标签
不丢),并提供 「⟲ 重置布局」 回到自动布局(无手动布局时不显示该按钮)。 - 不误触:拖动位移超过阈值后,松手不会触发导航;轻点(未移动)仍照常进入该
子会话。画布平移、缩放、适配都不受影响;「适配」会把拖到负坐标的内容一并框进来
(minX/minY参与计算)。 - 实测:叶子子代理拖动 → 偏移 1 条(只动自己);拖主代理 → 偏移 6 条(整棵
子树);Alt + 拖主代理 → 1 条;拖动后连线同步变化;点「重置布局」逐字节回到
自动位置且按钮消失;轻点仍能进入子会话;无页面报错。纯函数单测覆盖偏移应用、
子树/单节点语义、增量基于手势起点、包围盒越界扩张与重置。
工作流图相机策略修复(手动拖动总被踩回默认区域)
- 故障:
fit()原先在每次模型/布局变化时无条件执行——执行期的活动
轮询(live 2s、workflow runs 5s、会话 feed)不断重建视图模型与布局,于是
手动拖动的位置每两秒被重新适配踩回默认区域,部分节点长期在视口外;fit()
还会清掉"用户已手动调整"标记,让自动适配永远赢。 - 修法:新树(root id 变化)才自动适配并清除手动标记;同一棵树
只在视图仍处自动态时适配(!userAdjustedRef),用户一旦拖动/缩放就不再
抢占;ResizeObserver 与拖拽中同样不抢;「适配」按钮保持显式复位语义。 - 实测:拖动
-220,-120后触发刷新 + 跨两轮轮询(覆盖 live 与 workflow
两个轮询窗),transform 逐字节不变;「适配」可复位。 - 相机跨模式/跨重挂粘滞:图/树切换会重挂画布组件,原先相机随之丢失。
现按树根缓存相机(含"用户已接管"标记,容量 12、最旧淘汰):切回图或
离开会话再回来重开任务管理,都恢复到你上次的取景;未见过的树仍走自动适配。
实测:拖动后translate(-51.5,217)→ 树→图 保持 → 切走工作区/会话再切回并
重开任务管理仍为translate(8.5,257)(与拖动值逐字节一致,而全新适配为
translate(208.5,347))。
macOS 桌面拖拽域修复(上游 v0.22.1 / issue #772)
- 故障:宿主规则
html[data-platform=darwin] body > :not(#root) { -webkit-app-region: no-drag }命中本插件直挂 body 的面板宿主;而
app-region 无视 pointer-events,视口尺寸的宿主层把整条标题栏拖拽带
抵消——桌面壳上「窗口拖一次就失效、双击标题栏缩放失效」。 - 修法(照上游):面板宿主与放大视图(mermaid modal,同样 portal 到
body 的铺满层)用中性值-webkit-app-region: initial !important退出
blanket;宿主的子层保持no-drag(我们的按钮在标题栏条上按下不会
变成拖窗,延续 #103/#111 的既有约束);交互弹层(划选弹层/浮动窗/锚定
气泡)不加initial,否则按下会变拖窗。 - 实测(计算样式 + CSSOM):宿主
none/ 子层no-drag;模拟
data-platform=darwin后普通 body 子元素仍为no-drag(blanket 未被
破坏),证明只退出了我们这两层。产物级断言已加入smoke(中性规则
≥2 处 + 子层 no-drag 在位)。
工作流 run 入图(上游 v0.22.0 对应项)
- 宿主折叠:新增
src/subagent-workflow.ts(纯函数)从tool-workflow/*
事件家族折叠 run:run-start{runId,name}/agent-start{seq,label,phase?,childId}
/agent-end{seq,outcome}/run-end{stopReason}。相位按组内最小 seq
排序(工作流定义序),无相位成员排尾;agent-end的 outcome 按 seq 归位。 - 路由:
subagents.workflow(src/subagent-workflow-route.ts)折整个会话
树;宿主无 subagent 服务时仍折叠根会话(主代理发起的 run 可见),单个会话
日志不可读只跳过该会话。 - 入图:
buildTasksViewModel新增run/phase/member三种节点——
run 挂在发起代理下,相位成框,成员带真实 childId 时把目录子会话重挂到
相位下(保留其子树),目录里没有的成员用 run 数据合成(可点击导航)。
树与图共用同一模型,两种模式都渲染。
合并活动行(上游 v0.22.0 卡片底条)
mergedActivity()(src/subagent-activity.ts):把窗口内的tool/call按
名称归并计数(首次出现序),并找出最新无tool/result的调用作为
「在跑那条」;窗口语义与lastActivity对齐(尾部 N 条 surface message)。subagents.live每条活动带上merged;树行在图/树两种模式下都多一行
「Bash ×2 · fs_read ×1 · 运行中 fs_write」,图节点底条运行中追加归并摘要。
工作流图交互修复(实机发现的三个缺陷)
- 画布只显示一小块:图模式仍复用
overflow-y:auto的滚动容器,其中
flex:1无效 → 画布塌缩成内容高度。现图模式切换为弹性列
(.subagentBodyGraph,不滚动),画布撑满面板(实测 1019px / 面板 1029px)。 - 节点点不动、+/−/适配没反应(同一根因):容器上调用
setPointerCapture会把随后的click重定向到容器,节点<g>与控制条
按钮的 onClick 都不触发。现改为拖拽期间挂window指针监听,不再捕获;
控制条另行stopPropagation与拖拽解耦。实测:缩放/平移/适配/节点导航
全部生效(点子代理 → 面包屑切到该子会话)。 - 尺寸变化不重排:新增
ResizeObserver自动适配(用户手动平移/缩放后
不再抢视图,点「适配」可复位自动模式)。
浅色主题可读性修复(实机发现的 token 错误)
- 工作流图首版用了宿主不存在的 token(
--dsw-alias-bg-primary/
bg-secondary/border-strong/border-subtle/state-running-primary):
var()解析失败时 SVGfill回退为默认黑色,浅色主题下变成黑底黑字、
完全不可读。 - 现改用宿主
body/body[data-ds-dark-theme]上实际定义且本仓库既有
规则验证过的 token:卡片改「透明底 +border-l2描边」,分段用分隔线,
底条用interactive-bg-hover,运行点/当前描边用interactive-bg-hover-accent,
文字用label-primary/secondary/tertiary。 - 双主题实测(计算样式取值):深色 卡底透明 / 描边
rgba(255,255,255,.24)/
文字rgb(249,250,251);浅色 卡底透明 / 描边rgba(38,49,72,.14)/
文字rgb(15,17,21)——两主题均清晰可读。
团队 tab 状态机补全(实机发现的 UX 缺口)
- 非团队会话(从未用团队工具)的投影读取会正常完成但不发布
agentTeam
值——旧逻辑会停在「正在读取团队状态…」永转圈。现派生为终态
not-team→ 空态「当前会话不是团队会话」,不再无限等待。 projection-missing(宿主 <0.1.7)判定收窄:仅当快照完全没有投影 store
时呈现;idle/loading一律视为读取中。
兼容性说明
- 沿用 1.0.35 的 peer 口径:
>=0.1.7-rc.2 <1.0.0(0.1.7-rc.2+ 与 0.2.0-rc.x
均可安装);0.1.6 系宿主请使用 1.0.30。 - 经典缩进树保留为默认可切换视图;键盘导航行为不变。
验证
- typecheck 0;
testsALL PASS(run-openpath-tests全量,新增
subagent-tasks-model/subagent-tasks-layout/team-projection三个夹具
与 30+ 断言);check:artifacts字节可复现;smoke通过。 - 待 dev 实机验证:工作流图交互(平移/缩放/适配/点击导航/聚合展开)、
36 子代理会话的折叠观感、TeamView 在 0.1.7 宿主的成员/看板渲染。