Merge remote-tracking branch 'origin/master' into turtle/omit-unneeded-invariants

This commit is contained in:
Turtle 2026-08-31 17:45:29 +08:00
commit 79e388547c
11 changed files with 19 additions and 19 deletions

View file

@ -50,7 +50,7 @@ describe('web e2e: Full access confirmation', () => {
const access = page.locator('button[aria-label^="访问模式"]').first() const access = page.locator('button[aria-label^="访问模式"]').first()
await access.waitFor({ timeout: 10_000 }) await access.waitFor({ timeout: 10_000 })
expect(await access.getAttribute('aria-label')).toBe('访问模式,当前:可写入工作区') expect(await access.getAttribute('aria-label')).toBe('访问模式,当前:工作区内修改')
await access.click() await access.click()
await page.getByRole('menuitem', { name: '完全权限' }).click() await page.getByRole('menuitem', { name: '完全权限' }).click()

View file

@ -18,8 +18,8 @@
- img - img
- text: 关闭 - text: 关闭
- text: 权限 选择新会话的默认权限模式 - text: 权限 选择新会话的默认权限模式
- button "可写入工作区": - button "工作区内修改":
- text: 可写入工作区 - text: 工作区内修改
- img - img
- text: 语言 - text: 语言
- button "中文": - button "中文":

View file

@ -62,7 +62,7 @@ describe('web e2e: settings modal and General preferences', () => {
expect(await trigger.getAttribute('aria-expanded')).toBe('true') expect(await trigger.getAttribute('aria-expanded')).toBe('true')
// General is active by default; Permission, Language and Appearance are functional. // General is active by default; Permission, Language and Appearance are functional.
expect(await dialog.getByRole('button', { name: '通用设置' }).getAttribute('aria-current')).toBe('true') expect(await dialog.getByRole('button', { name: '通用设置' }).getAttribute('aria-current')).toBe('true')
await dialog.getByRole('button', { name: '可写入工作区' }).waitFor({ timeout: 10_000 }) await dialog.getByRole('button', { name: '工作区内修改' }).waitFor({ timeout: 10_000 })
await expect.poll(() => dialog.getByText('语言', { exact: true }).count(), { timeout: 5_000 }).toBe(1) await expect.poll(() => dialog.getByText('语言', { exact: true }).count(), { timeout: 5_000 }).toBe(1)
await expect.poll(() => dialog.getByText('外观', { exact: true }).count(), { timeout: 5_000 }).toBe(1) await expect.poll(() => dialog.getByText('外观', { exact: true }).count(), { timeout: 5_000 }).toBe(1)
const openDocument = dialog.getByRole('button', { name: '打开配置文件' }) const openDocument = dialog.getByRole('button', { name: '打开配置文件' })
@ -150,7 +150,7 @@ describe('web e2e: settings modal and General preferences', () => {
await page.getByRole('button', { name: '设置', exact: true }).click() await page.getByRole('button', { name: '设置', exact: true }).click()
const dialog = page.getByRole('dialog', { name: '设置' }) const dialog = page.getByRole('dialog', { name: '设置' })
await dialog.waitFor({ timeout: 10_000 }) await dialog.waitFor({ timeout: 10_000 })
const selector = dialog.getByRole('button', { name: '可写入工作区' }) const selector = dialog.getByRole('button', { name: '工作区内修改' })
await selector.waitFor({ timeout: 10_000 }) await selector.waitFor({ timeout: 10_000 })
await expect.poll(() => selector.isEnabled(), { timeout: 5_000 }).toBe(true) await expect.poll(() => selector.isEnabled(), { timeout: 5_000 }).toBe(true)
await selector.click() await selector.click()

View file

@ -56,7 +56,7 @@ export const zh = {
'settings.enter.queue': '排队发送', 'settings.enter.queue': '排队发送',
'settings.enter.steer': '插话发送', 'settings.enter.steer': '插话发送',
'access.preset.readOnly': '仅可查看', 'access.preset.readOnly': '仅可查看',
'access.preset.workspaceWrite': '可写入工作区', 'access.preset.workspaceWrite': '工作区内修改',
'access.preset.fullAccess': '完全权限', 'access.preset.fullAccess': '完全权限',
'access.confirm.title': '确认启用完全权限?', 'access.confirm.title': '确认启用完全权限?',
'access.confirm.description': '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。', 'access.confirm.description': '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。',

View file

@ -1335,11 +1335,11 @@ describe('command launcher chrome and control seats', () => {
.every(icon => icon.closest('[aria-hidden="true"]') !== null)).toBe(true) .every(icon => icon.closest('[aria-hidden="true"]') !== null)).toBe(true)
fireEvent.click(trigger) fireEvent.click(trigger)
const items = view.getAllByRole('menuitem') const items = view.getAllByRole('menuitem')
expect(items.map(o => o.textContent)).toEqual(['仅可查看', '可写入工作区', '完全权限']) expect(items.map(o => o.textContent)).toEqual(['仅可查看', '工作区内修改', '完全权限'])
fireEvent.click(items[1]!) fireEvent.click(items[1]!)
// Optimistic pick + disable until admission resolves (command stub resolves true). // Optimistic pick + disable until admission resolves (command stub resolves true).
const busy = view.getByLabelText(/^访问模式/) as HTMLButtonElement const busy = view.getByLabelText(/^访问模式/) as HTMLButtonElement
expect(busy.textContent).toBe('可写入工作区') expect(busy.textContent).toBe('工作区内修改')
expect(busy.disabled).toBe(true) expect(busy.disabled).toBe(true)
expect(command).toHaveBeenCalledWith('/permission workspace-write') expect(command).toHaveBeenCalledWith('/permission workspace-write')
await act(async () => {}) await act(async () => {})
@ -1413,7 +1413,7 @@ describe('command launcher chrome and control seats', () => {
fireEvent.click(view.getByRole('checkbox')) fireEvent.click(view.getByRole('checkbox'))
fireEvent.click(view.getByRole('button', { name: '取消' })) fireEvent.click(view.getByRole('button', { name: '取消' }))
expect(command).not.toHaveBeenCalled() expect(command).not.toHaveBeenCalled()
expect((view.getByLabelText(/^访问模式/) as HTMLButtonElement).textContent).toBe('可写入工作区') expect((view.getByLabelText(/^访问模式/) as HTMLButtonElement).textContent).toBe('工作区内修改')
openConfirmation() openConfirmation()
expect((view.getByRole('checkbox') as HTMLInputElement).checked).toBe(false) expect((view.getByRole('checkbox') as HTMLInputElement).checked).toBe(false)

View file

@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority; # 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: # after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/client/ui-permission-presets/README.md # pnpm run verify-translation-pairing --write packages/client/ui-permission-presets/README.md
README.md: 7cdd371c85aef30d972cfa1371a255935a0ebd93 README.md: 9fa1d42f90478c00c06b23bc89ef212195b01dc2
README.zh.md: 48a4954ae63c3ac87e4b5a740e6d737d5012f7e2 README.zh.md: dee60ba44d7997a535d51f544993ecca9947e3eb

View file

@ -29,7 +29,7 @@ Mount this plugin alongside the settings and commands packages; the permission r
### The picker ### The picker
A pick submits the `/permission <preset>` command line. The argued path (`/permission <preset>` typed directly) still switches directly; the decoration replaces only the bare invocation. The built-in labels are `Read Only`, `Workspace Write`, and `Full access` in English and `仅可查看`, `可写入工作区`, and `完全权限` in Chinese; `custom` is display state, never a target. A pick submits the `/permission <preset>` command line. The argued path (`/permission <preset>` typed directly) still switches directly; the decoration replaces only the bare invocation. The built-in labels are `Read Only`, `Workspace Write`, and `Full access` in English and `仅可查看`, `工作区内修改`, and `完全权限` in Chinese; `custom` is display state, never a target.
### The Settings row ### The Settings row

View file

@ -29,7 +29,7 @@ kind: "package-reference"
### 选择器 ### 选择器
选中即提交 `/permission <preset>` 命令行。带参路径(直接键入 `/permission <preset>`)仍直接切换;装饰只替换裸调用。内置标签在英文界面中是 `Read Only`、`Workspace Write` 和 `Full access`,在中文界面中是「仅可查看」「可写入工作区」和「完全权限」;`custom` 只是显示状态,绝非目标。 选中即提交 `/permission <preset>` 命令行。带参路径(直接键入 `/permission <preset>`)仍直接切换;装饰只替换裸调用。内置标签在英文界面中是 `Read Only`、`Workspace Write` 和 `Full access`,在中文界面中是「仅可查看」「工作区内修改」和「完全权限」;`custom` 只是显示状态,绝非目标。
### 设置行 ### 设置行

View file

@ -7,7 +7,7 @@ export const zh = {
'loading': '加载中', 'loading': '加载中',
'unavailable': '不可用', 'unavailable': '不可用',
'preset.readOnly': '仅可查看', 'preset.readOnly': '仅可查看',
'preset.workspaceWrite': '可写入工作区', 'preset.workspaceWrite': '工作区内修改',
'preset.fullAccess': '完全权限', 'preset.fullAccess': '完全权限',
'confirm.title': '确认启用完全权限?', 'confirm.title': '确认启用完全权限?',
'confirm.description': '启用完全权限后,新会话将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任后续任务时使用。', 'confirm.description': '启用完全权限后,新会话将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任后续任务时使用。',
@ -38,7 +38,7 @@ export const en = {
/** Simplified Chinese dictionary for the current-session popup gate. */ /** Simplified Chinese dictionary for the current-session popup gate. */
export const accessZh = { export const accessZh = {
'preset.readOnly': '仅可查看', 'preset.readOnly': '仅可查看',
'preset.workspaceWrite': '可写入工作区', 'preset.workspaceWrite': '工作区内修改',
'preset.fullAccess': '完全权限', 'preset.fullAccess': '完全权限',
'confirm.title': '确认启用完全权限?', 'confirm.title': '确认启用完全权限?',
'confirm.description': '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。', 'confirm.description': '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。',

View file

@ -128,7 +128,7 @@ describe('ui-permission browser plugin', () => {
}) })
b.locale.setLocale('zh') b.locale.setLocale('zh')
const localized = await c.ui.options(proj, new AbortController().signal) const localized = await c.ui.options(proj, new AbortController().signal)
expect(localized.map(option => option.label)).toEqual(['仅可查看', '可写入工作区', '完全权限']) expect(localized.map(option => option.label)).toEqual(['仅可查看', '工作区内修改', '完全权限'])
expect(localized.find(option => option.id === 'danger-full-access')?.confirmation).toEqual({ expect(localized.find(option => option.id === 'danger-full-access')?.confirmation).toEqual({
title: '确认启用完全权限?', title: '确认启用完全权限?',
description: accessZh['confirm.description'], description: accessZh['confirm.description'],

View file

@ -94,8 +94,8 @@ describe('PermissionRow', () => {
fireEvent.click(screen.getByRole('menuitem', { name: '仅可查看' })) fireEvent.click(screen.getByRole('menuitem', { name: '仅可查看' }))
expect(mutate).not.toHaveBeenCalled() expect(mutate).not.toHaveBeenCalled()
fireEvent.click(button) fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: '可写入工作区' })) fireEvent.click(screen.getByRole('menuitem', { name: '工作区内修改' }))
await screen.findByRole('button', { name: '可写入工作区' }) await screen.findByRole('button', { name: '工作区内修改' })
expect(mutate).toHaveBeenCalledOnce() expect(mutate).toHaveBeenCalledOnce()
}) })
@ -166,7 +166,7 @@ describe('PermissionRow', () => {
describe.resolve(ok({ writable: true, hasDocument: false, namespaces: [view('read-only')] })) describe.resolve(ok({ writable: true, hasDocument: false, namespaces: [view('read-only')] }))
const button = await screen.findByRole('button', { name: '仅可查看' }) const button = await screen.findByRole('button', { name: '仅可查看' })
fireEvent.click(button) fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: '可写入工作区' })) fireEvent.click(screen.getByRole('menuitem', { name: '工作区内修改' }))
expect((await screen.findByRole('alert')).textContent).toBe('changed elsewhere') expect((await screen.findByRole('alert')).textContent).toBe('changed elsewhere')
}) })
}) })