mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 15:31:27 +00:00
feat(cli): add direct argument support for /approval-mode command
Allow users to set approval mode directly via argument instead of opening the dialog. For example: - /approval-mode plan - /approval-mode yolo - /approval-mode auto-edit - /approval-mode default If no argument is provided, the dialog opens as before. If an invalid argument is provided, an error message shows valid options. Also adds tab completion for mode arguments. Fixes #1353
This commit is contained in:
parent
b95d9a8d2d
commit
8fcdd86b91
5 changed files with 246 additions and 14 deletions
|
|
@ -4,29 +4,34 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { approvalModeCommand } from './approvalModeCommand.js';
|
||||
import {
|
||||
type CommandContext,
|
||||
CommandKind,
|
||||
type OpenDialogActionReturn,
|
||||
type MessageActionReturn,
|
||||
} from './types.js';
|
||||
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
|
||||
import type { LoadedSettings } from '../../config/settings.js';
|
||||
|
||||
describe('approvalModeCommand', () => {
|
||||
let mockContext: CommandContext;
|
||||
let mockSetValue: ReturnType<typeof vi.fn>;
|
||||
let mockSetApprovalMode: ReturnType<typeof vi.fn>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockSetValue = vi.fn();
|
||||
mockSetApprovalMode = vi.fn();
|
||||
mockContext = createMockCommandContext({
|
||||
services: {
|
||||
config: {
|
||||
getApprovalMode: () => 'default',
|
||||
setApprovalMode: () => {},
|
||||
setApprovalMode: mockSetApprovalMode,
|
||||
},
|
||||
settings: {
|
||||
merged: {},
|
||||
setValue: () => {},
|
||||
merged: { tools: { approvalMode: 'default' } },
|
||||
setValue: mockSetValue,
|
||||
forScope: () => ({}),
|
||||
} as unknown as LoadedSettings,
|
||||
},
|
||||
|
|
@ -41,7 +46,7 @@ describe('approvalModeCommand', () => {
|
|||
expect(approvalModeCommand.kind).toBe(CommandKind.BUILT_IN);
|
||||
});
|
||||
|
||||
it('should open approval mode dialog when invoked', async () => {
|
||||
it('should open approval mode dialog when invoked without arguments', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'',
|
||||
|
|
@ -51,21 +56,177 @@ describe('approvalModeCommand', () => {
|
|||
expect(result.dialog).toBe('approval-mode');
|
||||
});
|
||||
|
||||
it('should open approval mode dialog with arguments (ignored)', async () => {
|
||||
it('should open approval mode dialog when invoked with whitespace only', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'some arguments',
|
||||
' ',
|
||||
)) as OpenDialogActionReturn;
|
||||
|
||||
expect(result.type).toBe('dialog');
|
||||
expect(result.dialog).toBe('approval-mode');
|
||||
});
|
||||
|
||||
describe('direct mode setting', () => {
|
||||
it('should set approval mode to "plan" when argument is "plan"', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'plan',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(result.content).toContain('plan');
|
||||
expect(mockSetValue).toHaveBeenCalledWith(
|
||||
'User',
|
||||
'tools.approvalMode',
|
||||
'plan',
|
||||
);
|
||||
expect(mockSetApprovalMode).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set approval mode to "yolo" when argument is "yolo"', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'yolo',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(result.content).toContain('yolo');
|
||||
expect(mockSetValue).toHaveBeenCalledWith(
|
||||
'User',
|
||||
'tools.approvalMode',
|
||||
'yolo',
|
||||
);
|
||||
});
|
||||
|
||||
it('should set approval mode to "auto-edit" when argument is "auto-edit"', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'auto-edit',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(result.content).toContain('auto-edit');
|
||||
expect(mockSetValue).toHaveBeenCalledWith(
|
||||
'User',
|
||||
'tools.approvalMode',
|
||||
'auto-edit',
|
||||
);
|
||||
});
|
||||
|
||||
it('should set approval mode to "default" when argument is "default"', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'default',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(result.content).toContain('default');
|
||||
expect(mockSetValue).toHaveBeenCalledWith(
|
||||
'User',
|
||||
'tools.approvalMode',
|
||||
'default',
|
||||
);
|
||||
});
|
||||
|
||||
it('should be case-insensitive for mode argument', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'YOLO',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(mockSetValue).toHaveBeenCalledWith(
|
||||
'User',
|
||||
'tools.approvalMode',
|
||||
'yolo',
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle argument with leading/trailing whitespace', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
' plan ',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(mockSetValue).toHaveBeenCalledWith(
|
||||
'User',
|
||||
'tools.approvalMode',
|
||||
'plan',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalid mode argument', () => {
|
||||
it('should return error for invalid mode', async () => {
|
||||
const result = (await approvalModeCommand.action?.(
|
||||
mockContext,
|
||||
'invalid-mode',
|
||||
)) as MessageActionReturn;
|
||||
|
||||
expect(result.type).toBe('message');
|
||||
expect(result.messageType).toBe('error');
|
||||
expect(result.content).toContain('invalid-mode');
|
||||
expect(result.content).toContain('plan');
|
||||
expect(result.content).toContain('yolo');
|
||||
expect(mockSetValue).not.toHaveBeenCalled();
|
||||
expect(mockSetApprovalMode).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not have subcommands', () => {
|
||||
expect(approvalModeCommand.subCommands).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not have completion function', () => {
|
||||
expect(approvalModeCommand.completion).toBeUndefined();
|
||||
describe('completion', () => {
|
||||
it('should have completion function', () => {
|
||||
expect(approvalModeCommand.completion).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return all modes when partial arg is empty', async () => {
|
||||
const completions = await approvalModeCommand.completion?.(
|
||||
mockContext,
|
||||
'',
|
||||
);
|
||||
|
||||
expect(completions).toContain('plan');
|
||||
expect(completions).toContain('default');
|
||||
expect(completions).toContain('auto-edit');
|
||||
expect(completions).toContain('yolo');
|
||||
});
|
||||
|
||||
it('should filter modes based on partial arg', async () => {
|
||||
const completions = await approvalModeCommand.completion?.(
|
||||
mockContext,
|
||||
'p',
|
||||
);
|
||||
|
||||
expect(completions).toContain('plan');
|
||||
expect(completions).not.toContain('yolo');
|
||||
});
|
||||
|
||||
it('should filter modes case-insensitively', async () => {
|
||||
const completions = await approvalModeCommand.completion?.(
|
||||
mockContext,
|
||||
'A',
|
||||
);
|
||||
|
||||
expect(completions).toContain('auto-edit');
|
||||
});
|
||||
|
||||
it('should return empty array when no modes match', async () => {
|
||||
const completions = await approvalModeCommand.completion?.(
|
||||
mockContext,
|
||||
'xyz',
|
||||
);
|
||||
|
||||
expect(completions).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue