diff --git a/apps/web/tests/access-confirmation.e2e.ts b/apps/web/tests/access-confirmation.e2e.ts index a47cad63f6..0ba0f60b25 100644 --- a/apps/web/tests/access-confirmation.e2e.ts +++ b/apps/web/tests/access-confirmation.e2e.ts @@ -64,7 +64,7 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { const currentMenu = page.getByRole('menu') await currentMenu.waitFor({ timeout: 10_000 }) expect(await currentMenu.getByRole('menuitem').allTextContents()) - .toEqual(['仅可查看', '工作区内修改', '完全权限', 'Auto reviewEXP']) + .toEqual(['仅可查看', '工作区内修改', '完全权限', '自动审查EXP']) await captureAutoReviewState(page, 'experimental-current-session-picker') const currentSnapshot = await captureStableAria(page, '[role="menu"]', scaffold.workspaceCwd) await compareOrRefreshGolden(CURRENT_SESSION_PICKER_EXPECTED, currentSnapshot, MODE) @@ -77,10 +77,10 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { expect(currentMenuBox!.width).toBeGreaterThan(currentTriggerBox!.width) expect(Math.abs(currentTriggerBox!.y - currentMenuBox!.y - currentMenuBox!.height - 4)).toBeLessThan(1) - await currentMenu.getByRole('menuitem', { name: 'Auto review EXP' }).click() - const autoDialog = page.getByRole('dialog', { name: '确认启用 Auto review(实验)?' }) + await currentMenu.getByRole('menuitem', { name: '自动审查 EXP' }).click() + const autoDialog = page.getByRole('dialog', { name: '确认启用自动审查(实验)?' }) await autoDialog.waitFor({ timeout: 10_000 }) - const autoEnable = autoDialog.getByRole('button', { name: '启用 Auto review' }) + const autoEnable = autoDialog.getByRole('button', { name: '启用自动审查' }) expect(await autoEnable.isDisabled()).toBe(true) expect(await autoDialog.getByText(/不使用沙箱/).count()).toBe(1) expect(await autoDialog.getByText(/误放行或误拒绝/).count()).toBe(1) @@ -105,7 +105,7 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { await slashPicker.waitFor({ timeout: 10_000 }) const slashRows = slashPicker.getByRole('option') expect(await slashRows.count()).toBe(4) - expect(await slashPicker.getByRole('option', { name: 'Auto review EXP' }).count()).toBe(1) + expect(await slashPicker.getByRole('option', { name: '自动审查 EXP' }).count()).toBe(1) await captureAutoReviewState(page, 'experimental-slash-picker') const slashSnapshot = await captureStableAria(page, '[aria-label="/permission 选项"]', scaffold.workspaceCwd) await compareOrRefreshGolden(SLASH_PICKER_EXPECTED, slashSnapshot, MODE) @@ -119,15 +119,15 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { expect(slashPickerBox!.x).toBeCloseTo(composerBox!.x) expect(Math.abs(composerBox!.y - slashPickerBox!.y - slashPickerBox!.height - 4)).toBeLessThan(1) - await slashPicker.getByRole('option', { name: 'Auto review EXP' }).click() - const slashDialog = page.getByRole('dialog', { name: '确认启用 Auto review(实验)?' }) + await slashPicker.getByRole('option', { name: '自动审查 EXP' }).click() + const slashDialog = page.getByRole('dialog', { name: '确认启用自动审查(实验)?' }) await slashDialog.waitFor({ timeout: 10_000 }) expect(await slashDialog.count()).toBe(1) expect(await slashPicker.count()).toBe(0) await slashDialog.getByRole('checkbox', { name: '我已了解这些风险,并愿意继续' }).check() - await slashDialog.getByRole('button', { name: '启用 Auto review' }).click() + await slashDialog.getByRole('button', { name: '启用自动审查' }).click() await expect.poll(() => access.getAttribute('aria-label'), { timeout: 10_000 }) - .toBe('访问模式,当前:Auto review EXP') + .toBe('访问模式,当前:自动审查 EXP') expect(await slashDialog.count()).toBe(0) expect(await input.textContent()).toBe('') await captureAutoReviewState(page, 'experimental-current-session') @@ -188,12 +188,18 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { expect(menuBox.width).toBeLessThanOrEqual(360) expect(menuBox.x).toBeGreaterThanOrEqual(0) expect(menuBox.x + menuBox.width).toBeLessThanOrEqual(420) - for (const name of ['仅可查看', '工作区内修改', '完全权限', 'Auto review']) { + for (const name of ['仅可查看', '工作区内修改', '完全权限', '自动审查']) { expect(await menu.getByText(name, { exact: true }).evaluate(node => node.scrollWidth <= node.clientWidth)).toBe(true) } await page.keyboard.press('Escape') const input = page.locator('[data-composer-input]').first() + await writeComposerDraft(page, input, '/permission auto') + await input.press('Enter') + await expect.poll(() => access.getAttribute('aria-label')).toBe('访问模式,当前:自动审查 EXP') + expect(await access.getByText('自动审查', { exact: true }).isVisible()).toBe(false) + expect(await access.getByText('EXP', { exact: true }).isVisible()).toBe(true) + expect(await access.getAttribute('title')).toBe('无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。') await writeComposerDraft(page, input, '/permission') await input.press('Escape') await input.press('Enter') @@ -206,7 +212,7 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { expect(slashBox.x + slashBox.width).toBeLessThanOrEqual(420) expect(await slash.evaluate(node => getComputedStyle(node).minWidth)).toBe('min(220px, 100%)') expect(await slash.evaluate(node => getComputedStyle(node).maxWidth)).toBe('100%') - for (const name of ['仅可查看', '工作区内修改', '完全权限', 'Auto review']) { + for (const name of ['仅可查看', '工作区内修改', '完全权限', '自动审查']) { expect(await slash.getByText(name, { exact: true }).evaluate(node => node.scrollWidth <= node.clientWidth)).toBe(true) } await page.keyboard.press('Escape') @@ -219,7 +225,7 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { const access = page.locator('button[aria-label^="访问模式"]').first() await writeComposerDraft(page, input, '/permission auto') await input.press('Enter') - await expect.poll(() => access.getAttribute('aria-label')).toBe('访问模式,当前:Auto review EXP') + await expect.poll(() => access.getAttribute('aria-label')).toBe('访问模式,当前:自动审查 EXP') expect(await page.getByRole('dialog').count()).toBe(0) await writeComposerDraft(page, input, '/permission') await input.press('Escape') @@ -237,7 +243,7 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { await input.press('Enter') await slash.waitFor() expect(await slash.getByRole('option').count()).toBe(3) - expect(await slash.getByText('Auto review', { exact: true }).count()).toBe(0) + expect(await slash.getByText('自动审查', { exact: true }).count()).toBe(0) await page.keyboard.press('Escape') await access.click() await expect.poll(() => page.getByRole('menuitem').allTextContents()) @@ -248,7 +254,7 @@ describe('web e2e: experimental Auto and Full access confirmation', () => { await scaffold.ctx.loader.await() await access.click() await expect.poll(() => page.getByRole('menuitem').allTextContents()) - .toEqual(['仅可查看', '工作区内修改', '完全权限', 'Auto reviewEXP']) + .toEqual(['仅可查看', '工作区内修改', '完全权限', '自动审查EXP']) expect(await access.getAttribute('aria-label')).toBe('访问模式,当前:完全权限') await captureAutoReviewState(page, 'reinstalled-current-session-picker') await page.keyboard.press('Escape') @@ -302,7 +308,7 @@ describe('web e2e: default permission choices', () => { const slash = page.locator('[aria-label="/permission 选项"]') await slash.waitFor() expect(await slash.getByRole('option').count()).toBe(3) - expect(await slash.getByText('Auto review', { exact: true }).count()).toBe(0) + expect(await slash.getByText('自动审查', { exact: true }).count()).toBe(0) await captureAutoReviewState(page, 'default-slash-picker') }) }) diff --git a/apps/web/tests/expected/access-confirmation/auto-confirmation.expected.md b/apps/web/tests/expected/access-confirmation/auto-confirmation.expected.md index b9967c9722..6c7320a3da 100644 --- a/apps/web/tests/expected/access-confirmation/auto-confirmation.expected.md +++ b/apps/web/tests/expected/access-confirmation/auto-confirmation.expected.md @@ -1,8 +1,8 @@ -- dialog "确认启用 Auto review(实验)?": - - heading "确认启用 Auto review(实验)?" [level=2] +- dialog "确认启用自动审查(实验)?": + - heading "确认启用自动审查(实验)?" [level=2] - button "关闭" - - paragraph: Auto review 不使用沙箱。每次原生工具调用和 PTC 内层调用前,都会由与当前 agent 相同的模型进行审查;审查拒绝的调用由你批准或拒绝。此功能仍属实验性,可能误放行或误拒绝,并会消耗额外 token。 + - paragraph: 自动审查不使用沙箱。每次原生工具调用和 PTC 内层调用前,都会由与当前 agent 相同的模型进行审查;审查拒绝的调用由你批准或拒绝。此功能仍属实验性,可能误放行或误拒绝,并会消耗额外 token。 - checkbox "我已了解这些风险,并愿意继续" - text: 我已了解这些风险,并愿意继续 - button "取消" - - button "启用 Auto review" [disabled] + - button "启用自动审查" [disabled] diff --git a/apps/web/tests/expected/access-confirmation/current-session-picker.expected.md b/apps/web/tests/expected/access-confirmation/current-session-picker.expected.md index 9e942e44b5..688540b20e 100644 --- a/apps/web/tests/expected/access-confirmation/current-session-picker.expected.md +++ b/apps/web/tests/expected/access-confirmation/current-session-picker.expected.md @@ -2,6 +2,4 @@ - menuitem "仅可查看" - menuitem "工作区内修改" - menuitem "完全权限" - - menuitem "Auto review EXP": - - text: Auto review - - superscript: EXP + - menuitem "自动审查 EXP" diff --git a/apps/web/tests/expected/access-confirmation/slash-picker.expected.md b/apps/web/tests/expected/access-confirmation/slash-picker.expected.md index f1b12d28b0..cf54b54669 100644 --- a/apps/web/tests/expected/access-confirmation/slash-picker.expected.md +++ b/apps/web/tests/expected/access-confirmation/slash-picker.expected.md @@ -4,7 +4,7 @@ - option "仅可查看" - option "工作区内修改" [selected] - option "完全权限" - - option "Auto review EXP": - - text: Auto review + - option "自动审查 EXP": + - text: 自动审查 - superscript: EXP - text: 无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。 diff --git a/packages/client/ui-permission-presets/README.i18n.yaml b/packages/client/ui-permission-presets/README.i18n.yaml index 3f24ef0979..4a82785e6a 100644 --- a/packages/client/ui-permission-presets/README.i18n.yaml +++ b/packages/client/ui-permission-presets/README.i18n.yaml @@ -10,7 +10,7 @@ zh: 74b8ded4da556e81 /deepseek-ai-dsh-client-ui-permission-presets/summary: en: 2591adc4721c0564 - zh: 311292f58621adb6 + zh: 558413d3f819d3af /deepseek-ai-dsh-client-ui-permission-presets/table-of-contents: en: d152484eb41ac6b4 zh: 09388d293f9be9cb @@ -18,14 +18,14 @@ en: 91606bff7da02253 zh: ef68e813d64c89be /deepseek-ai-dsh-client-ui-permission-presets/use-this-package/the-picker: - en: d851eab85fe002bd - zh: 0fdf6eeb1cbd609b + en: 8f19c50b77efd248 + zh: 711d331760b93d11 /deepseek-ai-dsh-client-ui-permission-presets/use-this-package/the-settings-row: en: 5067f6aa12496225 zh: cfa6796684f97535 /deepseek-ai-dsh-client-ui-permission-presets/understand-the-implementation: en: 4089d5bebf3e8bf0 - zh: bc5c3652b0612784 + zh: 22071e6cd6de0ffc /deepseek-ai-dsh-client-ui-permission-presets/further-exploration: en: 9bdbdea03d0e2a96 zh: cc3bf480a0706ef2 @@ -37,7 +37,7 @@ zh: 4fcbc876952d240d /deepseek-ai-dsh-client-ui-permission-presets/known-limitations-and-deferred-work: en: 08cdc0ad196d12c1 - zh: 1b65f5d30e219197 + zh: 157bee9d5b29f470 /deepseek-ai-dsh-client-ui-permission-presets/known-limitations-and-deferred-work/dev-note: en: e67f633dc6fe7773 zh: 3bb0c20c93f16f98 diff --git a/packages/client/ui-permission-presets/README.md b/packages/client/ui-permission-presets/README.md index 6798cc7f47..1618b0d305 100644 --- a/packages/client/ui-permission-presets/README.md +++ b/packages/client/ui-permission-presets/README.md @@ -29,7 +29,7 @@ Mount this plugin alongside the settings, commands, and conversation packages. G ### The picker -A pick submits the `/permission ` command line. The argument-bearing form (`/permission ` typed directly) still switches directly; the decoration replaces only the bare invocation. The built-in labels are `Read Only`, `Workspace Write`, `Full access`, and `Auto review` in English and `仅可查看`, `工作区内修改`, `完全权限`, and `Auto review` in Chinese. Explicit host labels remain unchanged, unknown kebab-case names render in title case, and `auto` carries an `EXP` badge plus an experimental-risk confirmation. `custom` is display state, never a target. +A pick submits the `/permission ` command line. The argument-bearing form (`/permission ` typed directly) still switches directly; the decoration replaces only the bare invocation. The built-in labels are `Read Only`, `Workspace Write`, `Full access`, and `Auto review` in English and `仅可查看`, `工作区内修改`, `完全权限`, and `自动审查` in Chinese. Explicit host labels remain unchanged, unknown kebab-case names render in title case, and `auto` carries an `EXP` badge plus an experimental-risk confirmation. `custom` is display state, never a target. When the live catalog withdraws a preset, the composer closes its pending confirmation and shows the Session's current value instead of an unavailable optimistic pick. Every catalog invalidation — the payload-free notification or a connection-generation change — closes an open slash picker or its confirmation without consuming the draft, while publishing the result of a read the picker waits for leaves it open with its failure and retry state; reopening reads the current catalog. A submitted command remains busy until its response settles. diff --git a/packages/client/ui-permission-presets/README.zh.md b/packages/client/ui-permission-presets/README.zh.md index 1c603b5eb5..e2a8df74c4 100644 --- a/packages/client/ui-permission-presets/README.zh.md +++ b/packages/client/ui-permission-presets/README.zh.md @@ -9,7 +9,7 @@ kind: "package-reference" ## 概述 -为当前 Web 会话或未来会话选择权限预设。通用设置行只更改之后创建会话所用的默认值;composer 与 `/permission` 选择器切换当前会话。默认 Web 提供仅可查看、工作区内修改与完全权限。显式加载实验 Auto integration 后,当前会话选择器会增加带 `EXP` 标记的 Auto review。通过可见选项选择完全权限或 Auto 时,需要分别确认对应风险;完整的 `/permission ` 命令直接执行。宿主通过 Session 投影确认每次变更。 +为当前 Web 会话或未来会话选择权限预设。通用设置行只更改之后创建会话所用的默认值;composer 与 `/permission` 选择器切换当前会话。默认 Web 提供仅可查看、工作区内修改与完全权限。显式加载实验 Auto integration 后,当前会话选择器会增加带 `EXP` 标记的自动审查。通过可见选项选择完全权限或 Auto 时,需要分别确认对应风险;完整的 `/permission ` 命令直接执行。宿主通过 Session 投影确认每次变更。 ## 目录 @@ -29,7 +29,7 @@ kind: "package-reference" ### 选择器 -选中即提交 `/permission ` 命令行。带参形式(直接键入 `/permission `)仍直接切换;装饰只替换裸调用。内置标签在英文界面中是 `Read Only`、`Workspace Write`、`Full access` 和 `Auto review`,在中文界面中是「仅可查看」「工作区内修改」「完全权限」和 `Auto review`。显式 host 标签保持原样,未知 kebab-case 名称渲染为 Title Case;`auto` 带有 `EXP` badge,并在可见选择时要求实验风险确认。`custom` 只是显示状态,绝非目标。 +选中即提交 `/permission ` 命令行。带参形式(直接键入 `/permission `)仍直接切换;装饰只替换裸调用。内置标签在英文界面中是 `Read Only`、`Workspace Write`、`Full access` 和 `Auto review`,在中文界面中是「仅可查看」「工作区内修改」「完全权限」和「自动审查」。显式 host 标签保持原样,未知 kebab-case 名称渲染为 Title Case;`auto` 带有 `EXP` badge,并在可见选择时要求实验风险确认。`custom` 只是显示状态,绝非目标。 实时目录撤销某个预设时,composer 关闭对应的待确认对话框,并用 Session 的当前值替代已不可用的乐观选择。每次目录失效(无 payload 的通知或连接代际变更)会关闭已打开的 slash 选择器或其确认对话框,不消费草稿;而发布某个 picker 正在等待的读取结果时,该 picker 保持打开并保留失败与重试状态;重新打开时读取当前目录。已经提交的命令在响应结束前继续保持忙碌状态。 @@ -45,7 +45,7 @@ kind: "package-reference"
实现细节——点击展开 -General Settings 行经 `ctx.configForms` 读取显式暴露的 `permission` Settings 描述符,并携带描述符 revision 写入一条 `settings.mutate` 路径操作;其 observable 经 slot 系统的 `hooks` compartment 传递,因此 React 钩子绑定归渲染器,推送失效通知会重新获取描述符。该值只在之后创建会话时读取。当前会话界面是挂在宿主 `/permission` 命令上的 popupSelect 装饰(`ctx.commandUi.decorate`):宿主命令保留斜杠菜单行、带参形式与持久生命周期记账,装饰只把裸调用替换为选择器。一个进程级目录会在首次 Remote 读取前订阅无 payload 的目录通知,并且只发布当前连接代际中最新的完整成功结果。胜出的读取失败或连接 reset 会清空旧快照:composer seat 因此隐藏,直到后续既有触发重试,而 slash 选择器保持可用并在弹窗内显示失败与重试;旧连接代际与 dispose 后才返回的结果会被忽略。它的公共 observable 是 `{ value }` 与 `invalidations`(每次目录通知或连接代际变更打一个点);失败仅供命令式加载内部使用。slash popup 与 composer seat 共用这份目录,而 Session `permissions` 投影只提供 `currentValue`。Full access 与 Auto review 各自携带本地化确认文案;Auto 还携带由共享 popup 外壳渲染的 badge。 +General Settings 行经 `ctx.configForms` 读取显式暴露的 `permission` Settings 描述符,并携带描述符 revision 写入一条 `settings.mutate` 路径操作;其 observable 经 slot 系统的 `hooks` compartment 传递,因此 React 钩子绑定归渲染器,推送失效通知会重新获取描述符。该值只在之后创建会话时读取。当前会话界面是挂在宿主 `/permission` 命令上的 popupSelect 装饰(`ctx.commandUi.decorate`):宿主命令保留斜杠菜单行、带参形式与持久生命周期记账,装饰只把裸调用替换为选择器。一个进程级目录会在首次 Remote 读取前订阅无 payload 的目录通知,并且只发布当前连接代际中最新的完整成功结果。胜出的读取失败或连接 reset 会清空旧快照:composer seat 因此隐藏,直到后续既有触发重试,而 slash 选择器保持可用并在弹窗内显示失败与重试;旧连接代际与 dispose 后才返回的结果会被忽略。它的公共 observable 是 `{ value }` 与 `invalidations`(每次目录通知或连接代际变更打一个点);失败仅供命令式加载内部使用。slash popup 与 composer seat 共用这份目录,而 Session `permissions` 投影只提供 `currentValue`。完全权限与自动审查各自携带本地化确认文案;Auto 还携带由共享 popup 外壳渲染的 badge。
@@ -80,7 +80,7 @@ General Settings 行经 `ctx.configForms` 读取显式暴露的 `permission` Set 这些限制界定了当前权限界面。它们是当前包约束,不是通用策略对比或任务积压。 - **设置行仅限 Web**——非 Web 客户端仍可经 `/permission` 切换当前会话,但不会获得这项浏览器贡献。 -- **Auto review 仅限当前会话**——General Settings 行有意省略它,且只有通过可见选择器选择时才显示实验确认;显式键入 `/permission auto` 已经构成明确同意。 +- **自动审查仅限当前会话**——General Settings 行有意省略它,且只有通过可见选择器选择时才显示实验确认;显式键入 `/permission auto` 已经构成明确同意。 - **预设描述来自宿主**——本地化的内置标签旁边可能显示另一种语言编写的描述。 diff --git a/packages/client/ui-permission-presets/src/client/PermissionSelect.module.css b/packages/client/ui-permission-presets/src/client/PermissionSelect.module.css index b40748e22e..30853c170f 100644 --- a/packages/client/ui-permission-presets/src/client/PermissionSelect.module.css +++ b/packages/client/ui-permission-presets/src/client/PermissionSelect.module.css @@ -52,7 +52,7 @@ .optionLabel { display: inline-flex; - align-items: baseline; + align-items: center; gap: 4px; min-width: 0; max-width: 100%; @@ -67,12 +67,10 @@ .badge { flex: none; - align-self: flex-start; - margin-top: -1px; color: var(--dsw-alias-label-tertiary); font-size: 8px; line-height: 10px; - font-weight: 600; + font-weight: 500; letter-spacing: 0.2px; } @@ -85,8 +83,8 @@ transition: transform 120ms ease; } -/* Narrow composer: the trigger collapses to icon + chevron so the row keeps - fitting. Only triggers that actually carry a mode glyph drop their label — +/* Narrow composer: mode text collapses while icons and badges stay visible. + Only triggers that actually carry a mode glyph drop their label — a host-configured mode without one keeps its text as the sole identifier. The 460px cut is the point where the row (attach + modes + model + send) starts squeezing labels; the container is the composer row (InputBar .row — diff --git a/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx b/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx index f34e2b16e9..f5d2c5a679 100644 --- a/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx +++ b/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx @@ -29,6 +29,7 @@ const permissionGlyphs = new Map([ ['read-only', ], ['workspace-write', ], [FULL_ACCESS, ], + [AUTO_REVIEW, ], ]) /** Glyph for a permission option value; host-configured names outside the design set get none. */ @@ -112,7 +113,7 @@ export function PermissionSelect({ : ( {label} - {badge} + {badge} ), ...icon === undefined ? {} : { icon }, @@ -186,7 +187,7 @@ export function PermissionSelect({ )} {currentLabel} {currentBadge !== undefined && ( - {currentBadge} + {currentBadge} )} diff --git a/packages/client/ui-permission-presets/src/client/locales.ts b/packages/client/ui-permission-presets/src/client/locales.ts index 96e0e01d0b..3754b8a07a 100644 --- a/packages/client/ui-permission-presets/src/client/locales.ts +++ b/packages/client/ui-permission-presets/src/client/locales.ts @@ -50,13 +50,13 @@ export const accessZh = { 'confirm.acknowledge': '我已了解风险,并愿意继续', 'confirm.cancel': '取消', 'confirm.enable': '启用完全权限', - 'auto.label': 'Auto review', + 'auto.label': '自动审查', 'auto.badge': 'EXP', 'auto.description': '无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。', - 'auto.confirm.title': '确认启用 Auto review(实验)?', - 'auto.confirm.description': 'Auto review 不使用沙箱。每次原生工具调用和 PTC 内层调用前,都会由与当前 agent 相同的模型进行审查;审查拒绝的调用由你批准或拒绝。此功能仍属实验性,可能误放行或误拒绝,并会消耗额外 token。', + 'auto.confirm.title': '确认启用自动审查(实验)?', + 'auto.confirm.description': '自动审查不使用沙箱。每次原生工具调用和 PTC 内层调用前,都会由与当前 agent 相同的模型进行审查;审查拒绝的调用由你批准或拒绝。此功能仍属实验性,可能误放行或误拒绝,并会消耗额外 token。', 'auto.confirm.acknowledge': '我已了解这些风险,并愿意继续', - 'auto.confirm.enable': '启用 Auto review', + 'auto.confirm.enable': '启用自动审查', } satisfies Record /** Current-session popup-gate key union. */ diff --git a/packages/client/ui-permission-presets/tests/browser-plugin.client.spec.ts b/packages/client/ui-permission-presets/tests/browser-plugin.client.spec.ts index 00f3fa5bf4..916f4d5fcf 100644 --- a/packages/client/ui-permission-presets/tests/browser-plugin.client.spec.ts +++ b/packages/client/ui-permission-presets/tests/browser-plugin.client.spec.ts @@ -225,7 +225,7 @@ describe('ui-permission browser plugin', () => { }) b.locale.setLocale('zh') const localized = await b.popup().options(proj, new AbortController().signal) - expect(localized.map(option => option.label)).toEqual(['仅可查看', '工作区内修改', '完全权限', 'Auto review']) + expect(localized.map(option => option.label)).toEqual(['仅可查看', '工作区内修改', '完全权限', '自动审查']) expect(localized.find(option => option.id === 'danger-full-access')?.confirmation).toEqual({ title: '确认启用完全权限?', description: accessZh['confirm.description'], diff --git a/packages/client/ui-permission-presets/tests/permission-select.client.spec.tsx b/packages/client/ui-permission-presets/tests/permission-select.client.spec.tsx index 7ea8cfe28c..ffc6bcda18 100644 --- a/packages/client/ui-permission-presets/tests/permission-select.client.spec.tsx +++ b/packages/client/ui-permission-presets/tests/permission-select.client.spec.tsx @@ -81,7 +81,7 @@ describe('PermissionSelect', () => { fireEvent.click(trigger()) expect(screen.getAllByRole('menuitem').map(item => item.textContent)) - .toEqual(['仅可查看', '工作区内修改', '完全权限', 'Auto reviewEXP']) + .toEqual(['仅可查看', '工作区内修改', '完全权限', '自动审查EXP']) fireEvent.click(screen.getByRole('menuitem', { name: '工作区内修改' })) expect(select).toHaveBeenCalledExactlyOnceWith('workspace-write') @@ -143,19 +143,22 @@ describe('PermissionSelect', () => { it('marks Auto experimental and uses the current-session risk copy', async () => { const { select, selection } = setup() fireEvent.click(trigger()) - fireEvent.click(screen.getByRole('menuitem', { name: 'Auto review EXP' })) + const autoOption = screen.getByRole('menuitem', { name: '自动审查 EXP' }) + expect(autoOption.querySelector('svg[aria-hidden="true"]')).not.toBeNull() + fireEvent.click(autoOption) - const dialog = screen.getByRole('dialog', { name: '确认启用 Auto review(实验)?' }) + const dialog = screen.getByRole('dialog', { name: '确认启用自动审查(实验)?' }) expect(dialog.textContent).toContain('不使用沙箱') expect(dialog.textContent).toContain('误放行或误拒绝') fireEvent.click(screen.getByRole('checkbox', { name: '我已了解这些风险,并愿意继续' })) - fireEvent.click(screen.getByRole('button', { name: '启用 Auto review' })) + fireEvent.click(screen.getByRole('button', { name: '启用自动审查' })) expect(select).toHaveBeenCalledExactlyOnceWith('auto') act(() => { selection.set({ value: { currentValue: 'auto' } }) }) await act(async () => {}) - expect(trigger().getAttribute('aria-label')).toBe('访问模式,当前:Auto review EXP') - expect(trigger().querySelector('sup')?.textContent).toBe('EXP') + expect(trigger().getAttribute('aria-label')).toBe('访问模式,当前:自动审查 EXP') + expect(trigger().textContent).toBe('自动审查EXP') + expect(trigger().querySelectorAll('svg[aria-hidden="true"]')).toHaveLength(2) expect(trigger().getAttribute('title')).toBe('无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。') }) @@ -186,7 +189,7 @@ describe('PermissionSelect', () => { const withoutAuto = { ...CATALOG, options: CATALOG.options.filter(option => option.value !== 'auto') } const chooseAuto = () => { fireEvent.click(trigger()) - fireEvent.click(screen.getByRole('menuitem', { name: 'Auto review EXP' })) + fireEvent.click(screen.getByRole('menuitem', { name: '自动审查 EXP' })) } try { chooseAuto() @@ -201,9 +204,9 @@ describe('PermissionSelect', () => { chooseAuto() expect(screen.getByRole('checkbox').checked).toBe(false) fireEvent.click(screen.getByRole('checkbox')) - fireEvent.click(screen.getByRole('button', { name: '启用 Auto review' })) + fireEvent.click(screen.getByRole('button', { name: '启用自动审查' })) expect(select).toHaveBeenCalledExactlyOnceWith('auto') - expect(trigger().textContent).toBe('Auto reviewEXP') + expect(trigger().textContent).toBe('自动审查EXP') act(() => { selection.set({ value: { currentValue: 'danger-full-access' } })