fix(web): deduplicate subagent navigation
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/client/ui-workspace/README.md
|
||||
README.md: 2854c678fd93d56267d0aec8515455b77d4bcbf1
|
||||
README.zh.md: 51db6cacfe83d176a6cc68b01fe3dd91acf49e25
|
||||
README.md: 2670bdfa2fb1a223bf0c0ea65fbacc1cfb30c607
|
||||
README.zh.md: 1e68cfb1a94c240c32949059ca6a3c6adc25208b
|
||||
|
||||
@@ -14,6 +14,8 @@ The Session row's Fork action forks at the source's last completed turn, increme
|
||||
|
||||
Both target slots are declared by other plugins, so `apply` registers through declaration-aware deferral and re-registers after a declaring slot is restored.
|
||||
|
||||
The shared sidebar projection hides rows whose durable Session summary has `origin: 'subagent'`; users enter those conversations through the selected parent's subagent header catalog. Ordinary forks remain visible because lineage alone does not set that origin. The runtime keeps hidden rows available for conversation, title, and addressed transport state.
|
||||
|
||||
## Model Experience
|
||||
|
||||
None, as the picker is browser chrome; nothing here reaches a model request.
|
||||
|
||||
@@ -14,6 +14,8 @@ Session 行内的 Fork 操作在源会话最后一个已完成轮次处 fork,
|
||||
|
||||
两个目标 slot 都由其他插件声明,因此 `apply` 通过声明感知的延迟机制完成注册,并在声明该 slot 的插件恢复后重新注册。
|
||||
|
||||
共享侧边栏投影会隐藏持久化 Session 摘要中带有 `origin: 'subagent'` 的行;用户从所选 parent 的 subagent 页头目录进入这些对话。普通 fork 仍然可见,因为仅有谱系不会设置该 origin。运行时仍保留隐藏行,供对话、标题与已寻址传输状态使用。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。选择器属于浏览器 chrome;这里没有任何内容进入模型请求。
|
||||
|
||||
@@ -92,11 +92,14 @@ function byRecency(a: SessionSummary, b: SessionSummary): number {
|
||||
|
||||
/**
|
||||
* Ordinary sessions are visible; among blank sessions, only the current one
|
||||
* is visible; archived sessions are visible nowhere (their accounting slots
|
||||
* remain, so unarchiving restores position).
|
||||
* is visible. Subagent children use their parent header catalog; archived
|
||||
* sessions are visible nowhere, while their accounting slots remain so
|
||||
* unarchiving restores position.
|
||||
*/
|
||||
function sessionVisible(session: SessionSummary, current: SessionId | undefined, archived: ReadonlySet<SessionId>): boolean {
|
||||
return !archived.has(session.id) && (!session.blank || session.id === current)
|
||||
return session.origin !== 'subagent'
|
||||
&& !archived.has(session.id)
|
||||
&& (!session.blank || session.id === current)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -69,6 +69,22 @@ describe('deriveGroups', () => {
|
||||
expect(strayGroups.map(group => group.key)).toEqual(['first'])
|
||||
})
|
||||
|
||||
it('hides subagent-origin sessions without hiding ordinary forks', () => {
|
||||
const parent = summary('parent', 1)
|
||||
const fork = { ...summary('fork', 2), parentId: parent.id }
|
||||
const subagent = { ...summary('subagent', 3), parentId: parent.id, origin: 'subagent' as const }
|
||||
const sessions = { ...list(parent, fork, subagent), current: subagent.id }
|
||||
const groups = deriveGroups(
|
||||
sessions,
|
||||
[workspace('first', ['parent', 'fork', 'subagent'])],
|
||||
noArchive,
|
||||
view(['first']),
|
||||
)
|
||||
|
||||
expect(groups[0]!.sessions.map(node => node.id)).toEqual([parent.id, fork.id])
|
||||
expect(groups[0]!.sessionCount).toBe(2)
|
||||
})
|
||||
|
||||
it('ignores fork lineage and sorts every ungrouped session as a top-level row', () => {
|
||||
const parent = summary('parent', 1)
|
||||
const oldChild = { ...summary('old-child', 10), parentId: parent.id }
|
||||
@@ -143,6 +159,17 @@ describe('deriveFlat', () => {
|
||||
expect(rows.map(row => row.id)).toEqual([sid('child'), sid('tie-a'), sid('tie-b'), sid('parent')])
|
||||
})
|
||||
|
||||
it('hides subagent-origin rows but keeps ordinary forks', () => {
|
||||
const parent = summary('parent', 1)
|
||||
const fork = { ...summary('fork', 2), parentId: parent.id }
|
||||
const subagent = { ...summary('subagent', 3), parentId: parent.id, origin: 'subagent' as const }
|
||||
const rows = deriveFlat(
|
||||
{ ...list(parent, fork, subagent), current: subagent.id },
|
||||
noArchive,
|
||||
)
|
||||
expect(rows.map(row => row.id)).toEqual([fork.id, parent.id])
|
||||
})
|
||||
|
||||
it('tolerates ids whose summary has not landed yet', () => {
|
||||
const partial: SessionListState = { ...list(summary('present', 1)), ids: [sid('ghost'), sid('present')] }
|
||||
expect(deriveFlat(partial, noArchive).map(row => row.id)).toEqual([sid('present')])
|
||||
|
||||
Reference in New Issue
Block a user