Browse Source

Merge pull request #305 from RooVetGit/only_load_context_in_user_input

Only load context and parse @-mentions in user input
Matt Rubens 1 year ago
parent
commit
748556528a
3 changed files with 99 additions and 9 deletions
  1. 5 0
      .changeset/odd-news-yell.md
  2. 18 9
      src/core/Cline.ts
  3. 76 0
      src/core/__tests__/Cline.test.ts

+ 5 - 0
.changeset/odd-news-yell.md

@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Only parse @-mentions in user input (not in files)

+ 18 - 9
src/core/Cline.ts

@@ -2360,22 +2360,30 @@ export class Cline {
 			// 2. ToolResultBlockParam's content/context text arrays if it contains "<feedback>" (see formatToolDeniedFeedback, attemptCompletion, executeCommand, and consecutiveMistakeCount >= 3) or "<answer>" (see askFollowupQuestion), we place all user generated content in these tags so they can effectively be used as markers for when we should parse mentions)
 			Promise.all(
 				userContent.map(async (block) => {
+					const shouldProcessMentions = (text: string) =>
+						text.includes("<task>") || text.includes("<feedback>");
+
 					if (block.type === "text") {
-						return {
-							...block,
-							text: await parseMentions(block.text, cwd, this.urlContentFetcher),
-						}
-					} else if (block.type === "tool_result") {
-						const isUserMessage = (text: string) => text.includes("<feedback>") || text.includes("<answer>")
-						if (typeof block.content === "string" && isUserMessage(block.content)) {
+						if (shouldProcessMentions(block.text)) {
 							return {
 								...block,
-								content: await parseMentions(block.content, cwd, this.urlContentFetcher),
+								text: await parseMentions(block.text, cwd, this.urlContentFetcher),
+							}
+						}
+						return block;
+					} else if (block.type === "tool_result") {
+						if (typeof block.content === "string") {
+							if (shouldProcessMentions(block.content)) {
+								return {
+									...block,
+									content: await parseMentions(block.content, cwd, this.urlContentFetcher),
+								}
 							}
+							return block;
 						} else if (Array.isArray(block.content)) {
 							const parsedContent = await Promise.all(
 								block.content.map(async (contentBlock) => {
-									if (contentBlock.type === "text" && isUserMessage(contentBlock.text)) {
+									if (contentBlock.type === "text" && shouldProcessMentions(contentBlock.text)) {
 										return {
 											...contentBlock,
 											text: await parseMentions(contentBlock.text, cwd, this.urlContentFetcher),
@@ -2389,6 +2397,7 @@ export class Cline {
 								content: parsedContent,
 							}
 						}
+						return block;
 					}
 					return block
 				}),

+ 76 - 0
src/core/__tests__/Cline.test.ts

@@ -626,6 +626,82 @@ describe('Cline', () => {
                     text: '[Referenced image in conversation]'
                 });
             });
+        
+            describe('loadContext', () => {
+                it('should process mentions in task and feedback tags', async () => {
+                    const cline = new Cline(
+                        mockProvider,
+                        mockApiConfig,
+                        undefined,
+                        false,
+                        undefined,
+                        'test task'
+                    );
+        
+                    // Mock parseMentions to track calls
+                    const mockParseMentions = jest.fn().mockImplementation(text => `processed: ${text}`);
+                    jest.spyOn(require('../../core/mentions'), 'parseMentions').mockImplementation(mockParseMentions);
+        
+                    const userContent = [
+                        {
+                            type: 'text',
+                            text: 'Regular text with @/some/path'
+                        } as const,
+                        {
+                            type: 'text',
+                            text: '<task>Text with @/some/path in task tags</task>'
+                        } as const,
+                        {
+                            type: 'tool_result',
+                            tool_use_id: 'test-id',
+                            content: [{
+                                type: 'text',
+                                text: '<feedback>Check @/some/path</feedback>'
+                            }]
+                        } as Anthropic.ToolResultBlockParam,
+                        {
+                            type: 'tool_result',
+                            tool_use_id: 'test-id-2',
+                            content: [{
+                                type: 'text',
+                                text: 'Regular tool result with @/path'
+                            }]
+                        } as Anthropic.ToolResultBlockParam
+                    ];
+        
+                    // Process the content
+                    const [processedContent] = await cline['loadContext'](userContent);
+        
+                    // Regular text should not be processed
+                    expect((processedContent[0] as Anthropic.TextBlockParam).text)
+                        .toBe('Regular text with @/some/path');
+        
+                    // Text within task tags should be processed
+                    expect((processedContent[1] as Anthropic.TextBlockParam).text)
+                        .toContain('processed:');
+                    expect(mockParseMentions).toHaveBeenCalledWith(
+                        '<task>Text with @/some/path in task tags</task>',
+                        expect.any(String),
+                        expect.any(Object)
+                    );
+        
+                    // Feedback tag content should be processed
+                    const toolResult1 = processedContent[2] as Anthropic.ToolResultBlockParam;
+                    const content1 = Array.isArray(toolResult1.content) ? toolResult1.content[0] : toolResult1.content;
+                    expect((content1 as Anthropic.TextBlockParam).text).toContain('processed:');
+                    expect(mockParseMentions).toHaveBeenCalledWith(
+                        '<feedback>Check @/some/path</feedback>',
+                        expect.any(String),
+                        expect.any(Object)
+                    );
+        
+                    // Regular tool result should not be processed
+                    const toolResult2 = processedContent[3] as Anthropic.ToolResultBlockParam;
+                    const content2 = Array.isArray(toolResult2.content) ? toolResult2.content[0] : toolResult2.content;
+                    expect((content2 as Anthropic.TextBlockParam).text)
+                        .toBe('Regular tool result with @/path');
+                });
+            });
         });
     });
 });