From 08a2fb0031ec7b9be25d35284e085b01b26be12e Mon Sep 17 00:00:00 2001 From: Haozhe Date: Mon, 31 Aug 2026 22:23:51 +0800 Subject: [PATCH] feat(cli): rename permission modes to Always Ask, Ask When Needed, and Never Ask (#3403) TUI copy for the three permission modes (manual/yolo/auto) now uses the new display names and descriptions across the /permission selector, footer badge, toggle notices, goal/swarm start prompts, session replay, and /status. The /yolo and /auto commands are renamed to /ask-when-needed and /never-ask, with the old names kept as aliases. --- apps/kimi-code/src/cli/commands.ts | 4 +-- apps/kimi-code/src/tui/commands/config.ts | 29 ++++++++++--------- apps/kimi-code/src/tui/commands/dispatch.ts | 4 +-- apps/kimi-code/src/tui/commands/registry.ts | 12 ++++---- .../src/tui/components/chrome/footer.ts | 7 +++-- .../dialogs/goal-start-permission-prompt.ts | 22 +++++++------- .../components/dialogs/permission-selector.ts | 15 ++++++---- .../dialogs/start-permission-prompt.ts | 4 +-- .../dialogs/swarm-start-permission-prompt.ts | 10 +++---- .../tui/components/messages/status-panel.ts | 3 +- apps/kimi-code/src/tui/constant/tips.ts | 4 +-- .../src/tui/controllers/session-replay.ts | 9 ++++-- .../src/tui/utils/permission-mode.ts | 7 +++++ apps/kimi-code/test/tui/commands/goal.test.ts | 8 ++--- .../test/tui/commands/registry.test.ts | 3 +- .../kimi-code/test/tui/commands/swarm.test.ts | 6 ++-- .../components/dialogs/approval-panel.test.ts | 4 +-- .../components/dialogs/choice-picker.test.ts | 2 +- .../components/messages/status-panel.test.ts | 2 +- .../test/tui/kimi-tui-message-flow.test.ts | 8 ++--- .../kimi-code/test/tui/message-replay.test.ts | 6 ++-- .../tui/reverse-rpc/approval-adapter.test.ts | 10 +++---- 22 files changed, 98 insertions(+), 81 deletions(-) create mode 100644 apps/kimi-code/src/tui/utils/permission-mode.ts diff --git a/apps/kimi-code/src/cli/commands.ts b/apps/kimi-code/src/cli/commands.ts index 6b6c3aca0..3326b562d 100644 --- a/apps/kimi-code/src/cli/commands.ts +++ b/apps/kimi-code/src/cli/commands.ts @@ -48,8 +48,8 @@ export function createProgram( ) .option('-c, --continue', 'Continue the previous session for the working directory.', false) .addOption(new Option('-C').hideHelp().default(false)) - .option('-y, --yolo', 'Auto-approve regular tool calls; the agent may still ask questions.', false) - .option('--auto', 'Start in auto permission mode: fully autonomous, the agent will not ask questions.', false) + .option('-y, --yolo', 'Start in Ask When Needed mode: routine edits and commands run automatically; risky actions, questions, and plans still ask.', false) + .option('--auto', 'Start in Never Ask mode: never interrupts you; everything runs and is decided automatically.', false) .addOption( new Option( '-m, --model ', diff --git a/apps/kimi-code/src/tui/commands/config.ts b/apps/kimi-code/src/tui/commands/config.ts index 003ec54b7..c90fd0cfe 100644 --- a/apps/kimi-code/src/tui/commands/config.ts +++ b/apps/kimi-code/src/tui/commands/config.ts @@ -26,6 +26,7 @@ import type { ThemeName } from '#/tui/theme'; import { currentTheme, isBuiltInTheme, lightColors, loadCustomThemeMerged } from '#/tui/theme'; import { NO_ACTIVE_SESSION_MESSAGE } from '../constant/kimi-tui'; import { formatErrorMessage } from '../utils/event-payload'; +import { PERMISSION_MODE_DISPLAY_NAMES } from '../utils/permission-mode'; import { thinkingEffortToConfig } from '../utils/thinking-config'; import { showUsage } from './info'; import { setExperimentalFeatures } from './experimental-flags'; @@ -139,23 +140,23 @@ export async function handleYoloCommand(host: SlashCommandHost, args: string): P if (subcmd === 'on') { if (currentMode === 'yolo') { - host.showNotice('YOLO mode is already on'); + host.showNotice('Ask When Needed mode is already on'); return; } await session?.setPermission('yolo'); host.setAppState({ permissionMode: 'yolo' }); - host.showNotice('YOLO mode: ON', 'Tool actions auto-approved; the agent may still ask you questions.'); + host.showNotice('Ask When Needed mode: ON', 'Routine edits and commands run automatically; risky actions, questions, and plans still ask.'); return; } if (subcmd === 'off') { if (currentMode !== 'yolo') { - host.showNotice('YOLO mode is already off'); + host.showNotice('Ask When Needed mode is already off'); return; } await session?.setPermission('manual'); host.setAppState({ permissionMode: 'manual' }); - host.showNotice('YOLO mode: OFF'); + host.showNotice('Ask When Needed mode: OFF'); return; } @@ -163,11 +164,11 @@ export async function handleYoloCommand(host: SlashCommandHost, args: string): P if (currentMode === 'yolo') { await session?.setPermission('manual'); host.setAppState({ permissionMode: 'manual' }); - host.showNotice('YOLO mode: OFF'); + host.showNotice('Ask When Needed mode: OFF'); } else { await session?.setPermission('yolo'); host.setAppState({ permissionMode: 'yolo' }); - host.showNotice('YOLO mode: ON', 'Tool actions auto-approved; the agent may still ask you questions.'); + host.showNotice('Ask When Needed mode: ON', 'Routine edits and commands run automatically; risky actions, questions, and plans still ask.'); } } @@ -185,23 +186,23 @@ export async function handleAutoCommand(host: SlashCommandHost, args: string): P if (subcmd === 'on') { if (currentMode === 'auto') { - host.showNotice('Auto mode is already on'); + host.showNotice('Never Ask mode is already on'); return; } await session?.setPermission('auto'); host.setAppState({ permissionMode: 'auto' }); - host.showNotice('Auto mode: ON', 'All actions auto-approved; the agent will not ask you questions.'); + host.showNotice('Never Ask mode: ON', 'Never interrupts you; everything runs and is decided automatically.'); return; } if (subcmd === 'off') { if (currentMode !== 'auto') { - host.showNotice('Auto mode is already off'); + host.showNotice('Never Ask mode is already off'); return; } await session?.setPermission('manual'); host.setAppState({ permissionMode: 'manual' }); - host.showNotice('Auto mode: OFF'); + host.showNotice('Never Ask mode: OFF'); return; } @@ -209,11 +210,11 @@ export async function handleAutoCommand(host: SlashCommandHost, args: string): P if (currentMode === 'auto') { await session?.setPermission('manual'); host.setAppState({ permissionMode: 'manual' }); - host.showNotice('Auto mode: OFF'); + host.showNotice('Never Ask mode: OFF'); } else { await session?.setPermission('auto'); host.setAppState({ permissionMode: 'auto' }); - host.showNotice('Auto mode: ON', 'All actions auto-approved; the agent will not ask you questions.'); + host.showNotice('Never Ask mode: ON', 'Never interrupts you; everything runs and is decided automatically.'); } } @@ -878,7 +879,7 @@ export async function applyUpdatePreferenceChoice( async function applyPermissionChoice(host: SlashCommandHost, mode: PermissionMode): Promise { if (mode === host.state.appState.permissionMode) { - host.showStatus(`Permission mode unchanged: ${mode}.`); + host.showStatus(`Permission mode unchanged: ${PERMISSION_MODE_DISPLAY_NAMES[mode]}.`); return; } @@ -898,7 +899,7 @@ async function applyPermissionChoice(host: SlashCommandHost, mode: PermissionMod } host.setAppState({ permissionMode: mode }); - host.showNotice(`Permission mode: ${mode}`); + host.showNotice(`Permission mode: ${PERMISSION_MODE_DISPLAY_NAMES[mode]}`); } export function showSettingsSelector(host: SlashCommandHost): void { diff --git a/apps/kimi-code/src/tui/commands/dispatch.ts b/apps/kimi-code/src/tui/commands/dispatch.ts index 05a692d39..afe3b88be 100644 --- a/apps/kimi-code/src/tui/commands/dispatch.ts +++ b/apps/kimi-code/src/tui/commands/dispatch.ts @@ -565,10 +565,10 @@ async function handleBuiltInSlashCommand( case 'title': await handleTitleCommand(host, args); return; - case 'yolo': + case 'ask-when-needed': await handleYoloCommand(host, args); return; - case 'auto': + case 'never-ask': await handleAutoCommand(host, args); return; case 'plan': diff --git a/apps/kimi-code/src/tui/commands/registry.ts b/apps/kimi-code/src/tui/commands/registry.ts index cf0b47e3d..c75f3260f 100644 --- a/apps/kimi-code/src/tui/commands/registry.ts +++ b/apps/kimi-code/src/tui/commands/registry.ts @@ -146,16 +146,16 @@ function formatDirectoryCompletionValue(argumentPrefix: string, parentInput: str export const BUILTIN_SLASH_COMMANDS = [ { - name: 'yolo', - aliases: ['yes'], - description: 'Toggle YOLO mode: auto-approve tool actions, but the agent may still ask questions.', + name: 'ask-when-needed', + aliases: ['yolo', 'yes'], + description: 'Toggle Ask When Needed mode: routine edits and commands run automatically; risky actions, questions, and plans still ask.', priority: 101, availability: 'always', }, { - name: 'auto', - aliases: [], - description: 'Toggle Auto mode: fully autonomous, but dangerous commands are blocked.', + name: 'never-ask', + aliases: ['auto'], + description: 'Toggle Never Ask mode: never interrupts you; everything runs and is decided automatically.', priority: 99, availability: 'always', }, diff --git a/apps/kimi-code/src/tui/components/chrome/footer.ts b/apps/kimi-code/src/tui/components/chrome/footer.ts index 4619c4468..ae39f4023 100644 --- a/apps/kimi-code/src/tui/components/chrome/footer.ts +++ b/apps/kimi-code/src/tui/components/chrome/footer.ts @@ -2,7 +2,7 @@ * Footer/status bar — multi-line status display at the bottom of the TUI. * * Layout: - * Line 1: [yolo] [plan] + * Line 1: [ask-when-needed] [plan] * Line 2: context: N% (tokens/max) */ @@ -16,6 +16,7 @@ import { isRainbowDancing, renderDanceFooterModel } from '#/tui/easter-eggs/danc import { currentTheme } from '#/tui/theme'; import type { ColorPalette } from '#/tui/theme/colors'; import type { AppState } from '#/tui/types'; +import { PERMISSION_MODE_DISPLAY_NAMES } from '#/tui/utils/permission-mode'; import { StatusLineCommandRunner, type StatusLinePayload, @@ -387,8 +388,8 @@ export class FooterComponent implements Component { } const modes: string[] = []; - if (state.permissionMode === 'auto') modes.push(chalk.hex(colors.warning).bold('auto')); - if (state.permissionMode === 'yolo') modes.push(chalk.hex(colors.warning).bold('yolo')); + if (state.permissionMode === 'auto') modes.push(chalk.hex(colors.warning).bold(PERMISSION_MODE_DISPLAY_NAMES.auto)); + if (state.permissionMode === 'yolo') modes.push(chalk.hex(colors.warning).bold(PERMISSION_MODE_DISPLAY_NAMES.yolo)); if (state.planMode) modes.push(chalk.hex(colors.primary).bold('plan')); if (state.swarmMode) modes.push(chalk.hex(colors.accent).bold('swarm')); if (state.towerMode) modes.push(chalk.hex(colors.accent).bold('tower')); diff --git a/apps/kimi-code/src/tui/components/dialogs/goal-start-permission-prompt.ts b/apps/kimi-code/src/tui/components/dialogs/goal-start-permission-prompt.ts index e60d85ce0..873dcc2e6 100644 --- a/apps/kimi-code/src/tui/components/dialogs/goal-start-permission-prompt.ts +++ b/apps/kimi-code/src/tui/components/dialogs/goal-start-permission-prompt.ts @@ -14,19 +14,19 @@ export interface GoalStartPermissionPromptOptions { export const GOAL_START_MANUAL_OPTIONS: readonly StartPermissionOption[] = [ { value: 'auto', - label: 'Switch to Auto and start', + label: 'Switch to Never Ask and start', description: 'Best if you want Kimi Code to keep working while you are away. Tools are approved automatically, and questions are skipped.', }, { value: 'yolo', - label: 'Switch to YOLO and start', + label: 'Switch to Ask When Needed and start', description: 'Tools and plan changes are approved automatically. Kimi Code may still ask you questions.', }, { value: 'manual', - label: 'Start in Manual', + label: 'Start in Always Ask', description: 'Keep approvals on. Kimi Code will ask before risky actions, so the goal may stop and wait for you.', }, @@ -40,13 +40,13 @@ export const GOAL_START_MANUAL_OPTIONS: readonly StartPermissionOption[] = [ export const GOAL_START_YOLO_OPTIONS: readonly StartPermissionOption[] = [ { value: 'auto', - label: 'Switch to Auto and start', + label: 'Switch to Never Ask and start', description: 'Best if you want Kimi Code to keep working while you are away. Tools are approved automatically, and questions are skipped.', }, { value: 'yolo', - label: 'Keep YOLO and start', + label: 'Keep Ask When Needed and start', description: 'Tools and plan changes stay approved automatically. Kimi Code may still ask you questions.', }, @@ -66,15 +66,15 @@ const MANUAL_OPTIONS = GOAL_START_MANUAL_OPTIONS; const YOLO_OPTIONS = GOAL_START_YOLO_OPTIONS; const MANUAL_NOTICE_LINES = [ - 'Manual mode asks you before Kimi Code runs commands, edits files, or takes other risky actions.', - 'Manual mode is not suitable for unattended goal work.', + 'Always Ask mode asks you before Kimi Code runs commands, edits files, or takes other risky actions.', + 'Always Ask mode is not suitable for unattended goal work.', 'You can go back without losing your command.', ] as const; const YOLO_NOTICE_LINES = [ - 'YOLO mode approves tools and plan changes automatically.', - 'YOLO mode can still stop for questions.', - 'Switch to Auto if you want questions skipped during goal work.', + 'Ask When Needed mode approves tools and plan changes automatically.', + 'Ask When Needed mode can still stop for questions.', + 'Switch to Never Ask if you want questions skipped during goal work.', ] as const; export class GoalStartPermissionPromptComponent extends StartPermissionPromptComponent { @@ -82,7 +82,7 @@ export class GoalStartPermissionPromptComponent extends StartPermissionPromptCom super({ title: opts.mode === 'yolo' - ? 'Start a goal in YOLO mode?' + ? 'Start a goal in Ask When Needed mode?' : 'Start a goal with approvals on?', noticeLines: opts.mode === 'yolo' ? YOLO_NOTICE_LINES : MANUAL_NOTICE_LINES, options: opts.mode === 'yolo' ? YOLO_OPTIONS : MANUAL_OPTIONS, diff --git a/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts b/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts index c1672454c..a212c4eaf 100644 --- a/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts +++ b/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts @@ -1,22 +1,25 @@ import type { PermissionMode } from '@moonshot-ai/kimi-code-sdk'; +import { PERMISSION_MODE_DISPLAY_NAMES } from '#/tui/utils/permission-mode'; + import { ChoicePickerComponent, type ChoiceOption } from './choice-picker'; const PERMISSION_OPTIONS: readonly ChoiceOption[] = [ { value: 'manual', - label: 'Manual', - description: 'Approve every action yourself.', + label: PERMISSION_MODE_DISPLAY_NAMES.manual, + description: 'Auto-read only; everything else needs your approval first.', }, { value: 'yolo', - label: 'YOLO', - description: 'Auto-approve tool actions, but the agent may still ask questions.', + label: PERMISSION_MODE_DISPLAY_NAMES.yolo, + description: + 'Routine edits and commands run automatically; risky actions, questions, and plans still ask.', }, { value: 'auto', - label: 'Auto', - description: 'Fully autonomous, but dangerous commands are blocked.', + label: PERMISSION_MODE_DISPLAY_NAMES.auto, + description: 'Never interrupts you; everything runs and is decided automatically.', }, ]; diff --git a/apps/kimi-code/src/tui/components/dialogs/start-permission-prompt.ts b/apps/kimi-code/src/tui/components/dialogs/start-permission-prompt.ts index 341ced723..9b8487d90 100644 --- a/apps/kimi-code/src/tui/components/dialogs/start-permission-prompt.ts +++ b/apps/kimi-code/src/tui/components/dialogs/start-permission-prompt.ts @@ -99,9 +99,9 @@ function styleLabel(label: string, selected: boolean): string { function styleModeNames(text: string, baseToken: 'text' | 'textMuted'): string { return text - .split(/(\b(?:Manual|Auto|YOLO)\b)/g) + .split(/(\b(?:Always Ask|Ask When Needed|Never Ask)\b)/g) .map((part) => { - if (part === 'Manual' || part === 'Auto' || part === 'YOLO') return currentTheme.boldFg('textStrong', part); + if (part === 'Always Ask' || part === 'Ask When Needed' || part === 'Never Ask') return currentTheme.boldFg('textStrong', part); return currentTheme.fg(baseToken, part); }) .join(''); diff --git a/apps/kimi-code/src/tui/components/dialogs/swarm-start-permission-prompt.ts b/apps/kimi-code/src/tui/components/dialogs/swarm-start-permission-prompt.ts index 694c0c0e6..b0dd63072 100644 --- a/apps/kimi-code/src/tui/components/dialogs/swarm-start-permission-prompt.ts +++ b/apps/kimi-code/src/tui/components/dialogs/swarm-start-permission-prompt.ts @@ -13,27 +13,27 @@ export interface SwarmStartPermissionPromptOptions { const OPTIONS: readonly StartPermissionOption[] = [ { value: 'auto', - label: 'Switch to Auto and start', + label: 'Switch to Never Ask and start', description: 'Best for swarm tasks. Tools are approved automatically, and questions are skipped.', }, { value: 'yolo', - label: 'Switch to YOLO and start', + label: 'Switch to Ask When Needed and start', description: 'Tools and plan changes are approved automatically. Kimi Code may still ask you questions.', }, { value: 'manual', - label: 'Start in Manual', + label: 'Start in Always Ask', description: 'Keep approvals on. Kimi Code may stop and wait for you during the swarm task.', }, ]; const NOTICE_LINES = [ - 'Manual mode asks you before Kimi Code runs commands, edits files, or takes other risky actions.', - 'Manual mode can block swarm work while agents are running.', + 'Always Ask mode asks you before Kimi Code runs commands, edits files, or takes other risky actions.', + 'Always Ask mode can block swarm work while agents are running.', 'You can go back without losing your command.', ] as const; diff --git a/apps/kimi-code/src/tui/components/messages/status-panel.ts b/apps/kimi-code/src/tui/components/messages/status-panel.ts index dfd1cf8d0..08058fe87 100644 --- a/apps/kimi-code/src/tui/components/messages/status-panel.ts +++ b/apps/kimi-code/src/tui/components/messages/status-panel.ts @@ -15,6 +15,7 @@ import { import { PRODUCT_NAME } from '#/constant/app'; import { currentTheme } from '#/tui/theme'; +import { PERMISSION_MODE_DISPLAY_NAMES } from '#/tui/utils/permission-mode'; import { formatTokenCount, ratioSeverity, @@ -114,7 +115,7 @@ export function buildStatusReportLines(options: StatusReportOptions): string[] { const rows: FieldRow[] = [ { label: 'Model', value: formatModelStatus(options) }, { label: 'Directory', value: options.workDir }, - { label: 'Permissions', value: permission }, + { label: 'Permissions', value: PERMISSION_MODE_DISPLAY_NAMES[permission] }, { label: 'Plan mode', value: planMode ? 'on' : 'off' }, ]; if (options.towerAvailable) { diff --git a/apps/kimi-code/src/tui/constant/tips.ts b/apps/kimi-code/src/tui/constant/tips.ts index a235ab6ce..1cb35a95b 100644 --- a/apps/kimi-code/src/tui/constant/tips.ts +++ b/apps/kimi-code/src/tui/constant/tips.ts @@ -39,8 +39,8 @@ export const ALL_TIPS: readonly ToolbarTip[] = [ { text: 'shift+enter: newline' }, { text: 'ctrl+c: cancel' }, { text: '/theme to switch the terminal UI theme' }, - { text: '/auto when you want Kimi to handle approvals and keep going unattended' }, - { text: '/yolo to skip most approvals for trusted batch work, only use it in repos you trust' }, + { text: '/never-ask when you want Kimi to handle approvals and keep going unattended' }, + { text: '/ask-when-needed to skip most approvals for trusted batch work, only use it in repos you trust' }, { text: '/help: show commands' }, { text: '/compact compresses context when it gets long', priority: 2 }, { text: 'ctrl-o to hide or reveal tool output switching between a clean chat view and full execution details', priority: 2 }, diff --git a/apps/kimi-code/src/tui/controllers/session-replay.ts b/apps/kimi-code/src/tui/controllers/session-replay.ts index ca9980657..542cd6b3a 100644 --- a/apps/kimi-code/src/tui/controllers/session-replay.ts +++ b/apps/kimi-code/src/tui/controllers/session-replay.ts @@ -24,6 +24,7 @@ import { formatBackgroundAgentTranscript } from '../utils/background-agent-statu import { formatBackgroundTaskTranscript } from '../utils/background-task-status'; import { modelDisplayName } from '../components/dialogs/model-selector'; import { buildGoalCompletionMessage } from '../utils/goal-completion'; +import { PERMISSION_MODE_DISPLAY_NAMES } from '../utils/permission-mode'; import { formatBashOutputForDisplay } from '../utils/shell-output'; import { markTranscriptComponent } from '../utils/transcript-component-metadata'; import { @@ -684,8 +685,8 @@ export class SessionReplayRenderer { private renderPermissionUpdate(context: ReplayRenderContext, mode: PermissionMode): void { if (mode === 'yolo') { this.host.appendTranscriptEntry( - replayEntry(context, 'status', 'YOLO mode: ON', 'notice', { - detail: 'Tool actions auto-approved; the agent may still ask you questions.', + replayEntry(context, 'status', 'Ask When Needed mode: ON', 'notice', { + detail: 'Routine edits and commands run automatically; risky actions, questions, and plans still ask.', }), ); return; @@ -694,7 +695,9 @@ export class SessionReplayRenderer { replayEntry( context, 'status', - mode === 'manual' ? 'YOLO mode: OFF' : `Permission mode: ${mode}`, + mode === 'manual' + ? 'Ask When Needed mode: OFF' + : `Permission mode: ${PERMISSION_MODE_DISPLAY_NAMES[mode]}`, 'notice', ), ); diff --git a/apps/kimi-code/src/tui/utils/permission-mode.ts b/apps/kimi-code/src/tui/utils/permission-mode.ts new file mode 100644 index 000000000..9adec2637 --- /dev/null +++ b/apps/kimi-code/src/tui/utils/permission-mode.ts @@ -0,0 +1,7 @@ +import type { PermissionMode } from '@moonshot-ai/kimi-code-sdk'; + +export const PERMISSION_MODE_DISPLAY_NAMES: Readonly> = { + manual: 'Always Ask', + yolo: 'Ask When Needed', + auto: 'Never Ask', +}; diff --git a/apps/kimi-code/test/tui/commands/goal.test.ts b/apps/kimi-code/test/tui/commands/goal.test.ts index d9c4a5d34..262e2a281 100644 --- a/apps/kimi-code/test/tui/commands/goal.test.ts +++ b/apps/kimi-code/test/tui/commands/goal.test.ts @@ -358,7 +358,7 @@ describe('handleGoalCommand', () => { expect(s.createGoal).not.toHaveBeenCalled(); expect(manualHost.sendNormalUserInput).not.toHaveBeenCalled(); const text = stripAnsi(mountedPicker(manualHost).render(80).join('\n')); - expect(text).toContain('Manual mode is not suitable for unattended goal work'); + expect(text).toContain('Always Ask mode is not suitable for unattended goal work'); expect(text).toContain('Return to the input box with your goal command'); }); @@ -466,9 +466,9 @@ describe('handleGoalCommand', () => { expect(s.createGoal).not.toHaveBeenCalled(); expect(yoloHost.sendNormalUserInput).not.toHaveBeenCalled(); const text = stripAnsi(mountedPicker(yoloHost).render(80).join('\n')); - expect(text).toContain('YOLO mode can still stop for questions'); - expect(text).toContain('Keep YOLO and start'); - expect(text).not.toContain('Start in Manual'); + expect(text).toContain('Ask When Needed mode can still stop for questions'); + expect(text).toContain('Keep Ask When Needed and start'); + expect(text).not.toContain('Start in Always Ask'); }); it('defaults to Auto when confirming a YOLO-mode goal start', async () => { diff --git a/apps/kimi-code/test/tui/commands/registry.test.ts b/apps/kimi-code/test/tui/commands/registry.test.ts index 1113a5998..dbf44ec5e 100644 --- a/apps/kimi-code/test/tui/commands/registry.test.ts +++ b/apps/kimi-code/test/tui/commands/registry.test.ts @@ -194,7 +194,8 @@ describe('built-in slash command registry', () => { 'undo', 'usage', 'version', - 'yolo', + 'ask-when-needed', + 'never-ask', ]), ); }); diff --git a/apps/kimi-code/test/tui/commands/swarm.test.ts b/apps/kimi-code/test/tui/commands/swarm.test.ts index 3e3c9b11a..a4d00ea30 100644 --- a/apps/kimi-code/test/tui/commands/swarm.test.ts +++ b/apps/kimi-code/test/tui/commands/swarm.test.ts @@ -122,7 +122,7 @@ describe('handleSwarmCommand', () => { expect(session.setPermission).not.toHaveBeenCalled(); expect(host.sendNormalUserInput).not.toHaveBeenCalled(); const text = stripAnsi(mountedPicker(host).render(80).join('\n')); - expect(text).toContain('Manual mode can block swarm work'); + expect(text).toContain('Always Ask mode can block swarm work'); mountedPicker(host).handleInput(ENTER); await vi.waitFor(() => { @@ -213,8 +213,8 @@ describe('handleSwarmCommand', () => { expect(session.setPermission).not.toHaveBeenCalled(); expect(host.sendNormalUserInput).not.toHaveBeenCalled(); const text = stripAnsi(mountedPicker(host).render(80).join('\n')); - expect(text).toContain('Manual mode can block swarm work'); - expect(text).toContain('Switch to YOLO and start'); + expect(text).toContain('Always Ask mode can block swarm work'); + expect(text).toContain('Switch to Ask When Needed and start'); expect(text).not.toContain('Do not start'); }); diff --git a/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts b/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts index d02df500e..16d031131 100644 --- a/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts +++ b/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts @@ -72,7 +72,7 @@ describe('ApprovalPanelComponent', () => { display: [], choices: [ { - label: 'Switch to Auto and start', + label: 'Switch to Never Ask and start', response: 'approved', selected_label: 'auto', description: 'Tools are approved automatically, and questions are skipped.', @@ -82,7 +82,7 @@ describe('ApprovalPanelComponent', () => { }, }; const out = strip(new ApprovalPanelComponent(pending, () => {}).render(80).join('\n')); - expect(out).toContain('1. Switch to Auto and start'); + expect(out).toContain('1. Switch to Never Ask and start'); expect(out).toContain('Tools are approved automatically, and questions are skipped.'); // A choice without a description stays label-only — no stray blank helper line. expect(out).toContain('2. Do not start'); diff --git a/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts b/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts index ec590e252..ac4e843c5 100644 --- a/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts +++ b/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts @@ -95,7 +95,7 @@ describe('ChoicePickerComponent', () => { onSelect, onCancel, }); - expect(permission.render(120).map(strip)).toContain(' ❯ Manual ← current'); + expect(permission.render(120).map(strip)).toContain(' ❯ Always Ask ← current'); const settings = new SettingsSelectorComponent({ onSelect, diff --git a/apps/kimi-code/test/tui/components/messages/status-panel.test.ts b/apps/kimi-code/test/tui/components/messages/status-panel.test.ts index fd534ab85..215f7cd5e 100644 --- a/apps/kimi-code/test/tui/components/messages/status-panel.test.ts +++ b/apps/kimi-code/test/tui/components/messages/status-panel.test.ts @@ -56,7 +56,7 @@ describe('status panel report lines', () => { expect(output).toContain('>_ Kimi Code (v1.2.3)'); expect(output).toContain('Model Kimi K2 (thinking high)'); expect(output).toContain('Directory /tmp/project'); - expect(output).toContain('Permissions auto'); + expect(output).toContain('Permissions Never Ask'); expect(output).toContain('Plan mode on'); expect(output).toContain('Session ses-1'); expect(output).toContain('Title Implement status'); diff --git a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts index 1368610d4..0be3b47c4 100644 --- a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts +++ b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts @@ -2613,7 +2613,7 @@ command = "vim" expect(driver.state.appState).toMatchObject({ permissionMode: 'yolo', }); - expect(harness.track).toHaveBeenCalledWith('input_command', { command: 'yolo' }); + expect(harness.track).toHaveBeenCalledWith('input_command', { command: 'ask-when-needed' }); expect(harness.track).not.toHaveBeenCalledWith('yolo_toggle', expect.anything()); }); @@ -2835,7 +2835,7 @@ command = "vim" driver.handleUserInput('/auto on'); await vi.waitFor(() => { - expect(stripSgr(renderTranscript(driver))).toContain('Auto mode: ON'); + expect(stripSgr(renderTranscript(driver))).toContain('Never Ask mode: ON'); }); driver.handleUserInput('/undo 10'); @@ -2855,7 +2855,7 @@ command = "vim" const transcript = stripSgr(renderTranscript(driver)); expect(transcript).not.toContain('hello'); expect(transcript).not.toContain('Cannot undo 10 prompts'); - expect(transcript).toContain('Auto mode: ON'); + expect(transcript).toContain('Never Ask mode: ON'); expect(driver.state.appState.permissionMode).toBe('auto'); }); @@ -6778,7 +6778,7 @@ command = "vim" expect(output).toContain('>_ Kimi Code'); expect(output).toContain('Model'); expect(output).toContain('thinking high'); - expect(output).toContain('Permissions auto'); + expect(output).toContain('Permissions Never Ask'); expect(output).toContain('Plan mode on'); expect(output).toContain('Context window'); expect(output).toContain('25%'); diff --git a/apps/kimi-code/test/tui/message-replay.test.ts b/apps/kimi-code/test/tui/message-replay.test.ts index 57ca82ea8..77fdeb6fe 100644 --- a/apps/kimi-code/test/tui/message-replay.test.ts +++ b/apps/kimi-code/test/tui/message-replay.test.ts @@ -1321,9 +1321,9 @@ describe('KimiTUI resume message replay', () => { const transcript = driver.state.transcriptContainer.render(120).join('\n'); expect(transcript).toContain('Plan mode: ON'); - expect(transcript).toContain('Permission mode: auto'); - expect(transcript).toContain('YOLO mode: ON'); - expect(transcript).toContain('YOLO mode: OFF'); + expect(transcript).toContain('Permission mode: Never Ask'); + expect(transcript).toContain('Ask When Needed mode: ON'); + expect(transcript).toContain('Ask When Needed mode: OFF'); expect(transcript).toContain('Approved for session: run command'); expect(transcript).toContain('Plan mode: OFF'); }); diff --git a/apps/kimi-code/test/tui/reverse-rpc/approval-adapter.test.ts b/apps/kimi-code/test/tui/reverse-rpc/approval-adapter.test.ts index cdc8709c3..ad29fb1c0 100644 --- a/apps/kimi-code/test/tui/reverse-rpc/approval-adapter.test.ts +++ b/apps/kimi-code/test/tui/reverse-rpc/approval-adapter.test.ts @@ -236,21 +236,21 @@ describe('approval adapter', () => { // /goal menu's description. expect(adapted.choices).toEqual([ { - label: 'Switch to Auto and start', + label: 'Switch to Never Ask and start', response: 'approved', selected_label: 'auto', description: 'Best if you want Kimi Code to keep working while you are away. Tools are approved automatically, and questions are skipped.', }, { - label: 'Switch to YOLO and start', + label: 'Switch to Ask When Needed and start', response: 'approved', selected_label: 'yolo', description: 'Tools and plan changes are approved automatically. Kimi Code may still ask you questions.', }, { - label: 'Start in Manual', + label: 'Start in Always Ask', response: 'approved', selected_label: 'manual', description: @@ -280,14 +280,14 @@ describe('approval adapter', () => { expect(adapted.display).toEqual([{ type: 'brief', text: 'Start goal: Ship the feature' }]); expect(adapted.choices).toEqual([ { - label: 'Switch to Auto and start', + label: 'Switch to Never Ask and start', response: 'approved', selected_label: 'auto', description: 'Best if you want Kimi Code to keep working while you are away. Tools are approved automatically, and questions are skipped.', }, { - label: 'Keep YOLO and start', + label: 'Keep Ask When Needed and start', response: 'approved', selected_label: 'yolo', description: