diff --git a/resources/prompts/rules-block.hbs b/resources/prompts/rules-block.hbs new file mode 100644 index 000000000..d56cb7c83 --- /dev/null +++ b/resources/prompts/rules-block.hbs @@ -0,0 +1,5 @@ + + +{{{rulesFiles}}} + + diff --git a/src/common/agent.ts b/src/common/agent.ts index 4b107190d..762cda693 100644 --- a/src/common/agent.ts +++ b/src/common/agent.ts @@ -424,6 +424,7 @@ export const DEFAULT_AGENT_PROFILE: AgentProfile = { color: '#3368a8', description: '', contextMemory: ContextMemoryMode.Off, + includeRules: false, }, ruleFiles: [], }; diff --git a/src/common/locales/en.json b/src/common/locales/en.json index f6bfd63c1..0ac8dd6b5 100644 --- a/src/common/locales/en.json +++ b/src/common/locales/en.json @@ -644,6 +644,8 @@ "descriptionPlaceholder": "Describe this subagent's purpose, capabilities, and specialization and when this subagent should be invoked", "systemPrompt": "System Prompt", "systemPromptPlaceholder": "Your subagent's system prompt goes here. This can be multiple paragraphs and should clearly define the subagent's role, capabilities, and approach to solving problems.", + "includeRules": "Include project rules", + "includeRulesInformation": "When enabled, the subagent will include project rules (AGENTS.md, .aider-desk/rules/*.md) at the start of its system prompt. This is useful when the subagent needs to follow specific project guidelines.", "invocationMode": "Invocation", "invocationModeOnDemand": "On demand", "invocationModeOnDemandInformation": "Subagent is only used when explicitly requested by the user.", diff --git a/src/common/locales/zh.json b/src/common/locales/zh.json index ce1a087a8..1ad37615a 100644 --- a/src/common/locales/zh.json +++ b/src/common/locales/zh.json @@ -642,6 +642,8 @@ "descriptionPlaceholder": "描述此子代理的目的、能力和专长...", "systemPrompt": "系统提示", "systemPromptPlaceholder": "输入此配置用作子代理时的自定义系统提示指令...", + "includeRules": "包含项目规则", + "includeRulesInformation": "启用后,子代理将在其系统提示开头包含项目规则(AGENTS.md、.aider-desk/rules/*.md)。当子代理需要遵循特定项目指南时,此选项非常有用。", "invocationMode": "调用方式", "invocationModeOnDemand": "按需", "invocationModeOnDemandInformation": "子代理仅在父代理明确请求时才使用。", diff --git a/src/common/types/common.ts b/src/common/types/common.ts index 845d29a84..eae82913e 100644 --- a/src/common/types/common.ts +++ b/src/common/types/common.ts @@ -368,6 +368,7 @@ export interface SubagentConfig { invocationMode: InvocationMode; color: string; description: string; + includeRules: boolean; } export interface BashToolSettings { diff --git a/src/main/__tests__/mocks/agent-profile.ts b/src/main/__tests__/mocks/agent-profile.ts index 40c61a63d..727f2a582 100644 --- a/src/main/__tests__/mocks/agent-profile.ts +++ b/src/main/__tests__/mocks/agent-profile.ts @@ -25,6 +25,7 @@ export const createMockAgentProfile = (overrides: Partial = {}): A invocationMode: InvocationMode.Automatic, color: 'blue', description: '', + includeRules: false, }, isSubagent: false, } as AgentProfile; diff --git a/src/main/agent/__tests__/agent.test.ts b/src/main/agent/__tests__/agent.test.ts index 15abbb9e1..c5b50c28f 100644 --- a/src/main/agent/__tests__/agent.test.ts +++ b/src/main/agent/__tests__/agent.test.ts @@ -60,6 +60,16 @@ describe('Agent - getContextFilesAsToolCallMessages', () => { // Store original implementation let originalGetContextFilesMessages: any; + // Mocks that need to be accessible to all tests + let mockStore: any; + let mockAgentProfileManager: any; + let mockMcpManager: any; + let mockModelManager: any; + let mockTelemetryManager: any; + let mockMemoryManager: any; + let mockPromptsManager: any; + let mockExtensionManager: any; + beforeEach(async () => { vi.clearAllMocks(); @@ -83,15 +93,15 @@ describe('Agent - getContextFilesAsToolCallMessages', () => { mockFileTypeFromBuffer.mockResolvedValue(undefined); mockFsReadFile.mockResolvedValue(Buffer.from('file content') as any); - // Create minimal mocks for Agent constructor dependencies - const mockStore = { + // Create minimal mocks for Agent constructor dependencies - make them accessible + mockStore = { getSettings: vi.fn(() => ({})), }; - const mockAgentProfileManager = {}; - const mockMcpManager = { + mockAgentProfileManager = {}; + mockMcpManager = { getConnectors: vi.fn(() => []), }; - const mockModelManager = { + mockModelManager = { createLlm: vi.fn(), getProviderOptions: vi.fn(() => ({})), getProviderParameters: vi.fn(() => ({})), @@ -100,14 +110,15 @@ describe('Agent - getContextFilesAsToolCallMessages', () => { getProviderTools: vi.fn(() => Promise.resolve({})), isStreamingDisabled: vi.fn(() => false), }; - const mockTelemetryManager = { + mockTelemetryManager = { captureAgentRun: vi.fn(), }; - const mockMemoryManager = {}; - const mockPromptsManager = {}; - const mockExtensionManager = { + mockMemoryManager = {}; + mockPromptsManager = {}; + mockExtensionManager = { isInitialized: vi.fn(() => false), createExtensionToolset: vi.fn(() => ({})), + dispatchEvent: vi.fn().mockImplementation((_eventName, data) => data), }; agent = new AgentClass( @@ -827,4 +838,389 @@ describe('Agent - getContextFilesAsToolCallMessages', () => { expect(mockUuidv4).toHaveBeenCalled(); }); }); + + describe('systemPrompt merging', () => { + // Variables for systemPrompt merging tests + let mockPromptsManagerGetSystemPrompt: ReturnType; + let mockPromptsManagerGetRulesContent: ReturnType; + let mockPromptsManagerGetRulesBlock: ReturnType; + let mockModelManagerCreateLlm: ReturnType; + let mockProvider: any; + let mockTaskWithRun: any; + + beforeEach(async () => { + vi.clearAllMocks(); + + // Create mock for getSystemPrompt + mockPromptsManagerGetSystemPrompt = vi.fn(); + mockPromptsManagerGetRulesContent = vi.fn(); + mockPromptsManagerGetRulesBlock = vi.fn(); + + // Update the mockPromptsManager with the getSystemPrompt mock + mockPromptsManager = { + getSystemPrompt: mockPromptsManagerGetSystemPrompt, + getRulesContent: mockPromptsManagerGetRulesContent, + getRulesBlock: mockPromptsManagerGetRulesBlock, + }; + + // Add missing methods to agentProfileManager mock + mockAgentProfileManager = { + getProjectProfiles: vi.fn().mockReturnValue([]), + getProfile: vi.fn(), + }; + + // Re-create agent with updated mocks + agent = new AgentClass( + mockStore as any, + mockAgentProfileManager as any, + mockMcpManager as any, + mockModelManager as any, + mockTelemetryManager as any, + mockMemoryManager as any, + mockPromptsManager as any, + mockExtensionManager as any, + ); + + // Spy on the private method for testing + originalGetContextFilesMessages = agent['getContextFilesMessages']; + agent['getContextFilesMessages'] = vi.fn(); + + // Create mock for createLlm to capture what systemPrompt is passed + mockModelManagerCreateLlm = vi.fn().mockReturnValue({ + modelId: 'test-model', + doStream: vi.fn(), + doWrite: vi.fn(), + }); + mockModelManager.createLlm = mockModelManagerCreateLlm; + mockModelManager.normalizeMessages = vi.fn().mockImplementation((_provider, _model, messages) => messages); + + // Mock fs.readdir to return empty array to avoid skills loading issues + mockFsReadFile.mockResolvedValue(Buffer.from('file content')); + vi.mocked(fs.readdir).mockResolvedValue([]); + vi.mocked(fs.stat).mockRejectedValue(new Error('not found')); + + // Setup provider mock + mockProvider = { + id: 'anthropic', + provider: { + name: 'Anthropic', + languageModel: vi.fn().mockReturnValue({}), + }, + }; + + // Update store mock to return our provider + mockStore.getProviders = vi.fn(() => [mockProvider]); + mockStore.getSettings = vi.fn(() => ({})); + + // Create a task mock with all required methods + mockTaskWithRun = { + ...mockTask, + getContextMessages: vi.fn().mockResolvedValue([]), + getContextFiles: vi.fn().mockResolvedValue([]), + addContextMessage: vi.fn(), + addLogMessage: vi.fn(), + hookManager: { + trigger: vi.fn().mockResolvedValue({ blocked: false, event: { prompt: 'test prompt' } }), + }, + getProjectDir: vi.fn().mockReturnValue('/test/project'), + getTaskDir: vi.fn().mockReturnValue('/test/project'), + task: { + ...mockTask.task, + autoApprove: false, + }, + }; + }); + + afterEach(() => { + // Restore original method + if (originalGetContextFilesMessages) { + agent['getContextFilesMessages'] = originalGetContextFilesMessages; + } + }); + + it('should call getSystemPrompt to fetch base prompt when custom systemPrompt is provided', async () => { + // Arrange + const basePrompt = 'This is the base system prompt from project rules.'; + const customPrompt = 'This is a custom system prompt.'; + + mockPromptsManagerGetSystemPrompt.mockResolvedValue(basePrompt); + + const profile = createMockAgentProfile({ + provider: 'anthropic', + }); + + // Act + await agent.runAgent( + mockTaskWithRun, + profile, + 'test prompt', + undefined, + { id: 'test-context-id' }, + [], + [], + customPrompt, // custom systemPrompt parameter + ); + + // Assert - getSystemPrompt should have been called + expect(mockPromptsManagerGetSystemPrompt).toHaveBeenCalled(); + }); + + it('should use base prompt when no custom systemPrompt is provided', async () => { + // Arrange + const basePrompt = 'BASE_PROMPT_FROM_RULES_ONLY'; + + mockPromptsManagerGetSystemPrompt.mockResolvedValue(basePrompt); + + const profile = createMockAgentProfile({ + provider: 'anthropic', + }); + + // Act - call without custom systemPrompt parameter + await agent.runAgent( + mockTaskWithRun, + profile, + 'test prompt', + undefined, + { id: 'test-context-id' }, + [], + [], + undefined, // no custom systemPrompt + ); + + // Assert - verify only base prompt is passed to createLlm + expect(mockModelManagerCreateLlm).toHaveBeenCalled(); + const callArgs = mockModelManagerCreateLlm.mock.calls[0]; + const systemPromptPassedToModel = callArgs[5]; + + // Should contain base prompt and NOT contain any custom additions + expect(systemPromptPassedToModel).toBe(basePrompt); + }); + + it('should handle empty base prompt gracefully', async () => { + // Arrange + const customPrompt = 'CUSTOM_ONLY_PROMPT'; + + mockPromptsManagerGetSystemPrompt.mockResolvedValue(''); // empty base prompt + + const profile = createMockAgentProfile({ + provider: 'anthropic', + }); + + // Act + await agent.runAgent(mockTaskWithRun, profile, 'test prompt', undefined, { id: 'test-context-id' }, [], [], customPrompt); + + // Assert + expect(mockModelManagerCreateLlm).toHaveBeenCalled(); + const callArgs = mockModelManagerCreateLlm.mock.calls[0]; + const systemPromptPassedToModel = callArgs[5]; + + // Should just be the custom prompt when base is empty + expect(systemPromptPassedToModel).toBe(customPrompt); + }); + }); + + describe('includeRules toggle behavior for subagents', () => { + // Variables for includeRules tests + let mockPromptsManagerGetSystemPrompt: ReturnType; + let mockPromptsManagerGetRulesContent: ReturnType; + let mockPromptsManagerGetRulesBlock: ReturnType; + let mockModelManagerCreateLlm: ReturnType; + let mockProvider: any; + let mockTaskWithRun: any; + + beforeEach(async () => { + vi.clearAllMocks(); + + // Create mocks for getSystemPrompt and getRulesContent + mockPromptsManagerGetSystemPrompt = vi.fn(); + mockPromptsManagerGetRulesContent = vi.fn(); + mockPromptsManagerGetRulesBlock = vi.fn(); + + mockPromptsManager = { + getSystemPrompt: mockPromptsManagerGetSystemPrompt, + getRulesContent: mockPromptsManagerGetRulesContent, + getRulesBlock: mockPromptsManagerGetRulesBlock, + }; + + // Add missing methods to agentProfileManager mock + mockAgentProfileManager = { + getProjectProfiles: vi.fn().mockReturnValue([]), + getProfile: vi.fn(), + }; + + // Re-create agent with updated mocks + agent = new AgentClass( + mockStore as any, + mockAgentProfileManager as any, + mockMcpManager as any, + mockModelManager as any, + mockTelemetryManager as any, + mockMemoryManager as any, + mockPromptsManager as any, + mockExtensionManager as any, + ); + + // Spy on the private method for testing + originalGetContextFilesMessages = agent['getContextFilesMessages']; + agent['getContextFilesMessages'] = vi.fn(); + + // Create mock for createLlm to capture what systemPrompt is passed + mockModelManagerCreateLlm = vi.fn().mockReturnValue({ + modelId: 'test-model', + doStream: vi.fn(), + doWrite: vi.fn(), + }); + mockModelManager.createLlm = mockModelManagerCreateLlm; + mockModelManager.normalizeMessages = vi.fn().mockImplementation((_provider, _model, messages) => messages); + + // Mock fs.readdir to return empty array to avoid skills loading issues + mockFsReadFile.mockResolvedValue(Buffer.from('file content')); + vi.mocked(fs.readdir).mockResolvedValue([]); + vi.mocked(fs.stat).mockRejectedValue(new Error('not found')); + + // Setup provider mock + mockProvider = { + id: 'anthropic', + provider: { + name: 'Anthropic', + languageModel: vi.fn().mockReturnValue({}), + }, + }; + + // Update store mock to return our provider + mockStore.getProviders = vi.fn(() => [mockProvider]); + mockStore.getSettings = vi.fn(() => ({})); + + // Create a task mock with all required methods + mockTaskWithRun = { + ...mockTask, + getContextMessages: vi.fn().mockResolvedValue([]), + getContextFiles: vi.fn().mockResolvedValue([]), + addContextMessage: vi.fn(), + addLogMessage: vi.fn(), + hookManager: { + trigger: vi.fn().mockResolvedValue({ blocked: false, event: { prompt: 'test prompt' } }), + }, + getProjectDir: vi.fn().mockReturnValue('/test/project'), + getTaskDir: vi.fn().mockReturnValue('/test/project'), + task: { + ...mockTask.task, + autoApprove: false, + }, + }; + }); + + afterEach(() => { + // Restore original method + if (originalGetContextFilesMessages) { + agent['getContextFilesMessages'] = originalGetContextFilesMessages; + } + }); + + it('should use custom systemPrompt as-is when includeRules is false (default)', async () => { + // Arrange + const customSystemPrompt = 'This is the custom subagent system prompt.'; + + mockPromptsManagerGetSystemPrompt.mockResolvedValue('base prompt'); + mockPromptsManagerGetRulesContent.mockResolvedValue('rules content'); + + const profile = createMockAgentProfile({ + provider: 'anthropic', + isSubagent: true, + subagent: { + enabled: true, + systemPrompt: customSystemPrompt, + includeRules: false, // explicitly set to false + invocationMode: 'automatic' as any, + contextMemory: 'lastMessage' as any, + color: '#3368a8', + description: 'Test subagent', + }, + }); + + // Act + await agent.runAgent(mockTaskWithRun, profile, 'test prompt', undefined, { id: 'test-context-id' }, [], [], customSystemPrompt); + + // Assert + expect(mockModelManagerCreateLlm).toHaveBeenCalled(); + const callArgs = mockModelManagerCreateLlm.mock.calls[0]; + const systemPromptPassedToModel = callArgs[5]; + + // Should use ONLY the custom systemPrompt (no rules, no base prompt) + expect(systemPromptPassedToModel).toBe(customSystemPrompt); + // getRulesContent should NOT be called when includeRules is false + expect(mockPromptsManagerGetRulesContent).not.toHaveBeenCalled(); + }); + + it('should prepend rules content to custom systemPrompt when includeRules is true', async () => { + // Arrange + const rulesContent = 'RULES_CONTENT_HERE'; + const customSystemPrompt = 'CUSTOM_SYSTEM_PROMPT_HERE'; + const wrappedRules = `\n \n${rulesContent}\n \n`; + + mockPromptsManagerGetSystemPrompt.mockResolvedValue('base prompt'); + mockPromptsManagerGetRulesBlock.mockResolvedValue(wrappedRules); + + const profile = createMockAgentProfile({ + provider: 'anthropic', + isSubagent: true, + subagent: { + enabled: true, + systemPrompt: customSystemPrompt, + includeRules: true, + invocationMode: 'automatic' as any, + contextMemory: 'lastMessage' as any, + color: '#3368a8', + description: 'Test subagent', + }, + }); + + // Act + await agent.runAgent(mockTaskWithRun, profile, 'test prompt', undefined, { id: 'test-context-id' }, [], [], customSystemPrompt); + + // Assert + expect(mockModelManagerCreateLlm).toHaveBeenCalled(); + const callArgs = mockModelManagerCreateLlm.mock.calls[0]; + const systemPromptPassedToModel = callArgs[5]; + + // Should have wrapped rules in tags + '\n\n' + customSystemPrompt + const expected = `${wrappedRules}\n\n${customSystemPrompt}`; + expect(systemPromptPassedToModel).toBe(expected); + }); + + it('should behave same as false when includeRules is undefined', async () => { + // Arrange + const customSystemPrompt = 'This is the custom subagent system prompt.'; + + mockPromptsManagerGetSystemPrompt.mockResolvedValue('base prompt'); + mockPromptsManagerGetRulesContent.mockResolvedValue('rules content'); + + const profile = createMockAgentProfile({ + provider: 'anthropic', + isSubagent: true, + subagent: { + enabled: true, + systemPrompt: customSystemPrompt, + includeRules: false, + invocationMode: 'automatic' as any, + contextMemory: 'lastMessage' as any, + color: '#3368a8', + description: 'Test subagent', + }, + }); + + // Act + await agent.runAgent(mockTaskWithRun, profile, 'test prompt', undefined, { id: 'test-context-id' }, [], [], customSystemPrompt); + + // Assert + expect(mockModelManagerCreateLlm).toHaveBeenCalled(); + const callArgs = mockModelManagerCreateLlm.mock.calls[0]; + const systemPromptPassedToModel = callArgs[5]; + + // Should use ONLY the custom systemPrompt (same as when includeRules is false) + expect(systemPromptPassedToModel).toBe(customSystemPrompt); + // getRulesContent should NOT be called when includeRules is undefined + expect(mockPromptsManagerGetRulesContent).not.toHaveBeenCalled(); + }); + }); }); diff --git a/src/main/agent/agent.ts b/src/main/agent/agent.ts index 775643b3b..73a7e05b6 100644 --- a/src/main/agent/agent.ts +++ b/src/main/agent/agent.ts @@ -870,6 +870,31 @@ export class Agent { return resultMessages; } + // Get the base system prompt (project rules) + const baseSystemPrompt = await this.promptsManager.getSystemPrompt(this.store.getSettings(), task, profile); + + // Check if this is a subagent with includeRules enabled + const isSubagent = profile.isSubagent; + const includeRules = isSubagent && profile.subagent.includeRules; + + if (includeRules) { + // When includeRules is true: prepend ONLY rules content to custom systemPrompt + // (not the entire base system prompt template) + // Use rules-block template to wrap rules in tags + const wrappedRules = await this.promptsManager.getRulesBlock(task, profile); + if (systemPrompt && wrappedRules) { + systemPrompt = `${wrappedRules} + +${systemPrompt}`; + } else if (!systemPrompt) { + systemPrompt = wrappedRules || ''; + } + } else if (!systemPrompt) { + // No custom systemPrompt provided, use base system prompt (main agent default) + systemPrompt = baseSystemPrompt; + } + // When includeRules is false and systemPrompt is provided, use it as-is (no merging) + const toolSet = await this.getAvailableTools( task, mode, @@ -1691,7 +1716,36 @@ export class Agent { const messages = await this.prepareMessages(task, profile, await task.getContextMessages(), await task.getContextFiles()); const toolSet = await this.getAvailableTools(task, 'agent', profile, provider, profile.model); - const systemPrompt = await this.promptsManager.getSystemPrompt(this.store.getSettings(), task, profile); + + // Get the base system prompt (project rules) + const baseSystemPrompt = await this.promptsManager.getSystemPrompt(this.store.getSettings(), task, profile); + + // Check if this is a subagent with includeRules enabled + const isSubagent = profile.isSubagent; + const includeRules = isSubagent && profile.subagent.includeRules; + + // Get custom systemPrompt from subagent profile (if this is a subagent) + const customSystemPrompt = isSubagent ? profile.subagent.systemPrompt : undefined; + + let systemPrompt: string | undefined; + if (includeRules) { + // When includeRules is true: prepend ONLY rules content to custom systemPrompt + // Use rules-block template to wrap rules in tags + const wrappedRules = await this.promptsManager.getRulesBlock(task, profile); + if (customSystemPrompt && wrappedRules) { + systemPrompt = `${wrappedRules} + +${customSystemPrompt}`; + } else if (!customSystemPrompt) { + systemPrompt = wrappedRules || ''; + } + } else if (customSystemPrompt) { + // When includeRules is false and custom systemPrompt provided, use it as-is + systemPrompt = customSystemPrompt; + } else { + // No custom systemPrompt provided, use base system prompt + systemPrompt = baseSystemPrompt; + } const cacheControl = this.modelManager.getCacheControl(profile, provider.provider); @@ -1720,7 +1774,7 @@ export class Agent { role: 'system', content: toolDefinitionsString, }); - optimizedMessages.unshift({ role: 'system', content: systemPrompt }); + optimizedMessages.unshift({ role: 'system', content: systemPrompt || '' }); const chatMessages = optimizedMessages.map((msg) => ({ role: msg.role === 'tool' ? 'user' : msg.role, // Map 'tool' role to user message as gpt-tokenizer does not support tool messages diff --git a/src/main/extensions/__tests__/agent-integration.test.ts b/src/main/extensions/__tests__/agent-integration.test.ts index 569193f0a..f8c4af0b3 100644 --- a/src/main/extensions/__tests__/agent-integration.test.ts +++ b/src/main/extensions/__tests__/agent-integration.test.ts @@ -138,6 +138,7 @@ const createMockProfile = (): AgentProfile => ({ invocationMode: 'on-demand' as InvocationMode, color: '#000', description: '', + includeRules: false, }, }); diff --git a/src/main/prompts/prompts-manager.ts b/src/main/prompts/prompts-manager.ts index 823cc0974..3c9c48d1e 100644 --- a/src/main/prompts/prompts-manager.ts +++ b/src/main/prompts/prompts-manager.ts @@ -123,6 +123,7 @@ export class PromptsManager { 'update-task-state', 'handoff', 'code-inline-request', + 'rules-block', ]; } @@ -382,7 +383,7 @@ export class PromptsManager { return await this.render('system-prompt', data, projectDir, task); }; - private getRulesContent = async (task: Task, agentProfile?: AgentProfile) => { + public getRulesContent = async (task: Task, agentProfile?: AgentProfile) => { const ruleFiles = await task.getRuleFilesAsContextFiles(agentProfile); const ruleFilesContent = await Promise.all( @@ -411,6 +412,14 @@ export class PromptsManager { return ruleFilesContent.filter(Boolean).join('\n'); }; + public getRulesBlock = async (task: Task, agentProfile?: AgentProfile): Promise => { + const rulesFiles = await this.getRulesContent(task, agentProfile); + if (!rulesFiles) { + return ''; + } + return this.render('rules-block', { rulesFiles }, task.getProjectDir()); + }; + public getInitProjectPrompt = async (task: Task) => { const data: InitProjectPromptData = {}; return await this.render('init-project', data, task.getProjectDir(), task); diff --git a/src/main/prompts/types.ts b/src/main/prompts/types.ts index 71353fdb2..2095a5156 100644 --- a/src/main/prompts/types.ts +++ b/src/main/prompts/types.ts @@ -102,4 +102,5 @@ export type PromptTemplateName = | 'conflict-resolution-system' | 'update-task-state' | 'handoff' - | 'code-inline-request'; + | 'code-inline-request' + | 'rules-block'; diff --git a/src/renderer/src/components/settings/agent/AgentSettings.tsx b/src/renderer/src/components/settings/agent/AgentSettings.tsx index b420fb85e..0bf93048a 100644 --- a/src/renderer/src/components/settings/agent/AgentSettings.tsx +++ b/src/renderer/src/components/settings/agent/AgentSettings.tsx @@ -1274,6 +1274,19 @@ export const AgentSettings = ({ placeholder={t('settings.agent.subagent.systemPromptPlaceholder')} /> +
+ + {t('settings.agent.subagent.includeRules')} + +
+ } + checked={selectedProfile.subagent.includeRules} + onChange={(checked) => handleProfileSettingChange('subagent', { ...selectedProfile.subagent, includeRules: checked })} + /> + +