refactor(tasks): 移植主 Agent 同款合并活动折叠(数据层)
把上一轮验证过的数据层搬到工作图基座上,图/树两种模式共用:
- 新增 src/process-activity.ts:宿主 ui-chat 的 process group 算法移植
(activity() 分类表逐条照抄、liveToolDetail 键优先级与 160 字截断、
counts 计数排序与并列规则、preparing 语义、按 user/reply 边界切范围)。
按本轮设计裁剪掉逐阶段列表(阶段改由徽标 + 颜色表达)。新增一条
偏差:最新范围为空(子代理刚回复完)时回退到上一个「做过事」的范围,
否则已结算卡片的小条只会显示「已完成分析」。
- chatT:从宿主 chat 命名空间读 message.stepProcess.* 措辞(方法调用 +
try/catch 兜底,key 未命中即回退),4 个回归用例钉住「不许解绑 bind」。
- subagents.live 载荷换新:SidebarChildLiveView { running?, text?, summary?,
lastEventTime? },报告树内每个子节点(含已结算)与拓扑根;删除
expand/stages 机制;childActivity → childLive(「不在 map 里 = 未运行」
的读法随旧协议一起作废)。
- tasks-model 消费新形状;LiveLine 与节点详情浮窗改显示合并活动措辞。
- 删除 src/subagent-activity.ts 与 tests/subagent-activity.spec.ts。
验证:typecheck / lint 通过;pnpm test 1252 passed / 9 skipped。
(cherry picked from commit 5e5284f214846b0c366048acbee459f3a7a79456)
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
* the width-aware solver.
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { SidebarChildLiveView } from '../src/context-types.ts'
|
||||
import {
|
||||
GRAPH_GAP_Y,
|
||||
GRAPH_LIVE_H,
|
||||
@@ -50,6 +51,12 @@ function layoutRow(layout: ReturnType<typeof layoutTasksGraph>, id: string): num
|
||||
return (box.y - GRAPH_PAD) / GRAPH_ROW_STRIDE
|
||||
}
|
||||
|
||||
/** One running node's live view: a merged activity row, no text tail. */
|
||||
const ACTIVITY: SidebarChildLiveView = {
|
||||
running: true,
|
||||
summary: { counts: [{ kind: 'read', count: 1 }], running: 'read', runningDetail: 'x' },
|
||||
}
|
||||
|
||||
describe('layoutTasksGraph', () => {
|
||||
it('places the root on row 0 and children one row below', () => {
|
||||
const nodes: TasksNode[] = [agent('root'), agent('a', 'root'), agent('b', 'root')]
|
||||
@@ -98,11 +105,11 @@ describe('layoutTasksGraph', () => {
|
||||
expect(plain.boxes.get('mate')?.h).toBe(GRAPH_NODE_H)
|
||||
})
|
||||
|
||||
it('reserves the live tail row only when the tail carries a tool AND text', () => {
|
||||
it('reserves the live tail row only when the tail carries activity AND text', () => {
|
||||
const nodes: TasksNode[] = [
|
||||
agent('root'),
|
||||
agent('tool-only', 'root', false, { live: { tool: { name: 'read', args: 'x' } } }),
|
||||
agent('both', 'root', false, { live: { tool: { name: 'read', args: 'x' }, text: 'y' } }),
|
||||
agent('tool-only', 'root', false, { live: ACTIVITY }),
|
||||
agent('both', 'root', false, { live: { ...ACTIVITY, text: 'y' } }),
|
||||
]
|
||||
const layout = layoutTasksGraph(nodes)
|
||||
// One live row either way (the tool row, or the meta-styled thinking
|
||||
@@ -118,9 +125,7 @@ describe('layoutTasksGraph', () => {
|
||||
expect(GRAPH_ROW_STRIDE).toBeGreaterThanOrEqual(tallest)
|
||||
const nodes: TasksNode[] = [
|
||||
agent('root'),
|
||||
agent('busiest', 'root', false, {
|
||||
live: { tool: { name: 'read', args: 'x' }, text: 'y' }, tasks: [task('t1')],
|
||||
}),
|
||||
agent('busiest', 'root', false, { live: { ...ACTIVITY, text: 'y' }, tasks: [task('t1')] }),
|
||||
]
|
||||
const layout = layoutTasksGraph(nodes)
|
||||
expect(layout.boxes.get('busiest')?.h).toBe(tallest)
|
||||
|
||||
Reference in New Issue
Block a user