fix(web): align and localize experimental permission mode

This commit is contained in:
Turtle committed 2026-10-09 11:42:28 +08:00
1 parent 68d37a3755
commit 18fd3d06c4
12 files changed
+62 -56

No files matched your search

+21 -15
View File
@@ -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')
})
})
@@ -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]
@@ -2,6 +2,4 @@
- menuitem "仅可查看"
- menuitem "工作区内修改"
- menuitem "完全权限"
- menuitem "Auto review EXP":
- text: Auto review
- superscript: EXP
- menuitem "自动审查 EXP"
@@ -4,7 +4,7 @@
- option "仅可查看"
- option "工作区内修改" [selected]
- option "完全权限"
- option "Auto review EXP":
- text: Auto review
- option "自动审查 EXP":
- text: 自动审查
- superscript: EXP
- text: 无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。
@@ -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
@@ -29,7 +29,7 @@ Mount this plugin alongside the settings, commands, and conversation packages. G
### The picker
A pick submits the `/permission <preset>` command line. The argument-bearing form (`/permission <preset>` 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 <preset>` command line. The argument-bearing form (`/permission <preset>` 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.
@@ -9,7 +9,7 @@ kind: "package-reference"
## 概述
为当前 Web 会话或未来会话选择权限预设。通用设置行只更改之后创建会话所用的默认值;composer 与 `/permission` 选择器切换当前会话。默认 Web 提供仅可查看、工作区内修改与完全权限。显式加载实验 Auto integration 后,当前会话选择器会增加带 `EXP` 标记的 Auto review。通过可见选项选择完全权限或 Auto 时,需要分别确认对应风险;完整的 `/permission <preset>` 命令直接执行。宿主通过 Session 投影确认每次变更。
为当前 Web 会话或未来会话选择权限预设。通用设置行只更改之后创建会话所用的默认值;composer 与 `/permission` 选择器切换当前会话。默认 Web 提供仅可查看、工作区内修改与完全权限。显式加载实验 Auto integration 后,当前会话选择器会增加带 `EXP` 标记的自动审查。通过可见选项选择完全权限或 Auto 时,需要分别确认对应风险;完整的 `/permission <preset>` 命令直接执行。宿主通过 Session 投影确认每次变更。
## 目录
@@ -29,7 +29,7 @@ kind: "package-reference"
### 选择器
选中即提交 `/permission <preset>` 命令行。带参形式(直接键入 `/permission <preset>`)仍直接切换;装饰只替换裸调用。内置标签在英文界面中是 `Read Only`、`Workspace Write`、`Full access` 和 `Auto review`,在中文界面中是「仅可查看」「工作区内修改」「完全权限」和 `Auto review`。显式 host 标签保持原样,未知 kebab-case 名称渲染为 Title Case;`auto` 带有 `EXP` badge,并在可见选择时要求实验风险确认。`custom` 只是显示状态,绝非目标。
选中即提交 `/permission <preset>` 命令行。带参形式(直接键入 `/permission <preset>`)仍直接切换;装饰只替换裸调用。内置标签在英文界面中是 `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"
<details>
<summary>实现细节——点击展开</summary>
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。
</details>
@@ -80,7 +80,7 @@ General Settings 行经 `ctx.configForms` 读取显式暴露的 `permission` Set
这些限制界定了当前权限界面。它们是当前包约束,不是通用策略对比或任务积压。
- **设置行仅限 Web**——非 Web 客户端仍可经 `/permission` 切换当前会话,但不会获得这项浏览器贡献。
- **Auto review 仅限当前会话**——General Settings 行有意省略它,且只有通过可见选择器选择时才显示实验确认;显式键入 `/permission auto` 已经构成明确同意。
- **自动审查仅限当前会话**——General Settings 行有意省略它,且只有通过可见选择器选择时才显示实验确认;显式键入 `/permission auto` 已经构成明确同意。
- **预设描述来自宿主**——本地化的内置标签旁边可能显示另一种语言编写的描述。
<a id="dev-note"></a>
@@ -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 —
@@ -29,6 +29,7 @@ const permissionGlyphs = new Map<string, ReactNode>([
['read-only', <PermissionIconReadOnlyRegular />],
['workspace-write', <PermissionIconWorkspaceWriteRegular />],
[FULL_ACCESS, <PermissionIconFullAccessRegular />],
[AUTO_REVIEW, <PermissionIconFullAccessRegular />],
])
/** Glyph for a permission option value; host-configured names outside the design set get none. */
@@ -112,7 +113,7 @@ export function PermissionSelect({
: (
<span className={css.optionLabel} aria-label={`${label} ${badge}`}>
<span className={css.optionLabelText}>{label}</span>
<sup className={css.badge}>{badge}</sup>
<span className={css.badge}>{badge}</span>
</span>
),
...icon === undefined ? {} : { icon },
@@ -186,7 +187,7 @@ export function PermissionSelect({
)}
<span className={css.triggerLabel}>{currentLabel}</span>
{currentBadge !== undefined && (
<sup className={css.badge}>{currentBadge}</sup>
<span className={css.badge}>{currentBadge}</span>
)}
<span className={clsx(css.chevron, open && css.chevronOpen)} aria-hidden>
<IconChevronDownOutlineRegular />
@@ -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<string, string>
/** Current-session popup-gate key union. */
@@ -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'],
@@ -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<HTMLInputElement>('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' } })