summaryrefslogtreecommitdiff
path: root/packages/cli
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli')
-rw-r--r--packages/cli/src/config/config.test.ts128
-rw-r--r--packages/cli/src/config/config.ts17
-rw-r--r--packages/cli/src/config/extension.ts1
3 files changed, 145 insertions, 1 deletions
diff --git a/packages/cli/src/config/config.test.ts b/packages/cli/src/config/config.test.ts
index 9808c407..d4820726 100644
--- a/packages/cli/src/config/config.test.ts
+++ b/packages/cli/src/config/config.test.ts
@@ -350,3 +350,131 @@ describe('mergeMcpServers', () => {
expect(settings).toEqual(originalSettings);
});
});
+
+describe('mergeExcludeTools', () => {
+ it('should merge excludeTools from settings and extensions', async () => {
+ const settings: Settings = { excludeTools: ['tool1', 'tool2'] };
+ const extensions: Extension[] = [
+ {
+ config: {
+ name: 'ext1',
+ version: '1.0.0',
+ excludeTools: ['tool3', 'tool4'],
+ },
+ contextFiles: [],
+ },
+ {
+ config: {
+ name: 'ext2',
+ version: '1.0.0',
+ excludeTools: ['tool5'],
+ },
+ contextFiles: [],
+ },
+ ];
+ const config = await loadCliConfig(settings, extensions, 'test-session');
+ expect(config.getExcludeTools()).toEqual(
+ expect.arrayContaining(['tool1', 'tool2', 'tool3', 'tool4', 'tool5']),
+ );
+ expect(config.getExcludeTools()).toHaveLength(5);
+ });
+
+ it('should handle overlapping excludeTools between settings and extensions', async () => {
+ const settings: Settings = { excludeTools: ['tool1', 'tool2'] };
+ const extensions: Extension[] = [
+ {
+ config: {
+ name: 'ext1',
+ version: '1.0.0',
+ excludeTools: ['tool2', 'tool3'],
+ },
+ contextFiles: [],
+ },
+ ];
+ const config = await loadCliConfig(settings, extensions, 'test-session');
+ expect(config.getExcludeTools()).toEqual(
+ expect.arrayContaining(['tool1', 'tool2', 'tool3']),
+ );
+ expect(config.getExcludeTools()).toHaveLength(3);
+ });
+
+ it('should handle overlapping excludeTools between extensions', async () => {
+ const settings: Settings = { excludeTools: ['tool1'] };
+ const extensions: Extension[] = [
+ {
+ config: {
+ name: 'ext1',
+ version: '1.0.0',
+ excludeTools: ['tool2', 'tool3'],
+ },
+ contextFiles: [],
+ },
+ {
+ config: {
+ name: 'ext2',
+ version: '1.0.0',
+ excludeTools: ['tool3', 'tool4'],
+ },
+ contextFiles: [],
+ },
+ ];
+ const config = await loadCliConfig(settings, extensions, 'test-session');
+ expect(config.getExcludeTools()).toEqual(
+ expect.arrayContaining(['tool1', 'tool2', 'tool3', 'tool4']),
+ );
+ expect(config.getExcludeTools()).toHaveLength(4);
+ });
+
+ it('should return an empty array when no excludeTools are specified', async () => {
+ const settings: Settings = {};
+ const extensions: Extension[] = [];
+ const config = await loadCliConfig(settings, extensions, 'test-session');
+ expect(config.getExcludeTools()).toEqual([]);
+ });
+
+ it('should handle settings with excludeTools but no extensions', async () => {
+ const settings: Settings = { excludeTools: ['tool1', 'tool2'] };
+ const extensions: Extension[] = [];
+ const config = await loadCliConfig(settings, extensions, 'test-session');
+ expect(config.getExcludeTools()).toEqual(
+ expect.arrayContaining(['tool1', 'tool2']),
+ );
+ expect(config.getExcludeTools()).toHaveLength(2);
+ });
+
+ it('should handle extensions with excludeTools but no settings', async () => {
+ const settings: Settings = {};
+ const extensions: Extension[] = [
+ {
+ config: {
+ name: 'ext1',
+ version: '1.0.0',
+ excludeTools: ['tool1', 'tool2'],
+ },
+ contextFiles: [],
+ },
+ ];
+ const config = await loadCliConfig(settings, extensions, 'test-session');
+ expect(config.getExcludeTools()).toEqual(
+ expect.arrayContaining(['tool1', 'tool2']),
+ );
+ expect(config.getExcludeTools()).toHaveLength(2);
+ });
+
+ it('should not modify the original settings object', async () => {
+ const settings: Settings = { excludeTools: ['tool1'] };
+ const extensions: Extension[] = [
+ {
+ config: {
+ name: 'ext1',
+ version: '1.0.0',
+ excludeTools: ['tool2'],
+ },
+ contextFiles: [],
+ },
+ ];
+ const originalSettings = JSON.parse(JSON.stringify(settings));
+ await loadCliConfig(settings, extensions, 'test-session');
+ expect(settings).toEqual(originalSettings);
+ });
+});
diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts
index 552a8f67..cecf904b 100644
--- a/packages/cli/src/config/config.ts
+++ b/packages/cli/src/config/config.ts
@@ -194,6 +194,7 @@ export async function loadCliConfig(
);
const mcpServers = mergeMcpServers(settings, extensions);
+ const excludeTools = mergeExcludeTools(settings, extensions);
const sandboxConfig = await loadSandboxConfig(settings, argv);
@@ -206,7 +207,7 @@ export async function loadCliConfig(
question: argv.prompt || '',
fullContext: argv.all_files || false,
coreTools: settings.coreTools || undefined,
- excludeTools: settings.excludeTools || undefined,
+ excludeTools,
toolDiscoveryCommand: settings.toolDiscoveryCommand,
toolCallCommand: settings.toolCallCommand,
mcpServerCommand: settings.mcpServerCommand,
@@ -265,6 +266,20 @@ function mergeMcpServers(settings: Settings, extensions: Extension[]) {
}
return mcpServers;
}
+
+function mergeExcludeTools(
+ settings: Settings,
+ extensions: Extension[],
+): string[] {
+ const allExcludeTools = new Set(settings.excludeTools || []);
+ for (const extension of extensions) {
+ for (const tool of extension.config.excludeTools || []) {
+ allExcludeTools.add(tool);
+ }
+ }
+ return [...allExcludeTools];
+}
+
function findEnvFile(startDir: string): string | null {
let currentDir = path.resolve(startDir);
while (true) {
diff --git a/packages/cli/src/config/extension.ts b/packages/cli/src/config/extension.ts
index 31a6111f..57e6632b 100644
--- a/packages/cli/src/config/extension.ts
+++ b/packages/cli/src/config/extension.ts
@@ -22,6 +22,7 @@ export interface ExtensionConfig {
version: string;
mcpServers?: Record<string, MCPServerConfig>;
contextFileName?: string | string[];
+ excludeTools?: string[];
}
export function loadExtensions(workspaceDir: string): Extension[] {