Jelajahi Sumber

fix(web): update Subagent parallelism copy

ZiyaZhang 2 hari lalu
induk
melakukan
6affc44992

+ 3 - 3
apps/web/tests/expected/plugin-config/subagent.expected.md

@@ -49,12 +49,12 @@
           - textbox "最大递归深度":
             - /placeholder: ""
             - text: "2"
-          - text: Subagent 总数上限
-          - button "Subagent 总数上限说明":
+          - text: Subagent 并行数量上限
+          - button "Subagent 并行数量上限说明":
             - img
           - text: 已覆盖
           - button "恢复默认"
-          - textbox "Subagent 总数上限":
+          - textbox "Subagent 并行数量上限":
             - /placeholder: ""
             - text: "12"
         - region "模型选择":

+ 4 - 4
apps/web/tests/plugin-config.e2e.ts

@@ -91,7 +91,7 @@ describe('web e2e: plugin configuration section', () => {
     const dialog = await openPlugins()
     await dialog.getByRole('button', { name: '展开设置: Subagent', exact: true }).click()
     const depth = dialog.getByLabel('最大递归深度', { exact: true })
-    const capacity = dialog.getByLabel('Subagent 总数上限', { exact: true })
+    const capacity = dialog.getByLabel('Subagent 并行数量上限', { exact: true })
     expect(await depth.inputValue()).toBe('3')
     expect(await capacity.inputValue()).toBe('8')
     await depth.fill('2')
@@ -136,9 +136,9 @@ describe('web e2e: plugin configuration section', () => {
     await depthHelp.press('Enter')
     expect(await depthRules.count()).toBe(0)
     expect(await depth.inputValue()).toBe('2')
-    await dialog.getByRole('button', { name: 'Subagent 总数上限说明', exact: true }).click()
-    const capacityRules = dialog.getByRole('region', { name: 'Subagent 总数上限说明', exact: true })
-    expect(await capacityRules.getByText('同一主 Agent 下,同时存活的 Subagent 总数,包含所有递归层级。等待中的 Subagent 也计入,主 Agent 不计入。', { exact: true }).count()).toBe(1)
+    await dialog.getByRole('button', { name: 'Subagent 并行数量上限说明', exact: true }).click()
+    const capacityRules = dialog.getByRole('region', { name: 'Subagent 并行数量上限说明', exact: true })
+    expect(await capacityRules.getByText('同一主 Agent 下,所有递归层级同时存活的 Subagent 总数,等待中的 Subagent 和主 Agent 不计入。', { exact: true }).count()).toBe(1)
     await dialog.getByRole('button', { name: '放弃修改', exact: true }).click()
     expect(await depth.inputValue()).toBe('3')
   })

+ 2 - 2
packages/client/ui-settings-plugins/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-settings-plugins/README.md
-README.md: 753819b9bdcba692d31f6f8d0f471b5816c18391
-README.zh.md: a5b9f3b7434e46ca3bde81863ac044b357deac45
+README.md: b5e05c604d2e267de42393332903acdf83a315b4
+README.zh.md: 672d27376335e9191fa9cde81d88d1ca95831fcb

+ 1 - 1
packages/client/ui-settings-plugins/README.md

@@ -35,7 +35,7 @@ The tab reads which settings namespaces the Host serves and dispatches one slot
 
 A card stages what the user types and writes it only when they save. Each control renders staged text, so what is on screen is exactly what a save would store; **Discard** drops the drafts, and a card holding unsaved edits says so on its header even while collapsed. A successful save collapses the card after the read-back confirms the writes; a failed save keeps the card open, reports the failure, and retains the drafts for correction. A reset stages the composed default rather than writing immediately, and a draft the field does not accept blocks the save instead of being dropped. The Host is the only authority on whether a value was accepted.
 
-The **Subagent** card groups delegation limits and model selection under one disclosure and one save/discard footer. **Maximum recursion depth** and **Subagent count limit** appear side by side, stacking on narrow screens. Information buttons reveal a two-row depth example and the shared count rule; validation errors remain visible below the input. Depth retains explicit tool overrides. Capacity counts live continuable descendants across all recursion levels, including waiting children and excluding the root, one-shot runs, and external providers. Saving applies to later delegation attempts; lowering capacity does not stop existing children.
+The **Subagent** card groups delegation limits and model selection under one disclosure and one save/discard footer. **Maximum recursion depth** and **Subagent parallelism limit** appear side by side, stacking on narrow screens. Information buttons reveal a two-row depth example and the shared count rule; validation errors remain visible below the input. Depth retains explicit tool overrides. Capacity counts live continuable descendants across all recursion levels, including waiting children and excluding the root, one-shot runs, and external providers. Saving applies to later delegation attempts; lowering capacity does not stop existing children.
 
 The model selection section stages its permission switch and exact model checkboxes together. Enabling requires at least one selected adapter route. Saving submits `enabled` and `allowedModels` in one mutation fenced by the revision where that draft began; a newer Host revision marks the draft failed instead of restoring a revoked route. Disabling retains the selected routes for later reuse. Available models are grouped by provider, while saved routes absent from the current catalog appear last and remain removable. Adapter names and model descriptions remain live directory metadata and are not stored, and the card refreshes them after adapter changes, settings commits, and reconnects.
 

+ 1 - 1
packages/client/ui-settings-plugins/README.zh.md

@@ -35,7 +35,7 @@ kind: "package-reference"
 
 卡片暂存用户输入,只有用户保存时才写入。每个控件渲染的都是暂存文本,因此屏幕上所见即保存后所存;**放弃修改**丢弃这些草稿,持有未保存修改的卡片即使收起也会在标题上标明。保存成功后,卡片会在回读确认写入后收起;保存失败时,卡片保持展开、报告失败并保留草稿供用户修改。重置暂存的是组装默认值而非立即写入;字段不接受的草稿会阻塞保存,而不是被丢弃。某个值是否被接受只有 Host 说了算。
 
-**Subagent** 卡片将委派限制与模型选择放在同一个折叠项中,共用保存和放弃修改操作。**最大递归深度**和 **Subagent 总数上限**并排呈现,窄屏时上下排列。信息按钮按需展开两行深度示例表和共享计数规则;校验错误仍直接显示在输入框下。深度保留工具显式覆盖。总数统计所有递归层级中存活的可续接 Subagent,包含等待中的 Subagent,不计入主 Agent、一次性运行和外部提供方。保存后用于后续委派;调低上限不会停止已有 Subagent。
+**Subagent** 卡片将委派限制与模型选择放在同一个折叠项中,共用保存和放弃修改操作。**最大递归深度**和 **Subagent 并行数量上限**并排呈现,窄屏时上下排列。信息按钮按需展开两行深度示例表和共享计数规则;校验错误仍直接显示在输入框下。深度保留工具显式覆盖。总数统计所有递归层级中存活的可续接 Subagent,包含等待中的 Subagent,不计入主 Agent、一次性运行和外部提供方。保存后用于后续委派;调低上限不会停止已有 Subagent。
 
 模型选择分区会同时暂存其权限开关与精确模型复选框。启用时必须至少选择一条适配器路由。保存会在一次 mutation 中提交 `enabled` 与 `allowedModels`,并以草稿开始时的 revision 设栅;Host revision 更新后,草稿会标记为失败,而不会恢复已撤销的路由。关闭时会保留已选路由供以后重新使用。可用模型按提供方分组;当前目录中缺失的已存路由排在末尾,且仍可移除。适配器名称与模型描述仍属于实时目录元数据,不会存储;适配器变化、设置提交和重连后,卡片会刷新这些元数据。
 

+ 6 - 6
packages/client/ui-settings-plugins/src/client/locales.ts

@@ -74,9 +74,9 @@ export const en: Record<PluginsSettingsLocaleKey, string> = {
   subagentDepthZero: 'Disable Subagents',
   subagentDepthOne: 'Only the main Agent can create Subagents',
   subagentDepthOverride: 'If a tool defines its own maximum recursion depth, that setting takes precedence.',
-  subagentMaxActive: 'Subagent count limit',
-  subagentCapacityHelpLabel: 'About the Subagent count limit',
-  subagentCapacityHelp: 'Total live Subagents under the same main Agent, across all recursion levels. Waiting Subagents count; the main Agent does not.',
+  subagentMaxActive: 'Subagent parallelism limit',
+  subagentCapacityHelpLabel: 'About the Subagent parallelism limit',
+  subagentCapacityHelp: 'Total live Subagents under the same main Agent, across all recursion levels. Waiting Subagents and the main Agent are excluded.',
   subagentDepthInvalid: 'Enter a whole number of 0 or more.',
   subagentCapacityInvalid: 'Enter a whole number of 1 or more.',
   subagentModelSelectionTitle: 'Model selection',
@@ -143,9 +143,9 @@ export const zh: Record<PluginsSettingsLocaleKey, string> = {
   subagentDepthZero: '禁用 Subagent',
   subagentDepthOne: '仅允许主 Agent 创建 Subagent',
   subagentDepthOverride: '如果某个工具单独设置了最大递归深度,以该工具的设置为准。',
-  subagentMaxActive: 'Subagent 总数上限',
-  subagentCapacityHelpLabel: 'Subagent 总数上限说明',
-  subagentCapacityHelp: '同一主 Agent 下,同时存活的 Subagent 总数,包含所有递归层级。等待中的 Subagent 也计入,主 Agent 不计入。',
+  subagentMaxActive: 'Subagent 并行数量上限',
+  subagentCapacityHelpLabel: 'Subagent 并行数量上限说明',
+  subagentCapacityHelp: '同一主 Agent 下,所有递归层级同时存活的 Subagent 总数,等待中的 Subagent 和主 Agent 不计入。',
   subagentDepthInvalid: '请输入不小于 0 的整数。',
   subagentCapacityInvalid: '请输入不小于 1 的整数。',
   subagentModelSelectionTitle: '模型选择',

+ 2 - 2
packages/client/ui-settings-plugins/tests/stores.client.spec.ts

@@ -1242,7 +1242,7 @@ describe('shared Subagent card actions', () => {
   it('retains the pending draft when discard is requested before both writes finish', async () => {
     const { limits, face, state } = card()
     const pending = deferred<undefined>()
-    limits.set.mockImplementationOnce(async () => {
+    const set = vi.spyOn(limits.scope, 'set').mockImplementationOnce(async () => {
       await pending.promise
       limits.publish({ value: { maxDepth: 2, maxActiveSubagents: 8 }, user: { maxDepth: 2 } })
     })
@@ -1254,7 +1254,7 @@ describe('shared Subagent card actions', () => {
         expect(face.hooks.subagentModelSelectionCard.getSnapshot()).toMatchObject({ saving: false, dirty: false })
       })
       expect(state().saving).toBe(true)
-      expect(limits.set).toHaveBeenCalledWith('maxDepth', 2)
+      expect(set).toHaveBeenCalledWith('maxDepth', 2)
       face.discard()
       expect(face.hooks.subagentLimitsCard.getSnapshot()).toMatchObject({ dirty: true, maxDepth: { text: '2' } })
     } finally {