mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-02 09:20:42 -07:00
feat(admin): support admin-enforced settings for Agent Skills (#16406)
This commit is contained in:
@@ -637,6 +637,7 @@ export async function loadCliConfig(
|
||||
|
||||
const mcpEnabled = settings.admin?.mcp?.enabled ?? true;
|
||||
const extensionsEnabled = settings.admin?.extensions?.enabled ?? true;
|
||||
const adminSkillsEnabled = settings.admin?.skills?.enabled ?? true;
|
||||
|
||||
return new Config({
|
||||
sessionId,
|
||||
@@ -661,6 +662,7 @@ export async function loadCliConfig(
|
||||
mcpEnabled,
|
||||
extensionsEnabled,
|
||||
agents: settings.agents,
|
||||
adminSkillsEnabled,
|
||||
allowedMcpServers: mcpEnabled
|
||||
? (argv.allowedMcpServerNames ?? settings.mcp?.allowed)
|
||||
: undefined,
|
||||
@@ -708,6 +710,7 @@ export async function loadCliConfig(
|
||||
enableAgents: settings.experimental?.enableAgents,
|
||||
skillsSupport: settings.experimental?.skills,
|
||||
disabledSkills: settings.skills?.disabled,
|
||||
|
||||
experimentalJitContext: settings.experimental?.jitContext,
|
||||
noBrowser: !!process.env['NO_BROWSER'],
|
||||
summarizeToolOutput: settings.model?.summarizeToolOutput,
|
||||
@@ -750,6 +753,8 @@ export async function loadCliConfig(
|
||||
const refreshedSettings = loadSettings(cwd);
|
||||
return {
|
||||
disabledSkills: refreshedSettings.merged.skills?.disabled,
|
||||
adminSkillsEnabled:
|
||||
refreshedSettings.merged.admin?.skills?.enabled ?? adminSkillsEnabled,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -26,11 +26,12 @@ vi.mock('node:os', async (importOriginal) => {
|
||||
|
||||
// Mock @google/gemini-cli-core
|
||||
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import('@google/gemini-cli-core')>();
|
||||
const core = await importOriginal<typeof import('@google/gemini-cli-core')>();
|
||||
return {
|
||||
...actual,
|
||||
...core,
|
||||
homedir: mockHomedir,
|
||||
loadAgentsFromDirectory: core.loadAgentsFromDirectory,
|
||||
loadSkillsFromDir: core.loadSkillsFromDir,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ import * as path from 'node:path';
|
||||
import * as os from 'node:os';
|
||||
import { ExtensionManager } from './extension-manager.js';
|
||||
import type { Settings } from './settings.js';
|
||||
import {
|
||||
loadAgentsFromDirectory,
|
||||
loadSkillsFromDir,
|
||||
} from '@google/gemini-cli-core';
|
||||
|
||||
let currentTempHome = '';
|
||||
|
||||
@@ -24,6 +28,11 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
loadAgentsFromDirectory: vi.fn().mockImplementation(async () => ({
|
||||
agents: [],
|
||||
errors: [],
|
||||
})),
|
||||
loadSkillsFromDir: vi.fn().mockImplementation(async () => []),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -34,6 +43,11 @@ describe('ExtensionManager Settings Scope', () => {
|
||||
let extensionDir: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.mocked(loadAgentsFromDirectory).mockResolvedValue({
|
||||
agents: [],
|
||||
errors: [],
|
||||
});
|
||||
vi.mocked(loadSkillsFromDir).mockResolvedValue([]);
|
||||
currentTempHome = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'gemini-cli-test-home-'),
|
||||
);
|
||||
|
||||
@@ -31,6 +31,12 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
return {
|
||||
...actual,
|
||||
homedir: mockHomedir,
|
||||
loadAgentsFromDirectory: vi
|
||||
.fn()
|
||||
.mockImplementation(async () => ({ agents: [], errors: [] })),
|
||||
loadSkillsFromDir: (
|
||||
await importOriginal<typeof import('@google/gemini-cli-core')>()
|
||||
).loadSkillsFromDir,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import {
|
||||
ExtensionDisableEvent,
|
||||
ExtensionEnableEvent,
|
||||
KeychainTokenStorage,
|
||||
loadAgentsFromDirectory,
|
||||
loadSkillsFromDir,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { loadSettings, SettingScope } from './settings.js';
|
||||
import {
|
||||
@@ -117,6 +119,10 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
listSecrets: vi.fn(),
|
||||
isAvailable: vi.fn().mockResolvedValue(true),
|
||||
})),
|
||||
loadAgentsFromDirectory: vi
|
||||
.fn()
|
||||
.mockImplementation(async () => ({ agents: [], errors: [] })),
|
||||
loadSkillsFromDir: vi.fn().mockImplementation(async () => []),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -171,6 +177,11 @@ describe('extension tests', () => {
|
||||
(
|
||||
KeychainTokenStorage as unknown as ReturnType<typeof vi.fn>
|
||||
).mockImplementation(() => mockKeychainStorage);
|
||||
vi.mocked(loadAgentsFromDirectory).mockResolvedValue({
|
||||
agents: [],
|
||||
errors: [],
|
||||
});
|
||||
vi.mocked(loadSkillsFromDir).mockResolvedValue([]);
|
||||
tempHomeDir = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'gemini-cli-test-home-'),
|
||||
);
|
||||
|
||||
@@ -324,23 +324,19 @@ export class LoadedSettings {
|
||||
|
||||
setRemoteAdminSettings(remoteSettings: GeminiCodeAssistSetting): void {
|
||||
const admin: Settings['admin'] = {};
|
||||
const { secureModeEnabled, mcpSetting, cliFeatureSetting } = remoteSettings;
|
||||
|
||||
if (remoteSettings.secureModeEnabled !== undefined) {
|
||||
admin.secureModeEnabled = remoteSettings.secureModeEnabled;
|
||||
if (secureModeEnabled !== undefined) {
|
||||
admin.secureModeEnabled = secureModeEnabled;
|
||||
}
|
||||
|
||||
if (remoteSettings.mcpSetting?.mcpEnabled !== undefined) {
|
||||
admin.mcp = { enabled: remoteSettings.mcpSetting.mcpEnabled };
|
||||
if (mcpSetting?.mcpEnabled !== undefined) {
|
||||
admin.mcp = { enabled: mcpSetting.mcpEnabled };
|
||||
}
|
||||
|
||||
if (
|
||||
remoteSettings.cliFeatureSetting?.extensionsSetting?.extensionsEnabled !==
|
||||
undefined
|
||||
) {
|
||||
admin.extensions = {
|
||||
enabled:
|
||||
remoteSettings.cliFeatureSetting.extensionsSetting.extensionsEnabled,
|
||||
};
|
||||
const extensionsSetting = cliFeatureSetting?.extensionsSetting;
|
||||
if (extensionsSetting?.extensionsEnabled !== undefined) {
|
||||
admin.extensions = { enabled: extensionsSetting.extensionsEnabled };
|
||||
}
|
||||
|
||||
this._remoteAdminSettings = { admin };
|
||||
|
||||
@@ -1842,6 +1842,28 @@ const SETTINGS_SCHEMA = {
|
||||
},
|
||||
},
|
||||
},
|
||||
skills: {
|
||||
type: 'object',
|
||||
label: 'Skills Settings',
|
||||
category: 'Admin',
|
||||
requiresRestart: false,
|
||||
default: {},
|
||||
description: 'Agent Skills-specific admin settings.',
|
||||
showInDialog: false,
|
||||
mergeStrategy: MergeStrategy.REPLACE,
|
||||
properties: {
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
label: 'Skills Enabled',
|
||||
category: 'Admin',
|
||||
requiresRestart: false,
|
||||
default: true,
|
||||
description: 'If false, disallows agent skills from being used.',
|
||||
showInDialog: false,
|
||||
mergeStrategy: MergeStrategy.REPLACE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies SettingsSchema;
|
||||
|
||||
Reference in New Issue
Block a user