fix(web): align and localize experimental permission mode
This commit is contained in:
1 parent
68d37a3755
commit
18fd3d06c4
12 files changed
+62
-56
No files matched your search
@@ -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' } })
|
||||
|
||||
Reference in new issue
Block a user