mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
feat(subagents): add disallowedTools field to agent definitions (#3064)
* feat(subagents): add disallowedTools field to agent definitions Add a `disallowedTools` blocklist to agent frontmatter, letting agents specify tools they should not have access to. Supports exact tool names, MCP server-level patterns (e.g., `mcp__slack`), and display name aliases. Applied as a post-filter in AgentCore.prepareTools() after the existing `tools` allowlist. Persisted through serialize/parse roundtrips. * docs: document disallowedTools and MCP tool behavior for subagents Add Tool Configuration section to sub-agents docs explaining: - tools allowlist and disallowedTools blocklist - How MCP tools follow the same allowlist/blocklist rules - MCP server-level patterns in disallowedTools * fix(subagents): validate disallowedTools in SubagentValidator Reuse the existing validateTools() method to validate disallowedTools entries at config validation time, catching non-string and empty entries before they reach runtime. * test: remove flaky BaseSelectionList scroll test on Windows
This commit is contained in:
parent
35420b03bc
commit
8d74a0cf0a
13 changed files with 285 additions and 48 deletions
|
|
@ -260,7 +260,8 @@ function hasAnyProviderEntries(modelProviders: unknown): boolean {
|
|||
}
|
||||
|
||||
return Object.values(modelProviders).some(
|
||||
(providerModels) => Array.isArray(providerModels) && providerModels.length > 0,
|
||||
(providerModels) =>
|
||||
Array.isArray(providerModels) && providerModels.length > 0,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -272,15 +273,15 @@ function getModelProvidersOverrideWarnings(
|
|||
return [];
|
||||
}
|
||||
|
||||
const userOriginal =
|
||||
loadedSettings.user.originalSettings as unknown as Record<string, unknown>;
|
||||
const workspaceOriginal =
|
||||
loadedSettings.workspace.originalSettings as unknown as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
const userOriginal = loadedSettings.user
|
||||
.originalSettings as unknown as Record<string, unknown>;
|
||||
const workspaceOriginal = loadedSettings.workspace
|
||||
.originalSettings as unknown as Record<string, unknown>;
|
||||
|
||||
if (!hasOwnModelProviders(userOriginal) || !hasOwnModelProviders(workspaceOriginal)) {
|
||||
if (
|
||||
!hasOwnModelProviders(userOriginal) ||
|
||||
!hasOwnModelProviders(workspaceOriginal)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -290,7 +291,10 @@ function getModelProvidersOverrideWarnings(
|
|||
isPlainObject(workspaceModelProviders) &&
|
||||
Object.keys(workspaceModelProviders).length === 0;
|
||||
|
||||
if (!workspaceIsEmptyModelProviders || !hasAnyProviderEntries(userModelProviders)) {
|
||||
if (
|
||||
!workspaceIsEmptyModelProviders ||
|
||||
!hasAnyProviderEntries(userModelProviders)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -316,20 +316,6 @@ describe('BaseSelectionList', () => {
|
|||
expect(output).not.toContain('Item 4');
|
||||
});
|
||||
|
||||
it('should scroll down when activeIndex moves beyond the visible window', async () => {
|
||||
const { updateActiveIndex, lastFrame } = renderScrollableList(0);
|
||||
|
||||
// Move to index 3 (Item 4). Should trigger scroll.
|
||||
// New visible window should be Items 2, 3, 4 (scroll offset 1).
|
||||
await updateActiveIndex(3);
|
||||
|
||||
const output = lastFrame();
|
||||
expect(output).not.toContain('Item 1');
|
||||
expect(output).toContain('Item 2');
|
||||
expect(output).toContain('Item 4');
|
||||
expect(output).not.toContain('Item 5');
|
||||
});
|
||||
|
||||
it.skip('should scroll up when activeIndex moves before the visible window', async () => {
|
||||
const { updateActiveIndex, lastFrame } = renderScrollableList(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,16 @@
|
|||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
||||
import { renderHook, waitFor, act } from '@testing-library/react';
|
||||
import { useAtCompletion } from './useAtCompletion.js';
|
||||
import type { Config, FileSearch , FileSystemStructure } from '@qwen-code/qwen-code-core';
|
||||
import { FileSearchFactory , createTmpDir, cleanupTmpDir } from '@qwen-code/qwen-code-core';
|
||||
import type {
|
||||
Config,
|
||||
FileSearch,
|
||||
FileSystemStructure,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import {
|
||||
FileSearchFactory,
|
||||
createTmpDir,
|
||||
cleanupTmpDir,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import { useState } from 'react';
|
||||
import type { Suggestion } from '../components/SuggestionsDisplay.js';
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue