ソースを参照

tighten branchless subagent catalog layout

kingwl 2 ヶ月 前
親
コミット
d5583210d4

+ 2 - 0
apps/web/tests/snapshots/subagent-conversation/branchless.expected.md

@@ -0,0 +1,2 @@
+- tree "Subagent sessions":
+  - treeitem "example editor continuable · not running 0 tok · {{duration}}" [level=1]: example editor continuable · not running 0 tok {{duration}}

+ 10 - 1
apps/web/tests/subagent-conversation.e2e.ts

@@ -20,6 +20,7 @@ import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './suppor
 const BASE_FIXTURE = fileURLToPath(new URL('./snapshots/live-interactions/session.jsonl', import.meta.url))
 const AVAILABLE_CHILD_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/ui.expected.md', import.meta.url))
 const TREE_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/tree.expected.md', import.meta.url))
+const BRANCHLESS_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/branchless.expected.md', import.meta.url))
 const STALE_CATALOG_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/stale-catalog.expected.md', import.meta.url))
 const SIDEBAR_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/sidebar.expected.md', import.meta.url))
 const UNAVAILABLE_GRANDCHILD_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/nested.expected.md', import.meta.url))
@@ -396,7 +397,15 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
   it('opens an unavailable persisted grandchild after recording the available child', async () => {
     onTestFailed(() => saveFailureShot(page, 'web-e2e-subagent-grandchild'))
     await page.getByRole('button', { name: '1 subagent' }).click()
-    await page.getByRole('treeitem', { name: new RegExp(NESTED_LABEL) }).click()
+    const tree = page.getByRole('tree', { name: 'Subagent sessions' })
+    const nestedRow = tree.getByRole('treeitem', { name: new RegExp(NESTED_LABEL) })
+    expect(await nestedRow.locator(':scope > *').count()).toBe(1)
+    await compareOrRefreshGolden(
+      BRANCHLESS_EXPECTED,
+      await captureStableAria(page, '[role="tree"][aria-label="Subagent sessions"]', scaffold.workspaceCwd),
+      MODE,
+    )
+    await nestedRow.click()
     await page.getByText('The parent session is offline; reopen it to continue sending messages.').waitFor()
     const hierarchy = page.getByRole('navigation', { name: 'Session hierarchy' })
     const crumbs = await hierarchy.getByRole('button').allTextContents()

+ 2 - 2
packages/client/ui-subagent/README.i18n.yaml

@@ -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-subagent/README.md
-README.md: 1ced0a82e5ec9340ee87620dfaaf7655fe4f6a3e
-README.zh.md: 778d3354ac78658044c2a13b3af632510b547f04
+README.md: cb210b219a8c66985eb4e1370468372eed9614b4
+README.zh.md: 7b87fa1095c404eda96066189b1e4480cd6d4c3c

ファイルの差分が大きいため隠しています
+ 0 - 0
packages/client/ui-subagent/README.md


ファイルの差分が大きいため隠しています
+ 0 - 0
packages/client/ui-subagent/README.zh.md


+ 5 - 2
packages/client/ui-subagent/src/client/SubagentCatalogAction.tsx

@@ -237,6 +237,9 @@ function CatalogRows({
   openChild, refresh, toggleBranch, closeCatalog, t,
 }: CatalogRowsProps & { t: TranslateNS<typeof NS> }) {
   const emptyLoading = catalog.state === 'loading' && catalog.entries.length === 0
+  const reserveDisclosure = catalog.entries.some(
+    entry => entry.kind === 'child' && entry.hasChildren,
+  )
   return (
     <>
       {emptyLoading && (
@@ -273,7 +276,7 @@ function CatalogRows({
                 className={`${css.row} ${css.disabled}`}
                 title={reason}
               >
-                <span className={css.disclosureSpace} />
+                {reserveDisclosure && <span className={css.disclosureSpace} />}
                 <StateDot state="error" />
                 <span className={css.content}>
                   <span className={css.label}>{entry.id}</span>
@@ -352,7 +355,7 @@ function CatalogRows({
               onKeyDown={handleKey}
             >
               {knownLeaf
-                ? <span className={css.disclosureSpace} />
+                ? reserveDisclosure && <span className={css.disclosureSpace} />
                 : (
                   <button
                     type="button"

+ 14 - 0
packages/client/ui-subagent/tests/conversation-ui.spec.tsx

@@ -151,6 +151,7 @@ describe('SubagentCatalogAction', () => {
     expect(diagnostic.getAttribute('aria-disabled')).toBe('true')
     expect(screen.getByRole('button', { name: '展开 worker 的下级子代理' })).toBeTruthy()
     expect(screen.queryByRole('button', { name: '展开 reviewer 的下级子代理' })).toBeNull()
+    expect(screen.getByRole('treeitem', { name: /reviewer/ }).children).toHaveLength(2)
 
     fireEvent.click(screen.getByRole('treeitem', { name: /worker/ }))
     expect(input.openChild).toHaveBeenCalledWith({
@@ -177,6 +178,19 @@ describe('SubagentCatalogAction', () => {
     expect(translate).toHaveBeenCalledWith('count.total.one', { count: 1 })
   })
 
+  it('removes the disclosure column from branchless catalog levels', () => {
+    const input = props(catalog({
+      entries: [{
+        kind: 'child', id: CHILD, mode: 'continuable', label: 'worker',
+        activity: 'running', hasChildren: false,
+      }],
+    }))
+    render(<SubagentCatalogAction {...input} />)
+    fireEvent.click(screen.getByRole('button', { name: /1 个子代理/ }))
+
+    expect(screen.getByRole('treeitem', { name: /worker/ }).children).toHaveLength(1)
+  })
+
   it('supports trigger/menu keyboard traversal, Escape focus restore, and outside close', async () => {
     const input = props(catalog())
     render(<SubagentCatalogAction {...input} />)

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません