Skip to content

dsh-coding-sidebar 1.0.36

Choose a tag to compare

@kkutysllb kkutysllb released this 01 Oct 08:53
· 5 commits to main since this release

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 的 agentTeam Session 投影
    (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.zip 745KB(testzip 无错、目录递归、命名正确)、含目录
    超 48MB 时给出明确拒绝提示、打开方式子菜单同时列出内建编辑器与本机应用
    (124 项,apps.list 200)、扩展目录时观察到 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() 解析失败时 SVG fill 回退为默认黑色,浅色主题下变成黑底黑字、
    完全不可读。
  • 现改用宿主 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;tests ALL PASS(run-openpath-tests 全量,新增
    subagent-tasks-model / subagent-tasks-layout / team-projection 三个夹具
    与 30+ 断言);check:artifacts 字节可复现;smoke 通过。
  • 待 dev 实机验证:工作流图交互(平移/缩放/适配/点击导航/聚合展开)、
    36 子代理会话的折叠观感、TeamView 在 0.1.7 宿主的成员/看板渲染。