尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DeepSeek Harness 侧边栏会话完成提醒:基于 SessionManager 的 running→idle 边沿检测与「绿点」状态投影

DeepSeek Harness 侧边栏会话完成提醒:基于 SessionManager 的 running→idle 边沿检测与「绿点」状态投影 人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载导读本文围绕 DeepSeek Harness 已落地的一项会话列表交互特性——「侧边栏会话完成提醒点done dot」展开。该特性解决的是多会话并行场景下的核心体验问题操作者派发任务后切到其他会话原会话悄悄跑完时没有任何信号。读完本文你将掌握该提醒的完整设计决策SessionManager 持有的内存集合 running→idle 边沿检测、数据投影链路SessionManager → SessionListEntry → SessionSummary → 工作区浏览区 → StateDot、三色互斥状态机绿/琥珀/蓝的语义以及为什么「仅在快照构建时检测」会漏掉完成事件并通过源码与测试用例验证每个环节的实现细节。一、问题背景多会话并行下「跑完了却没人知道」在使用 DeepSeek Harness 的工作区浏览界面时操作者通常会同时派发多个会话任务一个会话在跑长任务人切去另一个会话继续工作。此时原会话的运行指示running 指示停止后这一行与普通空闲会话看起来完全一样——没有绿色、没有信号操作者只能反复刷新列表或者很久之后才发现工作其实早已完成。这里的关键空白在于已有的「等待交互琥珀点」pendingInteraction覆盖 approval / plan-review / question 三种等待输入的状态只覆盖需要操作者输入的会话却不覆盖「只是干完了活」的会话。换句话说系统此前有能力告诉你「会话在等你」却没有能力告诉你「会话在等你回来看结果」。二、决策由SessionManager持有完成提醒集合为解决上述问题实现方案将完成提醒位设计为SessionManager持有的内存集合与既有的待交互位pendingInteraction并列而不是下放到组件本地状态。2.1 核心数据结构在 manager.ts 中可以看到该特性的两个关键成员/** * Sessions that finished running while not selected — the sidebars green * done reminder (manager-owned, survives connection generations; cleared * on select and session-removed, re-armed by the next completion). */ private readonly completedNotifications new SetSessionId() /** Last-observed running bits per session; the true→false edge here arms {link completedNotifications}. */ private readonly prevRunning new MapSessionId, boolean()completedNotifications完成提醒集合记录「跑完了但还没被查看」的会话 IDprevRunning上一观察到的运行位用于检测每个会话running: true → false的边沿edge只有边沿才能点亮提醒状态不变则不动。2.2 生命周期规则文档定义的完整语义事件行为非当前会话发生 running→idle 边沿点亮该会话的完成提醒select()/selectSubagent()选中该会话消费掉提醒熄灭重新开始一轮运行熄灭提醒再次完成时重新点亮会话被移除removed / drop清理提醒重新添加后从干净状态开始在源码中select()选中会话时明确注释「Looking at the session consumes its completion reminder (dot clears)」并执行this.completedNotifications.delete(sessionId)见 manager.ts而handleSessionRemoved会在同步时把已消失会话的提醒一并清理见 manager.ts。2.3 为什么放在 manager 而不是组件本地文档在「Alternatives considered」中记录了两条被拒绝的方案及其理由组件本地 UI 状态被拒绝侧边栏折叠时组件会被卸载且分组树、扁平列表、搜索结果多个界面需要共享同一个状态位。SessionManager本就持有运行状态迁移与选中状态由 manager 持有的集合是所有界面都能投影的唯一真源single source of truth。仅从状态帧做事件驱动点亮被拒绝列表拉取本身也可能携带 running→idle 迁移例如刷新时在途会话刚好跑完提醒必须对每次变更与每次拉取做对账而不是只依赖单次状态帧。三、核心算法每次变更与拉取时的边沿对账3.1 边沿检测的时机关键设计点是完成边沿在每次列表变更与拉取时即时检测而不是只在构建快照时检测。文档给出的理由非常具体——若只在建快照时检测会把「running → idle」这两个连续状态帧折叠为一次观察从而漏掉完成事件。syncCompletedNotifications()是这一对账逻辑的核心见 manager.tsprivate syncCompletedNotifications(): void { const seen new SetSessionId() for (const s of this.summaries) { seen.add(s.sessionId) const prev this.prevRunning.get(s.sessionId) if (prev undefined) { this.prevRunning.set(s.sessionId, s.running) continue } if (prev !s.running) { if (s.sessionId ! this.selected) this.completedNotifications.add(s.sessionId) } else if (s.running) { this.completedNotifications.delete(s.sessionId) } this.prevRunning.set(s.sessionId, s.running) } // 清理已消失会话的 prevRunning 与 completedNotifications 记录 for (const id of this.prevRunning.keys()) { if (!seen.has(id)) this.prevRunning.delete(id) } for (const id of this.completedNotifications) { if (!seen.has(id)) this.completedNotifications.delete(id) } }这段逻辑对应三条规则首次见到某会话只记录其 running 位不点亮无法构成边沿prevtrue → 当前 false 且非选中点亮提醒若会话正在运行则熄灭提醒运行状态优先对账清理从列表消失的会话其prevRunning与completedNotifications记录一并删除。3.2 两个调用路径变更与拉取都要对账syncCompletedNotifications()被调用的位置精确覆盖了文档要求的「每次列表变更与拉取」实时变更路径recordMutation()在应用每条列表变更upsert/remove后立即调用syncCompletedNotifications()见 manager.ts并注释「Eager edge reconciliation — a snapshot-build-time pass would miss consecutive status frames.」拉取路径refreshList()拉取基线后在每条重放的 in-flight 变更之后都调用一次对账最后对空变更的纯基线再补一次对账见 manager.ts。源码注释明确说明若只对折叠后的结果做一次 sync发生在「基线 idle → running → idle」之间的边沿就会被折叠掉而无法点亮。四、数据投影链路从 manager 到绿点渲染完成提醒位从 manager 一路投影到工作区浏览区路径完全符合文档描述的「SessionListEntry→SessionSummary可选字段缺省 无提醒→ 工作区浏览区 →StateDotdone 状态」。4.1 步骤一flattenLineage注入 completed 位lineage.ts 中定义SessionListEntry其completed字段注释为「Finished running while not selected and not yet opened — the sidebars green done reminder (clears on select or the next run)」。flattenLineage是纯函数投影见 lineage.ts把 lineage 树拍平成带缩进深度的扁平行其中out.push({ ...s, completed: completed?.has(s.sessionId) ?? false, depth, })即completed由 manager 的completedNotifications集合推导Set中存在的会话为 true缺省为 false。4.2 步骤二SessionSummary.completed为可选字段service.ts 中定义export interface SessionSummary { id: SessionId title?: string displayTitle: string cwd?: string parentId?: SessionId origin?: subagent running: boolean /** Finished while not selected and not yet opened — the sidebars green done reminder. Absent false. */ completed?: boolean blank: boolean updatedAt: number projectionValues?: ReadonlyPartialSessionProjectionMap }注意completed是可选字段缺省即「无提醒」。这意味着协议格式wire format、磁盘格式、配置格式均无变更现有消费方与测试 fixture 保持有效只有工作区浏览区读取该字段——这正是文档「Consequences」一节强调的兼容性保证。4.3 步骤三工作区浏览区投影到行节点在 tree.ts 中SessionNode与SearchResultNode都携带completed: boolean注释为「Finished running while not selected and not yet opened (the green done reminder dot)」投影逻辑为completed: s.completed true见 tree.ts。4.4 步骤四StateDot渲染「已完成」StateDot是客户端原语组件支持四种状态语义见 StateDot.tsx/** Four-color state semantic (green done / amber user-attention / blue running ring / red error). */ export type StateDotState done | warning | ongoing | error在 Rows.tsx 的sessionStatuses()中状态优先级为待交互warning 运行中ongoing 完成提醒done 空闲done 但无绿点语义if (node.completed) return [{ state: done, label: t(status.completed) }] return [{ state: done, label: t(status.idle) }]文档强调的渲染细节在此得到印证运行中仍显示转圈ongoing无提醒的空闲会话不显示任何点。搜索结果行同样复用该渲染逻辑且仅在primaryStatus.state ! done || result.completed时才渲染状态点见 Rows.tsx——即空闲行无点、有完成提醒的行才显示绿点。悬停卡片SessionHoverContent会把该状态标注为「已完成 / Completed」两个语言标签定义在 locales.ts 与 locales.ts。五、三色互斥状态机绿、琥珀、蓝侧边栏会话行的状态由此成为三个互斥信号颜色语义对应 StateDot 状态绿done已完成且未查看done琥珀warning等待操作者输入approval / plan-review / questionwarning蓝ongoing运行中含子代理运行中ongoing转圈动画待交互状态优先级最高、实时活动状态次之、完成提醒再次之见sessionStatuses()的顺序从而保证「需要你输入」永远盖过「只是跑完了」不会让用户错过关键的人工介入点。六、提醒的生命周期特性内存态、跨连接代、刷新即重置文档明确界定了该提醒的存储边界这也是一个容易被忽视但非常重要的设计约束仅存在于内存中不是持久化状态按浏览器实例隔离不同浏览器实例互不可见跨连接代存活连接传输抖动重连不会使「你还没回来看」失效——completedNotifications由SessionManager持有manager 的生命周期跨越连接代页面刷新后重置刷新会恢复选中状态且用户正看着列表持久化位只会变得陈旧。对应的「持久化提醒」方案在文档的 Alternatives 中被拒绝理由正是提醒的含义是「此浏览器里你还没查看该会话」刷新场景下用户已经面对列表本身持久化位没有任何增量价值反而可能变成过时信息。七、测试验证行为语义的完整覆盖该特性的行为语义在 manager.client.spec.ts 的completed reminder测试套件中被逐一验证测试用例验证语义arms on a running→idle flip of a non-selected session and clears on select非选中会话 running→idle 点亮提醒select()打开会话后熄灭never arms for the session being watched and re-arms after a switch-away re-run正在查看的会话跑完不点亮切走后再次运行完成才点亮a re-run disarms the reminder while running and re-arms on its completion不打开会话直接重新运行运行中熄灭、完成后再点亮session-removed drops the reminder and a re-add starts clean会话移除清理提醒重新添加从干净状态开始a list refresh carrying the running→idle transition arms the reminder列表拉取本身携带 running→idle 迁移时同样点亮验证拉取路径对账此外lineage.client.spec.ts 验证了flattenLineage对completed集合的投影集合中的会话completed true缺省为 false。八、设计要点小结与扩展阅读回看整条链路该特性是一个典型的「小 UI、大架构」设计值得借鉴的点在于状态归属跨界面共享的临时状态归 manager 所有组件只负责投影避免折叠/卸载丢失状态边沿而非电平以 running→idle 边沿为触发信号并对每次变更与拉取做对账防止状态帧折叠导致漏检向后兼容通过可选字段SessionSummary.completed?扩展协议wire format / 磁盘格式 / 配置格式零变更旧 fixture 与消费方全部保持有效明确的存储边界内存态 浏览器实例隔离 跨连接代存活 刷新重置语义清晰无歧义。如需深入源码可重点阅读边沿检测与提醒集合manager.ts协议字段定义service.ts列表投影纯函数lineage.ts行状态与绿点渲染Rows.tsx状态点原语组件StateDot.tsx行为测试manager.client.spec.ts赞分享人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载相关推荐DeepSeek Harness 会话完成状态点侧边栏「已完成」绿点提醒的设计与实现DeepSeek Harness 会话完成状态点侧边栏「已完成」绿点提醒的设计与实现 导读 DeepSeek Harness 支持操作者把任务委派给会话se人工智能AI AgentAgent 框架DeepSeekgstack × Conductor 侧边栏集成设计让 Chrome 侧边栏成为 Agent 会话的实时视窗gstack × Conductor 侧边栏集成设计让 Chrome 侧边栏成为 Agent 会话的实时视窗 本文基于 gstack 仓库中的设计文档 CON人工智能AI 技能浏览器控制AI 评测如何用 Browser-Use 自定义格式提取网页数据完整指南如何用 Browser Use 自定义格式提取网页数据完整指南 把10个商品页的价格逐个粘进Excel太磨人了。Browser Use 让 AI 像人一样打人工智能AI Agent浏览器控制GUI 自动化MCP 服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表