diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 1c2867b92e3e6..26551046669f2 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -1217,15 +1217,6 @@ configurationRegistry.registerConfiguration({ mode: 'auto' } }, - [ChatConfiguration.SubagentToolCustomAgents]: { - type: 'boolean', - description: nls.localize('chat.subagentTool.customAgents', "Whether the runSubagent tool is able to use custom agents. When enabled, the tool can take the name of a custom agent, but it must be given the exact name of the agent."), - default: false, - tags: ['experimental'], - experiment: { - mode: 'auto' - } - }, [ChatConfiguration.ChatCustomizationMenuEnabled]: { type: 'boolean', description: nls.localize('chat.aiCustomizationMenu.enabled', "Controls whether the Chat Customization Menu is shown in the Manage menu and Command Palette. When disabled, the Chat Customizations editor and related commands are hidden."), diff --git a/src/vs/workbench/contrib/chat/common/constants.ts b/src/vs/workbench/contrib/chat/common/constants.ts index d9c776a3618ec..b46ebc1b65370 100644 --- a/src/vs/workbench/contrib/chat/common/constants.ts +++ b/src/vs/workbench/contrib/chat/common/constants.ts @@ -47,7 +47,6 @@ export enum ChatConfiguration { ChatViewSessionsOrientation = 'chat.viewSessions.orientation', ChatViewProgressBadgeEnabled = 'chat.viewProgressBadge.enabled', ChatContextUsageEnabled = 'chat.contextUsage.enabled', - SubagentToolCustomAgents = 'chat.customAgentInSubagent.enabled', ShowCodeBlockProgressAnimation = 'chat.agent.codeBlockProgress', RestoreLastPanelSession = 'chat.restoreLastPanelSession', ExitAfterDelegation = 'chat.exitAfterDelegation', @@ -171,3 +170,9 @@ export const ChatEditorTitleMaxLength = 30; export const CHAT_TERMINAL_OUTPUT_MAX_PREVIEW_LINES = 1000; export const CONTEXT_MODELS_EDITOR = new RawContextKey('inModelsEditor', false); export const CONTEXT_MODELS_SEARCH_FOCUS = new RawContextKey('inModelsSearch', false); + +/** + * The built-in general-purpose agent name. When the model uses this name, + * the subagent inherits the parent's system prompt, model, and tools. + */ +export const GeneralPurposeAgentName = 'General Purpose'; diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/computeAutomaticInstructions.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/computeAutomaticInstructions.ts index 3c3e2597382c7..13982296bda4f 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/computeAutomaticInstructions.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/computeAutomaticInstructions.ts @@ -26,7 +26,7 @@ import { PromptsType } from './promptTypes.js'; import { ParsedPromptFile } from './promptFileParser.js'; import { AgentFileType, ICustomAgent, IPromptPath, IPromptsService } from './service/promptsService.js'; import { OffsetRange } from '../../../../../editor/common/core/ranges/offsetRange.js'; -import { ChatConfiguration, ChatModeKind } from '../constants.js'; +import { ChatModeKind, GeneralPurposeAgentName } from '../constants.js'; import { UserSelectedTools } from '../participants/chatAgents.js'; export type InstructionsCollectionEvent = { @@ -391,7 +391,18 @@ export class ComputeAutomaticInstructions { entries.push('', '', ''); // add trailing newline } } - if (runSubagentTool && this._configurationService.getValue(ChatConfiguration.SubagentToolCustomAgents)) { + if (runSubagentTool) { + entries.push(''); + entries.push('Here is a list of agents that can be used when running a subagent.'); + entries.push('Each agent has optionally a description with the agent\'s purpose and expertise. When asked to run a subagent, choose the most appropriate agent from this list.'); + entries.push(`Use the ${runSubagentTool.variable} tool with the agent name to run the subagent.`); + + // Built-in General Purpose agent, always available + entries.push(''); + entries.push(`${GeneralPurposeAgentName}`); + entries.push(`Full-capability agent for complex multi-step tasks requiring the complete toolset and high-quality reasoning. Has access to all tools. Inherits the parent agent's model and system prompt. Use for tasks that don't fit a more specialized agent.`); + entries.push(''); + const canUseAgent = (() => { if (!this._enabledSubagents || this._enabledSubagents.includes('*')) { return (agent: ICustomAgent) => agent.visibility.agentInvocable; @@ -401,29 +412,23 @@ export class ComputeAutomaticInstructions { } })(); const agents = await this._promptsService.getCustomAgents(token); - if (agents.length > 0) { - entries.push(''); - entries.push('Here is a list of agents that can be used when running a subagent.'); - entries.push('Each agent has optionally a description with the agent\'s purpose and expertise. When asked to run a subagent, choose the most appropriate agent from this list.'); - entries.push(`Use the ${runSubagentTool.variable} tool with the agent name to run the subagent.`); - for (const agent of agents) { - if (canUseAgent(agent)) { - entries.push(''); - entries.push(`${agent.name}`); - if (agent.description) { - entries.push(`${agent.description}`); - } - if (agent.argumentHint) { - entries.push(`${agent.argumentHint}`); - } - entries.push(''); - if (isInClaudeAgentsFolder(agent.uri)) { - telemetryEvent.claudeAgentsCount++; - } + for (const agent of agents) { + if (canUseAgent(agent)) { + entries.push(''); + entries.push(`${agent.name}`); + if (agent.description) { + entries.push(`${agent.description}`); + } + if (agent.argumentHint) { + entries.push(`${agent.argumentHint}`); + } + entries.push(''); + if (isInClaudeAgentsFolder(agent.uri)) { + telemetryEvent.claudeAgentsCount++; } } - entries.push('', '', ''); // add trailing newline } + entries.push('', '', ''); // add trailing newline } if (entries.length === 0) { return undefined; diff --git a/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts b/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts index 4e9eacf9ae365..4bd9e4fde1814 100644 --- a/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts +++ b/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts @@ -12,12 +12,11 @@ import { Disposable, DisposableStore } from '../../../../../../base/common/lifec import { ThemeIcon } from '../../../../../../base/common/themables.js'; import { generateUuid } from '../../../../../../base/common/uuid.js'; import { localize } from '../../../../../../nls.js'; -import { IConfigurationChangeEvent, IConfigurationService } from '../../../../../../platform/configuration/common/configuration.js'; import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js'; import { ILogService } from '../../../../../../platform/log/common/log.js'; import { ChatRequestVariableSet } from '../../attachments/chatVariableEntries.js'; import { IChatProgress, IChatService } from '../../chatService/chatService.js'; -import { ChatAgentLocation, ChatConfiguration, ChatModeKind } from '../../constants.js'; +import { ChatAgentLocation, ChatModeKind, GeneralPurposeAgentName } from '../../constants.js'; import { ILanguageModelsService } from '../../languageModels.js'; import { ChatModel, IChatRequestModeInstructions } from '../../model/chatModel.js'; import { IChatAgentRequest, IChatAgentService } from '../../participants/chatAgents.js'; @@ -47,19 +46,20 @@ const BaseModelDescription = `Launch a new agent to handle complex, multi-step t - When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. - Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you. - The agent's outputs should generally be trusted -- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user\'s intent`; +- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user\'s intent +- If the user asks for a certain agent, you MUST provide that EXACT agent name (case-sensitive) to invoke that specific agent.`; export interface IRunSubagentToolInputParams { prompt: string; description: string; - agentName?: string; + agentName: string; } export class RunSubagentTool extends Disposable implements IToolImpl { static readonly Id = 'runSubagent'; - readonly onDidUpdateToolData: Event; + readonly onDidUpdateToolData: Event; /** Hack to port data between prepare/invoke */ private readonly _resolvedModels = new Map(); @@ -70,17 +70,15 @@ export class RunSubagentTool extends Disposable implements IToolImpl { @ILanguageModelToolsService private readonly languageModelToolsService: ILanguageModelToolsService, @ILanguageModelsService private readonly languageModelsService: ILanguageModelsService, @ILogService private readonly logService: ILogService, - @ILanguageModelToolsService private readonly toolsService: ILanguageModelToolsService, - @IConfigurationService private readonly configurationService: IConfigurationService, @IPromptsService private readonly promptsService: IPromptsService, @IInstantiationService private readonly instantiationService: IInstantiationService, ) { super(); - this.onDidUpdateToolData = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ChatConfiguration.SubagentToolCustomAgents)); + this.onDidUpdateToolData = Event.None; } getToolData(): IToolData { - let modelDescription = BaseModelDescription; + const modelDescription = BaseModelDescription; const inputSchema: IJSONSchema & { properties: IJSONSchemaMap } = { type: 'object', properties: { @@ -91,18 +89,14 @@ export class RunSubagentTool extends Disposable implements IToolImpl { description: { type: 'string', description: 'A short (3-5 word) description of the task' + }, + agentName: { + type: 'string', + description: 'Name of the agent to invoke.' } }, - required: ['prompt', 'description'] + required: ['prompt', 'description', 'agentName'] }; - - if (this.configurationService.getValue(ChatConfiguration.SubagentToolCustomAgents)) { - inputSchema.properties.agentName = { - type: 'string', - description: 'Optional name of a specific agent to invoke. If not provided, uses the current agent.' - }; - modelDescription += `\n- If the user asks for a certain agent, you MUST provide that EXACT agent name (case-sensitive) to invoke that specific agent.`; - } const runSubagentToolData: IToolData = { id: RunSubagentTool.Id, toolReferenceName: VSCodeToolReference.runSubagent, @@ -150,7 +144,11 @@ export class RunSubagentTool extends Disposable implements IToolImpl { let resolvedModelName: string | undefined; const subAgentName = args.agentName; - if (subAgentName) { + // Defensive: model may omit agentName despite schema requiring it + const isGeneralPurpose = !subAgentName || subAgentName === GeneralPurposeAgentName; + + if (!isGeneralPurpose) { + // Custom agent; look up by name and apply its model/tools/instructions subagent = await this.getSubAgentByName(subAgentName); if (subagent) { // Check the pre-resolved model cache from prepareToolInvocation @@ -184,14 +182,15 @@ export class RunSubagentTool extends Disposable implements IToolImpl { modeInstructions = instructions && { name: subAgentName, content: instructions.content, - toolReferences: this.toolsService.toToolReferences(instructions.toolReferences), + toolReferences: this.languageModelToolsService.toToolReferences(instructions.toolReferences), metadata: instructions.metadata, }; } else { - throw new Error(`Requested agent '${subAgentName}' not found. Try again with the correct agent name, or omit the agentName to use the current agent.`); + this._resolvedModels.delete(invocation.callId); + throw new Error(`Requested agent '${subAgentName}' not found. Use '${GeneralPurposeAgentName}' for a full-capability agent.`); } } else { - // No subagent name - clean up any cached entry and resolve model name from main model + // General Purpose agent; inherit parent's model and tools const cached = this._resolvedModels.get(invocation.callId); if (cached) { this._resolvedModels.delete(invocation.callId); @@ -374,7 +373,9 @@ export class RunSubagentTool extends Disposable implements IToolImpl { async prepareToolInvocation(context: IToolInvocationPreparationContext, _token: CancellationToken): Promise { const args = context.parameters as IRunSubagentToolInputParams; - const subagent = args.agentName ? await this.getSubAgentByName(args.agentName) : undefined; + // Defensive: model may omit agentName despite schema requiring it + const isGeneralPurpose = !args.agentName || args.agentName === GeneralPurposeAgentName; + const subagent = isGeneralPurpose ? undefined : await this.getSubAgentByName(args.agentName); // Resolve the model early and cache it for invoke() const resolved = this.resolveSubagentModel(subagent, context.modelId); @@ -385,7 +386,7 @@ export class RunSubagentTool extends Disposable implements IToolImpl { toolSpecificData: { kind: 'subagent', description: args.description, - agentName: subagent?.name, + agentName: isGeneralPurpose ? GeneralPurposeAgentName : (subagent?.name ?? args.agentName), prompt: args.prompt, modelName: resolved.resolvedModelName, }, diff --git a/src/vs/workbench/contrib/chat/test/common/promptSyntax/computeAutomaticInstructions.test.ts b/src/vs/workbench/contrib/chat/test/common/promptSyntax/computeAutomaticInstructions.test.ts index 2b0c19af80183..78b3e49df0789 100644 --- a/src/vs/workbench/contrib/chat/test/common/promptSyntax/computeAutomaticInstructions.test.ts +++ b/src/vs/workbench/contrib/chat/test/common/promptSyntax/computeAutomaticInstructions.test.ts @@ -43,7 +43,7 @@ import { ILanguageModelToolsService } from '../../../common/tools/languageModelT import { IRemoteAgentService } from '../../../../../../workbench/services/remote/common/remoteAgentService.js'; import { basename } from '../../../../../../base/common/resources.js'; import { match } from '../../../../../../base/common/glob.js'; -import { ChatModeKind } from '../../../common/constants.js'; +import { ChatModeKind, GeneralPurposeAgentName } from '../../../common/constants.js'; import { IContextKeyService } from '../../../../../../platform/contextkey/common/contextkey.js'; import { MockContextKeyService } from '../../../../../../platform/keybinding/test/common/mockKeybindingService.js'; import { IAgentPluginService } from '../../../common/plugins/agentPluginService.js'; @@ -1036,7 +1036,6 @@ suite('ComputeAutomaticInstructions', () => { const rootFolderUri = URI.file(rootFolder); workspaceContextService.setWorkspace(testWorkspace(rootFolderUri)); - testConfigService.setUserConfiguration('chat.customAgentInSubagent.enabled', true); testConfigService.setUserConfiguration(PromptsConfig.AGENTS_LOCATION_KEY, { [AGENTS_SOURCE_FOLDER]: true, '.claude/agents': true, @@ -1159,9 +1158,6 @@ suite('ComputeAutomaticInstructions', () => { workspaceContextService.setWorkspace(testWorkspace(rootFolderUri)); - // Enable the config for custom agents - testConfigService.setUserConfiguration('chat.customAgentInSubagent.enabled', true); - await mockFiles(fileService, [ { path: `${rootFolder}/.github/agents/test-agent-1.agent.md`, @@ -1235,16 +1231,19 @@ suite('ComputeAutomaticInstructions', () => { assert.equal(agentsList.length, 1, 'There should be one agents list'); const agents = xmlContents(agentsList[0], 'agent'); - assert.equal(agents.length, 3, 'There should be three agents'); + assert.equal(agents.length, 4, 'There should be four agents (General Purpose + 3 custom)'); + + // First agent should always be the built-in General Purpose agent + assert.equal(xmlContents(agents[0], 'name')[0], GeneralPurposeAgentName); - assert.equal(xmlContents(agents[0], 'description')[0], 'Test agent 1'); - assert.equal(xmlContents(agents[0], 'name')[0], `test-agent-1`); + assert.equal(xmlContents(agents[1], 'description')[0], 'Test agent 1'); + assert.equal(xmlContents(agents[1], 'name')[0], `test-agent-1`); - assert.equal(xmlContents(agents[1], 'description')[0], 'Test agent 3'); - assert.equal(xmlContents(agents[1], 'name')[0], `test-agent-3`); + assert.equal(xmlContents(agents[2], 'description')[0], 'Test agent 3'); + assert.equal(xmlContents(agents[2], 'name')[0], `test-agent-3`); - assert.equal(xmlContents(agents[2], 'description')[0], 'Test agent 5'); - assert.equal(xmlContents(agents[2], 'name')[0], `test-agent-5`); + assert.equal(xmlContents(agents[3], 'description')[0], 'Test agent 5'); + assert.equal(xmlContents(agents[3], 'name')[0], `test-agent-5`); }); test('should include skills list when readFile tool available', async () => { diff --git a/src/vs/workbench/contrib/chat/test/common/tools/builtinTools/runSubagentTool.test.ts b/src/vs/workbench/contrib/chat/test/common/tools/builtinTools/runSubagentTool.test.ts index df306a3ef3ad0..45ef7c11d8aed 100644 --- a/src/vs/workbench/contrib/chat/test/common/tools/builtinTools/runSubagentTool.test.ts +++ b/src/vs/workbench/contrib/chat/test/common/tools/builtinTools/runSubagentTool.test.ts @@ -8,8 +8,8 @@ import { CancellationToken } from '../../../../../../../base/common/cancellation import { URI } from '../../../../../../../base/common/uri.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../../base/test/common/utils.js'; import { NullLogService } from '../../../../../../../platform/log/common/log.js'; -import { TestConfigurationService } from '../../../../../../../platform/configuration/test/common/testConfigurationService.js'; import { RunSubagentTool } from '../../../../common/tools/builtinTools/runSubagentTool.js'; +import { GeneralPurposeAgentName } from '../../../../common/constants.js'; import { MockLanguageModelToolsService } from '../mockLanguageModelToolsService.js'; import { IChatAgentService } from '../../../../common/participants/chatAgents.js'; import { IChatService } from '../../../../common/chatService/chatService.js'; @@ -22,6 +22,26 @@ import { ExtensionIdentifier } from '../../../../../../../platform/extensions/co suite('RunSubagentTool', () => { const testDisposables = ensureNoDisposablesAreLeakedInTestSuite(); + function createTool(opts?: { + customAgents?: ICustomAgent[]; + }) { + const mockToolsService = testDisposables.add(new MockLanguageModelToolsService()); + const promptsService = new MockPromptsService(); + if (opts?.customAgents) { + promptsService.setCustomModes(opts.customAgents); + } + + return testDisposables.add(new RunSubagentTool( + {} as IChatAgentService, + {} as IChatService, + mockToolsService, + {} as ILanguageModelsService, + new NullLogService(), + promptsService, + {} as IInstantiationService, + )); + } + suite('resultText trimming', () => { test('trims leading empty codeblocks (```\\n```) from result', () => { // This tests the regex: /^\n*```\n+```\n*/g @@ -44,10 +64,6 @@ suite('RunSubagentTool', () => { suite('prepareToolInvocation', () => { test('returns correct toolSpecificData', async () => { - const mockToolsService = testDisposables.add(new MockLanguageModelToolsService()); - const configService = new TestConfigurationService(); - - const promptsService = new MockPromptsService(); const customMode: ICustomAgent = { uri: URI.parse('file:///test/custom-agent.md'), name: 'CustomAgent', @@ -58,19 +74,8 @@ suite('RunSubagentTool', () => { target: Target.Undefined, visibility: { userInvocable: true, agentInvocable: true } }; - promptsService.setCustomModes([customMode]); - const tool = testDisposables.add(new RunSubagentTool( - {} as IChatAgentService, - {} as IChatService, - mockToolsService, - {} as ILanguageModelsService, - new NullLogService(), - mockToolsService, - configService, - promptsService, - {} as IInstantiationService, - )); + const tool = createTool({ customAgents: [customMode] }); const result = await tool.prepareToolInvocation( { @@ -95,57 +100,98 @@ suite('RunSubagentTool', () => { modelName: undefined, }); }); - }); - suite('getToolData', () => { - test('returns basic tool data', () => { - const mockToolsService = testDisposables.add(new MockLanguageModelToolsService()); - const configService = new TestConfigurationService(); - const promptsService = new MockPromptsService(); + test('treats undefined agentName as General Purpose', async () => { + const tool = createTool(); - const tool = testDisposables.add(new RunSubagentTool( - {} as IChatAgentService, - {} as IChatService, - mockToolsService, - {} as ILanguageModelsService, - new NullLogService(), - mockToolsService, - configService, - promptsService, - {} as IInstantiationService, - )); + const result = await tool.prepareToolInvocation( + { + parameters: { + prompt: 'Test prompt', + description: 'Test task', + agentName: undefined, + }, + toolCallId: 'test-call-undef', + chatSessionResource: URI.parse('test://session'), + }, + CancellationToken.None + ); - const toolData = tool.getToolData(); + assert.ok(result); + assert.deepStrictEqual(result.toolSpecificData, { + kind: 'subagent', + description: 'Test task', + agentName: GeneralPurposeAgentName, + prompt: 'Test prompt', + modelName: undefined, + }); + }); - assert.strictEqual(toolData.id, 'runSubagent'); - assert.ok(toolData.inputSchema); - assert.ok(toolData.inputSchema.properties?.prompt); - assert.ok(toolData.inputSchema.properties?.description); - assert.deepStrictEqual(toolData.inputSchema.required, ['prompt', 'description']); + test('treats empty string agentName as General Purpose', async () => { + const tool = createTool(); + + const result = await tool.prepareToolInvocation( + { + parameters: { + prompt: 'Test prompt', + description: 'Test task', + agentName: '', + }, + toolCallId: 'test-call-empty', + chatSessionResource: URI.parse('test://session'), + }, + CancellationToken.None + ); + + assert.ok(result); + assert.deepStrictEqual(result.toolSpecificData, { + kind: 'subagent', + description: 'Test task', + agentName: GeneralPurposeAgentName, + prompt: 'Test prompt', + modelName: undefined, + }); }); - test('includes agentName property when SubagentToolCustomAgents is enabled', () => { - const mockToolsService = testDisposables.add(new MockLanguageModelToolsService()); - const configService = new TestConfigurationService({ - 'chat.customAgentInSubagent.enabled': true, + test('falls through to raw agentName when agent not found', async () => { + const tool = createTool(); + + const result = await tool.prepareToolInvocation( + { + parameters: { + prompt: 'Test prompt', + description: 'Test task', + agentName: 'NonExistentAgent', + }, + toolCallId: 'test-call-unknown', + chatSessionResource: URI.parse('test://session'), + }, + CancellationToken.None + ); + + assert.ok(result); + assert.deepStrictEqual(result.toolSpecificData, { + kind: 'subagent', + description: 'Test task', + agentName: 'NonExistentAgent', + prompt: 'Test prompt', + modelName: undefined, }); - const promptsService = new MockPromptsService(); + }); + }); - const tool = testDisposables.add(new RunSubagentTool( - {} as IChatAgentService, - {} as IChatService, - mockToolsService, - {} as ILanguageModelsService, - new NullLogService(), - mockToolsService, - configService, - promptsService, - {} as IInstantiationService, - )); + suite('getToolData', () => { + test('returns basic tool data', () => { + const tool = createTool(); const toolData = tool.getToolData(); - assert.ok(toolData.inputSchema?.properties?.agentName, 'agentName should be in schema when custom agents enabled'); + assert.strictEqual(toolData.id, 'runSubagent'); + assert.ok(toolData.inputSchema); + assert.ok(toolData.inputSchema.properties?.prompt); + assert.ok(toolData.inputSchema.properties?.description); + assert.ok(toolData.inputSchema.properties?.agentName); + assert.deepStrictEqual(toolData.inputSchema.required, ['prompt', 'description', 'agentName']); }); }); @@ -236,7 +282,6 @@ suite('RunSubagentTool', () => { customAgents?: ICustomAgent[]; }) { const mockToolsService = testDisposables.add(new MockLanguageModelToolsService()); - const configService = new TestConfigurationService(); const promptsService = new MockPromptsService(); if (opts.customAgents) { promptsService.setCustomModes(opts.customAgents); @@ -257,8 +302,6 @@ suite('RunSubagentTool', () => { mockToolsService, mockLanguageModelsService as ILanguageModelsService, new NullLogService(), - mockToolsService, - configService, promptsService, {} as IInstantiationService, )); @@ -438,14 +481,14 @@ suite('RunSubagentTool', () => { }); }); - test('uses main model when no subagent is specified', async () => { + test('uses main model when General Purpose agent is specified', async () => { const mainMeta = createMetadata('GPT-4o', 1); const models = new Map([['main-model-id', mainMeta]]); const tool = createTool({ models }); const result = await tool.prepareToolInvocation({ - parameters: { prompt: 'test', description: 'test task' }, + parameters: { prompt: 'test', description: 'test task', agentName: GeneralPurposeAgentName }, toolCallId: 'call-6', modelId: 'main-model-id', chatSessionResource: URI.parse('test://session'), @@ -455,7 +498,7 @@ suite('RunSubagentTool', () => { assert.deepStrictEqual(result.toolSpecificData, { kind: 'subagent', description: 'test task', - agentName: undefined, + agentName: GeneralPurposeAgentName, prompt: 'test', modelName: 'GPT-4o', }); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts index 63a328d454b56..ea3b7cd1d5452 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts @@ -184,7 +184,6 @@ export const tocData: ITOCEntry = { 'chat.editRequests', 'chat.requestQueuing.*', 'chat.undoRequests.*', - 'chat.customAgentInSubagent.*', 'chat.editing.autoAcceptDelay', 'chat.editing.confirmEditRequest*', 'chat.planAgent.defaultModel'