fix: /policy to display policies according to mode (#16772)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Allen Hutchison <adh@google.com>
This commit is contained in:
Ishaan Gupta
2026-01-22 03:03:57 +05:30
committed by GitHub
parent addecf2c74
commit 1033550f78
2 changed files with 62 additions and 23 deletions

View File

@@ -62,7 +62,7 @@ describe('policiesCommand', () => {
);
});
it('should list active policies in correct format', async () => {
it('should list policies grouped by mode', async () => {
const mockRules = [
{
decision: PolicyDecision.DENY,
@@ -99,13 +99,18 @@ describe('policiesCommand', () => {
const call = vi.mocked(mockContext.ui.addItem).mock.calls[0];
const content = (call[0] as { text: string }).text;
expect(content).toContain('### Normal Mode Policies');
expect(content).toContain(
'1. **DENY** tool: `dangerousTool` [Priority: 10]',
'### Auto Edit Mode Policies (combined with normal mode policies)',
);
expect(content).toContain(
'2. **ALLOW** all tools (args match: `safe`) [Source: `test.toml`]',
'### Yolo Mode Policies (combined with normal mode policies)',
);
expect(content).toContain('3. **ASK_USER** all tools');
expect(content).toContain(
'**DENY** tool: `dangerousTool` [Priority: 10]',
);
expect(content).toContain('**ALLOW** all tools (args match: `safe`)');
expect(content).toContain('**ASK_USER** all tools');
});
});
});

View File

@@ -4,12 +4,46 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { ApprovalMode, type PolicyRule } from '@google/gemini-cli-core';
import { CommandKind, type SlashCommand } from './types.js';
import { MessageType } from '../types.js';
interface CategorizedRules {
normal: PolicyRule[];
autoEdit: PolicyRule[];
yolo: PolicyRule[];
}
const categorizeRulesByMode = (
rules: readonly PolicyRule[],
): CategorizedRules => {
const result: CategorizedRules = {
normal: [],
autoEdit: [],
yolo: [],
};
const ALL_MODES = Object.values(ApprovalMode);
rules.forEach((rule) => {
const modes = rule.modes?.length ? rule.modes : ALL_MODES;
const modeSet = new Set(modes);
if (modeSet.has(ApprovalMode.DEFAULT)) result.normal.push(rule);
if (modeSet.has(ApprovalMode.AUTO_EDIT)) result.autoEdit.push(rule);
if (modeSet.has(ApprovalMode.YOLO)) result.yolo.push(rule);
});
return result;
};
const formatRule = (rule: PolicyRule, i: number) =>
`${i + 1}. **${rule.decision.toUpperCase()}** ${rule.toolName ? `tool: \`${rule.toolName}\`` : 'all tools'}` +
(rule.argsPattern ? ` (args match: \`${rule.argsPattern.source}\`)` : '') +
(rule.priority !== undefined ? ` [Priority: ${rule.priority}]` : '');
const formatSection = (title: string, rules: PolicyRule[]) =>
`### ${title}\n${rules.length ? rules.map(formatRule).join('\n') : '_No policies._'}\n\n`;
const listPoliciesCommand: SlashCommand = {
name: 'list',
description: 'List all active policies',
description: 'List all active policies grouped by mode',
kind: CommandKind.BUILT_IN,
autoExecute: true,
action: async (context) => {
@@ -39,25 +73,25 @@ const listPoliciesCommand: SlashCommand = {
return;
}
const categorized = categorizeRulesByMode(rules);
const normalRulesSet = new Set(categorized.normal);
const uniqueAutoEdit = categorized.autoEdit.filter(
(rule) => !normalRulesSet.has(rule),
);
const uniqueYolo = categorized.yolo.filter(
(rule) => !normalRulesSet.has(rule),
);
let content = '**Active Policies**\n\n';
rules.forEach((rule, index) => {
content += `${index + 1}. **${rule.decision.toUpperCase()}**`;
if (rule.toolName) {
content += ` tool: \`${rule.toolName}\``;
} else {
content += ` all tools`;
}
if (rule.argsPattern) {
content += ` (args match: \`${rule.argsPattern.source}\`)`;
}
if (rule.priority !== undefined) {
content += ` [Priority: ${rule.priority}]`;
}
if (rule.source) {
content += ` [Source: \`${rule.source}\`]`;
}
content += '\n';
});
content += formatSection('Normal Mode Policies', categorized.normal);
content += formatSection(
'Auto Edit Mode Policies (combined with normal mode policies)',
uniqueAutoEdit,
);
content += formatSection(
'Yolo Mode Policies (combined with normal mode policies)',
uniqueYolo,
);
context.ui.addItem(
{