فهرست منبع

fix(web): hide built-in profile bundles from plugin cards

Yichen Jiang 1 ماه پیش
والد
کامیت
05e675863b

+ 2 - 2
packages/client/ui-plugin-manager/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-plugin-manager/README.md
-README.md: 2cfeaad06d2b0247057f5824213411019a8a3cef
-README.zh.md: e61a79b1b58d66fbec543966d12b7a8c15e402c9
+README.md: e7128dd2146cc0553ab36fdef5c31470be7877f2
+README.zh.md: ff7706f1d9747f553bf91f45a76fa5f50472330d

+ 1 - 1
packages/client/ui-plugin-manager/README.md

@@ -37,7 +37,7 @@ During installation, **Cancel install** asks the Host to stop the run and shows
 
 ### Switching a bundle
 
-A bundle's page shows its full package name under the title, the spec that installs it elsewhere. A bundle's switch changes its layer selection. A profile with HMR recomposes before the operation completes; one without HMR, and a bundle a higher layer overrides, say so in a toast. A bundle the Host cannot read carries a problem tag and its reason on its page and cannot be switched on; one that provides the management components stays locked. The Host answers with error codes, which the page's dictionary words; pnpm's and the Loader's own diagnostics are shown as they are. The installation's own bundles are not on the page; the Settings Plugins section's Plugin list tab inspects them.
+A bundle's page shows its full package name under the title, the spec that installs it elsewhere. A bundle's switch changes its layer selection. A profile with HMR recomposes before the operation completes; one without HMR, and a bundle a higher layer overrides, say so in a toast. A bundle the Host cannot read carries a problem tag and its reason on its page and cannot be switched on; one that provides the management components stays locked. The Host answers with error codes, which the page's dictionary words; pnpm's and the Loader's own diagnostics are shown as they are. The page excludes built-in profile bundles from cards and counts even when the profile holds them as dependencies or the Host reports an error. The Host inventory remains complete; the Settings Plugins section's Plugin list tab inspects their plugins.
 
 ### Switching one row of a bundle
 

+ 1 - 1
packages/client/ui-plugin-manager/README.zh.md

@@ -37,7 +37,7 @@ Agent Teams、Agent Teams Web UI 和 Auto Authorization Review 三个包使用
 
 ### 切换一个组合包
 
-组合包页面在标题下方显示完整包名,也就是在别处安装它所需的 spec。组合包开关改变其层选择。启用了 HMR 的 profile 在操作完成前重组;没有 HMR 的 profile,以及被更高层覆盖的组合包,会以 toast 说明。Host 读不了的组合包带异常标签,其页面给出原因,且不能打开;提供管理组件的组合包保持锁定。Host 以错误码作答,由页面字典措辞;pnpm 与 Loader 自己的诊断原样显示。随安装提供的组合包不在本页;设置中「插件」分区的「插件列表」标签页负责查看它们。
+组合包页面在标题下方显示完整包名,也就是在别处安装它所需的 spec。组合包开关改变其层选择。启用了 HMR 的 profile 在操作完成前重组;没有 HMR 的 profile,以及被更高层覆盖的组合包,会以 toast 说明。Host 读不了的组合包带异常标签,其页面给出原因,且不能打开;提供管理组件的组合包保持锁定。Host 以错误码作答,由页面字典措辞;pnpm 与 Loader 自己的诊断原样显示。页面从卡片与数量中排除内置 profile 组合包,即使 profile 将它们列为依赖或 Host 报告了异常。Host 清单仍保留完整数据;设置中「插件」分区的「插件列表」标签页负责查看它们的插件。
 
 ### 切换组合包里的一行
 

+ 12 - 1
packages/client/ui-plugin-manager/src/client/PluginManagerPage.tsx

@@ -51,6 +51,16 @@ type RowPhase = NonNullable<PackageRow['phase']>
 /** How long the list marks a package an install just enabled. */
 const HIGHLIGHT_MS = 2_400
 
+/** Built-in profile bundles stay out of this page even when the profile declares them as dependencies. */
+const BUILTIN_PROFILE_BUNDLES = new Set([
+  '@deepseek-ai/dsh-base',
+  '@deepseek-ai/dsh-web-app',
+  '@deepseek-ai/dsh-headless',
+  '@deepseek-ai/dsh-sdk-app',
+  '@deepseek-ai/dsh-acp-app',
+  '@deepseek-ai/dsh-sdk-minimal',
+])
+
 /** How long a toast holds: long enough to read a failure that names what broke. */
 function toastHoldMs(text: string): number {
   return Math.min(8_000, Math.max(3_000, text.length * 80))
@@ -848,7 +858,8 @@ export function PluginManagerPage(props: PluginManagerPageProps): ReactNode {
   // The page manages what the person installed, what the installation ships for them to switch on, and a
   // selected name the Host cannot read; the installation's other bundles are inspected in the Settings
   // Plugins section's Plugin list tab.
-  const listed = state.packages.filter(pkg => pkg.installed || pkg.optional || pkg.error !== undefined)
+  const listed = state.packages.filter(pkg => !BUILTIN_PROFILE_BUNDLES.has(pkg.name)
+    && (pkg.installed || pkg.optional || pkg.error !== undefined))
   const mine = listed.filter(pkg => pkg.installed || !pkg.optional)
   const official = listed.filter(pkg => pkg.optional && !pkg.installed)
   const loaded = state.status === 'ready' || state.status === 'error'

+ 33 - 0
packages/client/ui-plugin-manager/tests/components.client.spec.tsx

@@ -155,6 +155,39 @@ describe('PluginManagerPage', () => {
     expect(locked.getAttribute('title')).toBe(en.reasonManagementRequired)
   })
 
+  it('omits built-in profile dependencies from cards and counts while retaining optional and third-party bundles', () => {
+    renderTab({
+      packages: [
+        ...[
+          '@deepseek-ai/dsh-base',
+          '@deepseek-ai/dsh-web-app',
+          '@deepseek-ai/dsh-headless',
+          '@deepseek-ai/dsh-sdk-app',
+          '@deepseek-ai/dsh-acp-app',
+          '@deepseek-ai/dsh-sdk-minimal',
+        ].map(name => pkg({ name })),
+        pkg({ name: '@acme/dsh-base', readOnlyReason: 'management-required' }),
+        pkg({ name: 'dsh-better-sidebar' }),
+        pkg({ name: '@deepseek-ai/dsh-experimental-agent-team-profile', installed: false, optional: true }),
+      ],
+    })
+    expect(screen.getAllByRole('listitem').map(card => card.getAttribute('data-plugin-package'))).toEqual([
+      '@deepseek-ai/dsh-experimental-agent-team-profile', '@acme/dsh-base', 'dsh-better-sidebar',
+    ])
+    expect([...document.querySelectorAll('[data-plugin-count]')].map(count => count.textContent)).toEqual(['1', '2'])
+  })
+
+  it.each([false, true])('shows an empty list for built-in bundles with errors and installed=%s', (installed) => {
+    renderTab({
+      packages: ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app'].map(name => pkg({
+        name, installed, error: { code: 'operation-error', diagnostic: 'Unreadable bundle' },
+      })),
+    })
+    expect(screen.getByText(en.empty)).toBeTruthy()
+    expect(screen.queryAllByRole('listitem')).toHaveLength(0)
+    expect(document.querySelectorAll('[data-plugin-count]')).toHaveLength(0)
+  })
+
   it('opens an official bundle\'s page with its beta tag and no uninstall, and switches it on', () => {
     const { actions } = renderTab({
       packages: [pkg({ name: '@deepseek-ai/dsh-experimental-agent-team-profile', installed: false, optional: true, enabled: false })],