Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions packages/ai-native/src/browser/chat/chat.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ import 'react-chat-elements/dist/main.css';
import { IWorkspaceService } from '@opensumi/ide-workspace';

import { AI_CHAT_VIEW_ID, IChatAgentService, IChatInternalService, IChatMessageStructure } from '../../common';
import { LLMContextService, LLMContextServiceToken } from '../../common/llm-context';
import {
LLMContextService,
LLMContextServiceToken,
LLM_CONTEXT_KEY,
LLM_CONTEXT_KEY_REGEX,
} from '../../common/llm-context';
import { CodeBlockData } from '../../common/types';
import { cleanAttachedTextWrapper } from '../../common/utils';
import { FileChange, FileListDisplay } from '../components/ChangeList';
Expand Down Expand Up @@ -636,9 +641,8 @@ export const AIChatView = () => {
// 由于涉及 tool 调用,超时时间设置长一点
600 * 1000,
);

msgHistoryManager.addUserMessage({
content: message,
content: message.replaceAll(LLM_CONTEXT_KEY_REGEX, ''),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

修复关键 Bug:防止将附加键发送给 LLM

使用正则表达式移除消息中的附加文件和文件夹标记,确保这些标记不会被发送给 LLM 处理,符合 PR 的主要目标。

这个修改解决了原始问题,确保 LLM 不会处理附加的标记文本。

🤖 Prompt for AI Agents (early access)
In packages/ai-native/src/browser/chat/chat.view.tsx at line 645, the content
field should be set by removing all occurrences of additional key markers from
the message using the LLM_CONTEXT_KEY_REGEX regular expression. This prevents
sending appended file and folder tags to the LLM, ensuring only the cleaned
message content is processed. Update the code to replace all matches of
LLM_CONTEXT_KEY_REGEX in the message with an empty string before assigning it to
content.

images: images || [],
agentId: agentId!,
agentCommand: command!,
Expand Down Expand Up @@ -702,7 +706,7 @@ export const AIChatView = () => {
}
const fileUri = new URI(filePath);
const relativePath = (await workspaceService.asRelativePath(fileUri))?.path || fileUri.displayName;
processedContent = processedContent.replace(match, `\`<attached_file>${relativePath}\``);
processedContent = processedContent.replace(match, `\`${LLM_CONTEXT_KEY.AttachedFile}${relativePath}\``);
}
}

Expand All @@ -713,7 +717,7 @@ export const AIChatView = () => {
const folderPath = match.replace(/\{\{@folder:(.*?)\}\}/, '$1');
const folderUri = new URI(folderPath);
const relativePath = (await workspaceService.asRelativePath(folderUri))?.path || folderUri.displayName;
processedContent = processedContent.replace(match, `\`<attached_folder>${relativePath}\``);
processedContent = processedContent.replace(match, `\`${LLM_CONTEXT_KEY.AttachedFolder}${relativePath}\``);
}
}
const codePattern = /\{\{@code:(.*?)\}\}/g;
Expand All @@ -731,7 +735,7 @@ export const AIChatView = () => {
const relativePath = (await workspaceService.asRelativePath(fileUri))?.path || fileUri.displayName;
processedContent = processedContent.replace(
match,
`\`<attached_file>${relativePath}:L${range[0]}-${range[1]}\``,
`\`${LLM_CONTEXT_KEY.AttachedFile}${relativePath}:L${range[0]}-${range[1]}\``,
);
}
}
Expand Down
96 changes: 48 additions & 48 deletions packages/ai-native/src/browser/components/ChatMentionInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,54 +109,6 @@ export const ChatMentionInput = (props: IChatMentionInputProps) => {

// 默认菜单项
const defaultMenuItems: MentionItem[] = [
{
id: 'code',
type: 'code',
text: 'Code',
icon: getIcon('codebraces'),
getHighestLevelItems: () => [],
getItems: async (searchText: string) => {
if (!searchText || prevOutlineItems.current.length === 0) {
const uri = outlineTreeService.currentUri;
if (!uri) {
return [];
}
const treeNodes = await resolveSymbols();
prevOutlineItems.current = await Promise.all(
treeNodes.map(async (treeNode) => {
const relativePath = await workspaceService.asRelativePath(uri);
return {
id: treeNode.raw.id,
type: MentionType.CODE,
text: treeNode.raw.name,
symbol: treeNode.raw,
value: treeNode.raw.id,
description: `${relativePath?.root ? relativePath.path : ''}:L${treeNode.raw.range.startLineNumber}-${
treeNode.raw.range.endLineNumber
}`,
kind: treeNode.raw.kind,
contextId: `${outlineTreeService.currentUri?.codeUri.fsPath}:L${treeNode.raw.range.startLineNumber}-${treeNode.raw.range.endLineNumber}`,
icon: getSymbolIcon(treeNode.raw.kind) + ' outline-icon',
};
}),
);
return prevOutlineItems.current;
} else {
searchText = searchText.toLocaleLowerCase();
return prevOutlineItems.current.sort((a, b) => {
if (a.text.toLocaleLowerCase().includes(searchText) && b.text.toLocaleLowerCase().includes(searchText)) {
return 0;
}
if (a.text.toLocaleLowerCase().includes(searchText)) {
return -1;
} else if (b.text.toLocaleLowerCase().includes(searchText)) {
return 1;
}
return 0;
});
}
},
},
{
id: MentionType.FILE,
type: MentionType.FILE,
Expand Down Expand Up @@ -312,6 +264,54 @@ export const ChatMentionInput = (props: IChatMentionInputProps) => {
return folders.filter((folder) => folder.id !== new URI(workspaceService.workspace?.uri).codeUri.fsPath);
},
},
{
id: 'code',
type: 'code',
text: 'Code',
icon: getIcon('codebraces'),
getHighestLevelItems: () => [],
getItems: async (searchText: string) => {
if (!searchText || prevOutlineItems.current.length === 0) {
const uri = outlineTreeService.currentUri;
if (!uri) {
return [];
}
const treeNodes = await resolveSymbols();
prevOutlineItems.current = await Promise.all(
treeNodes.map(async (treeNode) => {
const relativePath = await workspaceService.asRelativePath(uri);
return {
id: treeNode.raw.id,
type: MentionType.CODE,
text: treeNode.raw.name,
symbol: treeNode.raw,
value: treeNode.raw.id,
description: `${relativePath?.root ? relativePath.path : ''}:L${treeNode.raw.range.startLineNumber}-${
treeNode.raw.range.endLineNumber
}`,
kind: treeNode.raw.kind,
contextId: `${outlineTreeService.currentUri?.codeUri.fsPath}:L${treeNode.raw.range.startLineNumber}-${treeNode.raw.range.endLineNumber}`,
icon: getSymbolIcon(treeNode.raw.kind) + ' outline-icon',
};
}),
);
return prevOutlineItems.current;
} else {
searchText = searchText.toLocaleLowerCase();
return prevOutlineItems.current.sort((a, b) => {
if (a.text.toLocaleLowerCase().includes(searchText) && b.text.toLocaleLowerCase().includes(searchText)) {
return 0;
}
if (a.text.toLocaleLowerCase().includes(searchText)) {
return -1;
} else if (b.text.toLocaleLowerCase().includes(searchText)) {
return 1;
}
return 0;
});
}
},
},
];

const defaultMentionInputFooterOptions: FooterConfig = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
border-radius: 4px;
padding: 0 4px;
margin: 0 3px;
font-size: 12px;
user-select: all;
cursor: default;
display: inline-flex;
Expand Down
7 changes: 7 additions & 0 deletions packages/ai-native/src/common/llm-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,10 @@ export interface SerializedContext {
attachedFiles: Array<AttachFileContext>;
attachedFolders: string[];
}

export enum LLM_CONTEXT_KEY {
AttachedFile = '<attached_file>',
AttachedFolder = '<attached_folder>',
}

export const LLM_CONTEXT_KEY_REGEX = /<attached_file>|<attached_folder>/g;
2 changes: 1 addition & 1 deletion packages/overlay/src/browser/dialog.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class DialogService extends AbstractMessageService implements IDialogServ
this._visible = false;
this.onDidDialogVisibleChangeEmitter.fire(this._visible);
this.contextkeyService.dialogViewVisibleContext.set(false);
this.deferred.resolve(value);
this.deferred?.resolve(value);
}

reset(): void {
Expand Down
Loading