@opensumi/ide-ai-native 3.9.1-next-1749452811.0 → 3.9.1-next-1749538805.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/ai-core.contribution.d.ts.map +1 -1
- package/lib/browser/ai-core.contribution.js +9 -4
- package/lib/browser/ai-core.contribution.js.map +1 -1
- package/lib/browser/chat/apply.service.d.ts +3 -0
- package/lib/browser/chat/apply.service.d.ts.map +1 -1
- package/lib/browser/chat/apply.service.js +47 -0
- package/lib/browser/chat/apply.service.js.map +1 -1
- package/lib/browser/chat/chat-manager.service.d.ts +1 -0
- package/lib/browser/chat/chat-manager.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-manager.service.js +9 -3
- package/lib/browser/chat/chat-manager.service.js.map +1 -1
- package/lib/browser/chat/chat-model.d.ts +8 -1
- package/lib/browser/chat/chat-model.d.ts.map +1 -1
- package/lib/browser/chat/chat-model.js +113 -76
- package/lib/browser/chat/chat-model.js.map +1 -1
- package/lib/browser/chat/chat-proxy.service.d.ts +0 -2
- package/lib/browser/chat/chat-proxy.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-proxy.service.js +50 -57
- package/lib/browser/chat/chat-proxy.service.js.map +1 -1
- package/lib/browser/chat/chat.feature.registry.d.ts +4 -1
- package/lib/browser/chat/chat.feature.registry.d.ts.map +1 -1
- package/lib/browser/chat/chat.feature.registry.js +6 -0
- package/lib/browser/chat/chat.feature.registry.js.map +1 -1
- package/lib/browser/chat/chat.view.d.ts.map +1 -1
- package/lib/browser/chat/chat.view.js +50 -10
- package/lib/browser/chat/chat.view.js.map +1 -1
- package/lib/browser/components/ChatEditor.js +2 -2
- package/lib/browser/components/ChatEditor.js.map +1 -1
- package/lib/browser/components/ChatHistory.d.ts.map +1 -1
- package/lib/browser/components/ChatHistory.js +2 -1
- package/lib/browser/components/ChatHistory.js.map +1 -1
- package/lib/browser/components/ChatMentionInput.d.ts.map +1 -1
- package/lib/browser/components/ChatMentionInput.js +148 -30
- package/lib/browser/components/ChatMentionInput.js.map +1 -1
- package/lib/browser/components/ChatReply.js +2 -2
- package/lib/browser/components/ChatReply.js.map +1 -1
- package/lib/browser/components/ChatToolRender.d.ts.map +1 -1
- package/lib/browser/components/ChatToolRender.js +7 -2
- package/lib/browser/components/ChatToolRender.js.map +1 -1
- package/lib/browser/components/ChatToolRender.module.less +25 -0
- package/lib/browser/components/components.module.less +37 -8
- package/lib/browser/components/mention-input/mention-input.d.ts.map +1 -1
- package/lib/browser/components/mention-input/mention-input.js +150 -14
- package/lib/browser/components/mention-input/mention-input.js.map +1 -1
- package/lib/browser/components/mention-input/mention-input.module.less +165 -1
- package/lib/browser/components/mention-input/mention-select.d.ts +28 -0
- package/lib/browser/components/mention-input/mention-select.d.ts.map +1 -0
- package/lib/browser/components/mention-input/mention-select.js +136 -0
- package/lib/browser/components/mention-input/mention-select.js.map +1 -0
- package/lib/browser/components/mention-input/mention-select.module.less +297 -0
- package/lib/browser/components/mention-input/types.d.ts +28 -1
- package/lib/browser/components/mention-input/types.d.ts.map +1 -1
- package/lib/browser/components/mention-input/types.js +1 -0
- package/lib/browser/components/mention-input/types.js.map +1 -1
- package/lib/browser/components/utils.d.ts +2 -2
- package/lib/browser/context/llm-context.service.d.ts +21 -2
- package/lib/browser/context/llm-context.service.d.ts.map +1 -1
- package/lib/browser/context/llm-context.service.js +162 -20
- package/lib/browser/context/llm-context.service.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/decoration/additions-deletions.decoration.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/decoration/additions-deletions.decoration.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/diff-computer.js +1 -1
- package/lib/browser/contrib/intelligent-completions/diff-computer.js.map +1 -1
- package/lib/browser/contrib/terminal/terminal.feature.registry.js.map +1 -1
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +7 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/layout/ai-layout.d.ts.map +1 -1
- package/lib/browser/layout/ai-layout.js +6 -4
- package/lib/browser/layout/ai-layout.js.map +1 -1
- package/lib/browser/layout/tabbar.view.d.ts +1 -1
- package/lib/browser/layout/tabbar.view.d.ts.map +1 -1
- package/lib/browser/layout/tabbar.view.js +5 -12
- package/lib/browser/layout/tabbar.view.js.map +1 -1
- package/lib/browser/mcp/base-apply.service.d.ts +5 -4
- package/lib/browser/mcp/base-apply.service.d.ts.map +1 -1
- package/lib/browser/mcp/base-apply.service.js +23 -5
- package/lib/browser/mcp/base-apply.service.js.map +1 -1
- package/lib/browser/mcp/mcp-server-proxy.service.d.ts +3 -1
- package/lib/browser/mcp/mcp-server-proxy.service.d.ts.map +1 -1
- package/lib/browser/mcp/mcp-server-proxy.service.js +4 -0
- package/lib/browser/mcp/mcp-server-proxy.service.js.map +1 -1
- package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -1
- package/lib/browser/mcp/mcp-server.feature.registry.js +7 -1
- package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -1
- package/lib/browser/mcp/tools/createNewFileWithText.d.ts +1 -3
- package/lib/browser/mcp/tools/createNewFileWithText.d.ts.map +1 -1
- package/lib/browser/mcp/tools/createNewFileWithText.js +14 -40
- package/lib/browser/mcp/tools/createNewFileWithText.js.map +1 -1
- package/lib/browser/mcp/tools/fileSearch.d.ts.map +1 -1
- package/lib/browser/mcp/tools/fileSearch.js +9 -5
- package/lib/browser/mcp/tools/fileSearch.js.map +1 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js.map +1 -1
- package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js.map +1 -1
- package/lib/browser/mcp/tools/grepSearch.d.ts.map +1 -1
- package/lib/browser/mcp/tools/grepSearch.js +22 -10
- package/lib/browser/mcp/tools/grepSearch.js.map +1 -1
- package/lib/browser/mcp/tools/handlers/CreateNewFileWithText.d.ts +15 -0
- package/lib/browser/mcp/tools/handlers/CreateNewFileWithText.d.ts.map +1 -0
- package/lib/browser/mcp/tools/handlers/CreateNewFileWithText.js +53 -0
- package/lib/browser/mcp/tools/handlers/CreateNewFileWithText.js.map +1 -0
- package/lib/browser/mcp/tools/handlers/ListDir.js +1 -1
- package/lib/browser/mcp/tools/handlers/ListDir.js.map +1 -1
- package/lib/browser/mcp/tools/handlers/ReadFile.js +1 -1
- package/lib/browser/mcp/tools/handlers/ReadFile.js.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts +11 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.js +11 -4
- package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -1
- package/lib/browser/mcp/tools/listDir.d.ts.map +1 -1
- package/lib/browser/mcp/tools/listDir.js +19 -15
- package/lib/browser/mcp/tools/listDir.js.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -1
- package/lib/browser/model/msg-history-manager.d.ts +47 -1
- package/lib/browser/model/msg-history-manager.d.ts.map +1 -1
- package/lib/browser/model/msg-history-manager.js +127 -2
- package/lib/browser/model/msg-history-manager.js.map +1 -1
- package/lib/browser/preferences/schema.d.ts.map +1 -1
- package/lib/browser/preferences/schema.js +5 -0
- package/lib/browser/preferences/schema.js.map +1 -1
- package/lib/browser/rules/rules.contribution.d.ts +29 -0
- package/lib/browser/rules/rules.contribution.d.ts.map +1 -0
- package/lib/browser/rules/rules.contribution.js +94 -0
- package/lib/browser/rules/rules.contribution.js.map +1 -0
- package/lib/browser/rules/rules.module.less +175 -0
- package/lib/browser/rules/rules.service.d.ts +25 -0
- package/lib/browser/rules/rules.service.d.ts.map +1 -0
- package/lib/browser/rules/rules.service.js +180 -0
- package/lib/browser/rules/rules.service.js.map +1 -0
- package/lib/browser/rules/rules.view.d.ts +3 -0
- package/lib/browser/rules/rules.view.d.ts.map +1 -0
- package/lib/browser/rules/rules.view.js +76 -0
- package/lib/browser/rules/rules.view.js.map +1 -0
- package/lib/browser/types.d.ts +12 -1
- package/lib/browser/types.d.ts.map +1 -1
- package/lib/browser/types.js.map +1 -1
- package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts.map +1 -1
- package/lib/browser/widget/inline-stream-diff/live-preview.component.js.map +1 -1
- package/lib/common/image-compression.d.ts +25 -0
- package/lib/common/image-compression.d.ts.map +1 -0
- package/lib/common/image-compression.js +153 -0
- package/lib/common/image-compression.js.map +1 -0
- package/lib/common/index.d.ts +5 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +2 -0
- package/lib/common/index.js.map +1 -1
- package/lib/common/llm-context.d.ts +19 -0
- package/lib/common/llm-context.d.ts.map +1 -1
- package/lib/common/llm-context.js.map +1 -1
- package/lib/common/mdc-parser.d.ts +60 -0
- package/lib/common/mdc-parser.d.ts.map +1 -0
- package/lib/common/mdc-parser.js +246 -0
- package/lib/common/mdc-parser.js.map +1 -0
- package/lib/common/model.d.ts +1 -0
- package/lib/common/model.d.ts.map +1 -1
- package/lib/common/model.js.map +1 -1
- package/lib/common/prompts/context-prompt-provider.d.ts +0 -2
- package/lib/common/prompts/context-prompt-provider.d.ts.map +1 -1
- package/lib/common/prompts/context-prompt-provider.js +35 -29
- package/lib/common/prompts/context-prompt-provider.js.map +1 -1
- package/lib/common/prompts/system-prompt.d.ts +2 -0
- package/lib/common/prompts/system-prompt.d.ts.map +1 -0
- package/lib/common/prompts/system-prompt.js +5 -0
- package/lib/common/prompts/system-prompt.js.map +1 -0
- package/lib/common/types.d.ts +21 -0
- package/lib/common/types.d.ts.map +1 -1
- package/lib/common/types.js.map +1 -1
- package/lib/common/utils.d.ts +1 -0
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +5 -2
- package/lib/common/utils.js.map +1 -1
- package/lib/node/anthropic/anthropic-language-model.d.ts +1 -1
- package/lib/node/base-language-model.d.ts +2 -1
- package/lib/node/base-language-model.d.ts.map +1 -1
- package/lib/node/base-language-model.js +12 -2
- package/lib/node/base-language-model.js.map +1 -1
- package/lib/node/deepseek/deepseek-language-model.d.ts +1 -1
- package/lib/node/mcp/sumi-mcp-server.d.ts +3 -1
- package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -1
- package/lib/node/mcp/sumi-mcp-server.js +7 -1
- package/lib/node/mcp/sumi-mcp-server.js.map +1 -1
- package/lib/node/mcp-server-manager-impl.d.ts +3 -1
- package/lib/node/mcp-server-manager-impl.d.ts.map +1 -1
- package/lib/node/mcp-server-manager-impl.js +14 -2
- package/lib/node/mcp-server-manager-impl.js.map +1 -1
- package/lib/node/mcp-server.sse.d.ts +187 -1
- package/lib/node/mcp-server.sse.d.ts.map +1 -1
- package/lib/node/mcp-server.sse.js +2 -2
- package/lib/node/mcp-server.sse.js.map +1 -1
- package/lib/node/mcp-server.stdio.d.ts +187 -1
- package/lib/node/mcp-server.stdio.d.ts.map +1 -1
- package/package.json +27 -26
- package/src/browser/ai-core.contribution.ts +14 -4
- package/src/browser/chat/apply.service.ts +62 -1
- package/src/browser/chat/chat-manager.service.ts +16 -7
- package/src/browser/chat/chat-model.ts +130 -73
- package/src/browser/chat/chat-proxy.service.ts +68 -81
- package/src/browser/chat/chat.feature.registry.ts +17 -1
- package/src/browser/chat/chat.view.tsx +73 -12
- package/src/browser/components/ChatEditor.tsx +1 -1
- package/src/browser/components/ChatHistory.tsx +2 -1
- package/src/browser/components/ChatMentionInput.tsx +180 -35
- package/src/browser/components/ChatReply.tsx +4 -4
- package/src/browser/components/ChatToolRender.module.less +25 -0
- package/src/browser/components/ChatToolRender.tsx +10 -2
- package/src/browser/components/components.module.less +37 -8
- package/src/browser/components/mention-input/mention-input.module.less +165 -1
- package/src/browser/components/mention-input/mention-input.tsx +232 -31
- package/src/browser/components/mention-input/mention-select.module.less +297 -0
- package/src/browser/components/mention-input/mention-select.tsx +256 -0
- package/src/browser/components/mention-input/types.ts +29 -0
- package/src/browser/context/llm-context.service.ts +182 -21
- package/src/browser/contrib/intelligent-completions/decoration/additions-deletions.decoration.ts +1 -1
- package/src/browser/contrib/intelligent-completions/diff-computer.ts +1 -1
- package/src/browser/contrib/terminal/terminal.feature.registry.ts +1 -1
- package/src/browser/index.ts +8 -0
- package/src/browser/layout/ai-layout.tsx +12 -8
- package/src/browser/layout/tabbar.view.tsx +10 -23
- package/src/browser/mcp/base-apply.service.ts +30 -10
- package/src/browser/mcp/mcp-server-proxy.service.ts +6 -1
- package/src/browser/mcp/mcp-server.feature.registry.ts +6 -1
- package/src/browser/mcp/tools/createNewFileWithText.ts +17 -46
- package/src/browser/mcp/tools/fileSearch.ts +8 -5
- package/src/browser/mcp/tools/getDiagnosticsByPath.ts +1 -1
- package/src/browser/mcp/tools/getOpenEditorFileDiagnostics.ts +1 -1
- package/src/browser/mcp/tools/grepSearch.ts +32 -21
- package/src/browser/mcp/tools/handlers/CreateNewFileWithText.ts +49 -0
- package/src/browser/mcp/tools/handlers/ListDir.ts +2 -2
- package/src/browser/mcp/tools/handlers/ReadFile.ts +2 -2
- package/src/browser/mcp/tools/handlers/RunCommand.ts +21 -14
- package/src/browser/mcp/tools/listDir.ts +15 -12
- package/src/browser/mcp/tools/runTerminalCmd.ts +1 -1
- package/src/browser/model/msg-history-manager.ts +181 -2
- package/src/browser/preferences/schema.ts +5 -0
- package/src/browser/rules/rules.contribution.ts +105 -0
- package/src/browser/rules/rules.module.less +175 -0
- package/src/browser/rules/rules.service.ts +189 -0
- package/src/browser/rules/rules.view.tsx +127 -0
- package/src/browser/types.ts +18 -0
- package/src/browser/widget/inline-stream-diff/live-preview.component.tsx +0 -1
- package/src/common/image-compression.ts +174 -0
- package/src/common/index.ts +6 -1
- package/src/common/llm-context.ts +23 -0
- package/src/common/mdc-parser.ts +295 -0
- package/src/common/model.ts +1 -0
- package/src/common/prompts/context-prompt-provider.ts +55 -40
- package/src/common/prompts/system-prompt.ts +2 -0
- package/src/common/types.ts +18 -0
- package/src/common/utils.ts +4 -1
- package/src/node/base-language-model.ts +11 -14
- package/src/node/mcp/sumi-mcp-server.ts +10 -2
- package/src/node/mcp-server-manager-impl.ts +17 -2
- package/src/node/mcp-server.sse.ts +1 -2
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import cls from 'classnames';
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { ClickOutside } from '@opensumi/ide-components/lib/click-outside';
|
|
5
|
+
import { Icon, getIcon } from '@opensumi/ide-core-browser/lib/components';
|
|
6
|
+
|
|
7
|
+
import styles from './mention-select.module.less';
|
|
8
|
+
|
|
9
|
+
export interface ExtendedModelOption {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
icon?: string;
|
|
13
|
+
iconClass?: string;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
features?: string[];
|
|
16
|
+
description?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
badge?: string;
|
|
19
|
+
badgeColor?: string;
|
|
20
|
+
selected?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface MentionSelectProps {
|
|
24
|
+
options: ExtendedModelOption[];
|
|
25
|
+
value?: string;
|
|
26
|
+
onChange?: (value: string) => void;
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
className?: string;
|
|
30
|
+
size?: 'small' | 'medium' | 'large';
|
|
31
|
+
showThinking?: boolean;
|
|
32
|
+
thinkingEnabled?: boolean;
|
|
33
|
+
onThinkingChange?: (enabled: boolean) => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const ThinkingToggle: React.FC<{
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
onChange: (enabled: boolean) => void;
|
|
39
|
+
}> = ({ enabled, onChange }) => (
|
|
40
|
+
<div className={styles.thinking_toggle} onClick={() => onChange(!enabled)}>
|
|
41
|
+
<Icon
|
|
42
|
+
iconClass={getIcon(enabled ? 'check' : 'circle-outline')}
|
|
43
|
+
className={cls(styles.thinking_icon, {
|
|
44
|
+
[styles.enabled]: enabled,
|
|
45
|
+
})}
|
|
46
|
+
/>
|
|
47
|
+
<span className={styles.thinking_label}>Thinking</span>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
export const MentionSelect: React.FC<MentionSelectProps> = ({
|
|
52
|
+
options,
|
|
53
|
+
value,
|
|
54
|
+
onChange,
|
|
55
|
+
placeholder,
|
|
56
|
+
disabled = false,
|
|
57
|
+
className,
|
|
58
|
+
size = 'small',
|
|
59
|
+
showThinking = false,
|
|
60
|
+
thinkingEnabled = false,
|
|
61
|
+
onThinkingChange,
|
|
62
|
+
}) => {
|
|
63
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
64
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
65
|
+
const [dropdownDirection, setDropdownDirection] = useState<'up' | 'down'>('up');
|
|
66
|
+
const selectRef = useRef<HTMLDivElement>(null);
|
|
67
|
+
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
68
|
+
|
|
69
|
+
const selectedOption = options.find((option) => option.selected) || options.find((option) => option.value === value);
|
|
70
|
+
|
|
71
|
+
const handleToggle = () => {
|
|
72
|
+
if (!disabled) {
|
|
73
|
+
setIsOpen(!isOpen);
|
|
74
|
+
setActiveIndex(-1);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const handleSelect = (option: ExtendedModelOption) => {
|
|
79
|
+
if (!option.disabled) {
|
|
80
|
+
onChange?.(option.value);
|
|
81
|
+
setIsOpen(false);
|
|
82
|
+
setActiveIndex(-1);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
87
|
+
if (disabled) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
switch (e.key) {
|
|
92
|
+
case 'Enter':
|
|
93
|
+
case ' ':
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
if (!isOpen) {
|
|
96
|
+
setIsOpen(true);
|
|
97
|
+
} else if (activeIndex >= 0) {
|
|
98
|
+
handleSelect(options[activeIndex]);
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
case 'Escape':
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
setIsOpen(false);
|
|
104
|
+
setActiveIndex(-1);
|
|
105
|
+
break;
|
|
106
|
+
case 'ArrowDown':
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
if (!isOpen) {
|
|
109
|
+
setIsOpen(true);
|
|
110
|
+
} else {
|
|
111
|
+
setActiveIndex((prev) => (prev < options.length - 1 ? prev + 1 : 0));
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
case 'ArrowUp':
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
if (isOpen) {
|
|
117
|
+
setActiveIndex((prev) => (prev > 0 ? prev - 1 : options.length - 1));
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const handleClickOutside = () => {
|
|
124
|
+
setIsOpen(false);
|
|
125
|
+
setActiveIndex(-1);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (isOpen && selectRef.current) {
|
|
130
|
+
const selectRect = selectRef.current.getBoundingClientRect();
|
|
131
|
+
const viewportHeight = window.innerHeight;
|
|
132
|
+
const dropdownHeight = Math.min(400, options.length * 60);
|
|
133
|
+
|
|
134
|
+
const spaceAbove = selectRect.top;
|
|
135
|
+
const spaceBelow = viewportHeight - selectRect.bottom;
|
|
136
|
+
|
|
137
|
+
if (spaceAbove < dropdownHeight && spaceBelow > spaceAbove) {
|
|
138
|
+
setDropdownDirection('down');
|
|
139
|
+
} else {
|
|
140
|
+
setDropdownDirection('up');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}, [isOpen, options.length]);
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (isOpen && activeIndex >= 0 && dropdownRef.current) {
|
|
147
|
+
const activeElement = dropdownRef.current.children[activeIndex] as HTMLElement;
|
|
148
|
+
if (activeElement) {
|
|
149
|
+
activeElement.scrollIntoView({
|
|
150
|
+
behavior: 'smooth',
|
|
151
|
+
block: 'nearest',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}, [isOpen, activeIndex]);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<ClickOutside onOutsideClick={handleClickOutside}>
|
|
159
|
+
<div
|
|
160
|
+
ref={selectRef}
|
|
161
|
+
className={cls(
|
|
162
|
+
styles.mention_select,
|
|
163
|
+
styles[`size_${size}`],
|
|
164
|
+
{
|
|
165
|
+
[styles.disabled]: disabled,
|
|
166
|
+
[styles.open]: isOpen,
|
|
167
|
+
[styles.dropdown_up]: dropdownDirection === 'up',
|
|
168
|
+
[styles.dropdown_down]: dropdownDirection === 'down',
|
|
169
|
+
},
|
|
170
|
+
className,
|
|
171
|
+
)}
|
|
172
|
+
onClick={handleToggle}
|
|
173
|
+
onKeyDown={handleKeyDown}
|
|
174
|
+
tabIndex={disabled ? -1 : 0}
|
|
175
|
+
role='combobox'
|
|
176
|
+
aria-expanded={isOpen}
|
|
177
|
+
aria-haspopup='listbox'
|
|
178
|
+
>
|
|
179
|
+
<div className={styles.select_trigger}>
|
|
180
|
+
<div className={styles.select_content}>
|
|
181
|
+
{selectedOption ? (
|
|
182
|
+
<div className={styles.selected_option}>
|
|
183
|
+
<span className={styles.option_label}>{selectedOption.label}</span>
|
|
184
|
+
{selectedOption.badge && (
|
|
185
|
+
<span className={styles.option_badge} style={{ backgroundColor: selectedOption.badgeColor }}>
|
|
186
|
+
{selectedOption.badge}
|
|
187
|
+
</span>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
) : (
|
|
191
|
+
<span className={styles.placeholder}>{placeholder}</span>
|
|
192
|
+
)}
|
|
193
|
+
</div>
|
|
194
|
+
<Icon
|
|
195
|
+
iconClass={getIcon('down-arrow')}
|
|
196
|
+
className={cls(styles.dropdown_arrow, {
|
|
197
|
+
[styles.open]: isOpen,
|
|
198
|
+
})}
|
|
199
|
+
/>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
{isOpen && (
|
|
203
|
+
<div ref={dropdownRef} className={styles.dropdown} role='listbox'>
|
|
204
|
+
{showThinking && onThinkingChange && (
|
|
205
|
+
<div className={styles.thinking_section}>
|
|
206
|
+
<ThinkingToggle enabled={thinkingEnabled} onChange={onThinkingChange} />
|
|
207
|
+
<div className={styles.divider} />
|
|
208
|
+
</div>
|
|
209
|
+
)}
|
|
210
|
+
|
|
211
|
+
{options.map((option, index) => (
|
|
212
|
+
<div
|
|
213
|
+
key={option.value}
|
|
214
|
+
className={cls(styles.option, {
|
|
215
|
+
[styles.active]: index === activeIndex,
|
|
216
|
+
[styles.selected]: option.selected || option.value === value,
|
|
217
|
+
[styles.disabled]: option.disabled,
|
|
218
|
+
})}
|
|
219
|
+
onClick={() => handleSelect(option)}
|
|
220
|
+
role='option'
|
|
221
|
+
aria-selected={option.selected || option.value === value}
|
|
222
|
+
>
|
|
223
|
+
<div className={styles.option_main}>
|
|
224
|
+
<div className={styles.option_header}>
|
|
225
|
+
<div className={styles.option_title}>
|
|
226
|
+
{option.icon && <Icon icon={option.icon} className={styles.option_icon} />}
|
|
227
|
+
{option.iconClass && <Icon iconClass={option.iconClass} className={styles.option_icon} />}
|
|
228
|
+
<span className={styles.option_label}>{option.label}</span>
|
|
229
|
+
{option.badge && (
|
|
230
|
+
<span className={styles.option_badge} style={{ backgroundColor: option.badgeColor }}>
|
|
231
|
+
{option.badge}
|
|
232
|
+
</span>
|
|
233
|
+
)}
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
{option.description && <div className={styles.option_description}>{option.description}</div>}
|
|
238
|
+
|
|
239
|
+
{option.tags && option.tags.length > 0 && (
|
|
240
|
+
<div className={styles.option_tags}>
|
|
241
|
+
{option.tags.map((tag, idx) => (
|
|
242
|
+
<span key={idx} className={styles.tag}>
|
|
243
|
+
{tag}
|
|
244
|
+
</span>
|
|
245
|
+
))}
|
|
246
|
+
</div>
|
|
247
|
+
)}
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
))}
|
|
251
|
+
</div>
|
|
252
|
+
)}
|
|
253
|
+
</div>
|
|
254
|
+
</ClickOutside>
|
|
255
|
+
);
|
|
256
|
+
};
|
|
@@ -46,6 +46,30 @@ export interface MentionState {
|
|
|
46
46
|
interface ModelOption {
|
|
47
47
|
label: string;
|
|
48
48
|
value: string;
|
|
49
|
+
icon?: string;
|
|
50
|
+
iconClass?: string;
|
|
51
|
+
tags?: string[];
|
|
52
|
+
description?: string;
|
|
53
|
+
badge?: string;
|
|
54
|
+
badgeColor?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ExtendedModelOption extends ModelOption {
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
selected?: boolean; // 由外部控制选中状态
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ExtendedModelOption {
|
|
63
|
+
label: string;
|
|
64
|
+
value: string;
|
|
65
|
+
icon?: string;
|
|
66
|
+
iconClass?: string;
|
|
67
|
+
tags?: string[];
|
|
68
|
+
features?: string[];
|
|
69
|
+
description?: string;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
badge?: string;
|
|
72
|
+
badgeColor?: string;
|
|
49
73
|
}
|
|
50
74
|
|
|
51
75
|
export enum FooterButtonPosition {
|
|
@@ -57,6 +81,7 @@ export enum MentionType {
|
|
|
57
81
|
FILE = 'file',
|
|
58
82
|
FOLDER = 'folder',
|
|
59
83
|
CODE = 'code',
|
|
84
|
+
RULE = 'rule',
|
|
60
85
|
}
|
|
61
86
|
|
|
62
87
|
interface FooterButton {
|
|
@@ -70,10 +95,14 @@ interface FooterButton {
|
|
|
70
95
|
|
|
71
96
|
export interface FooterConfig {
|
|
72
97
|
modelOptions?: ModelOption[];
|
|
98
|
+
extendedModelOptions?: ExtendedModelOption[];
|
|
73
99
|
defaultModel?: string;
|
|
74
100
|
buttons?: FooterButton[];
|
|
75
101
|
showModelSelector?: boolean;
|
|
76
102
|
disableModelSelector?: boolean;
|
|
103
|
+
showThinking?: boolean;
|
|
104
|
+
thinkingEnabled?: boolean;
|
|
105
|
+
onThinkingChange?: (enabled: boolean) => void;
|
|
77
106
|
}
|
|
78
107
|
|
|
79
108
|
export interface MentionInputProps {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DataContent } from 'ai';
|
|
2
|
-
|
|
3
1
|
import { Autowired, Injectable } from '@opensumi/di';
|
|
2
|
+
import { PreferenceService } from '@opensumi/ide-core-browser';
|
|
4
3
|
import { AppConfig } from '@opensumi/ide-core-browser/lib/react-providers/config-provider';
|
|
4
|
+
import { AINativeSettingSectionsId, IApplicationService, RulesServiceToken } from '@opensumi/ide-core-common';
|
|
5
5
|
import { WithEventBus } from '@opensumi/ide-core-common/lib/event-bus/event-decorator';
|
|
6
6
|
import { MarkerSeverity } from '@opensumi/ide-core-common/lib/types/markers/markers';
|
|
7
|
-
import { Emitter, URI } from '@opensumi/ide-core-common/lib/utils';
|
|
7
|
+
import { Emitter, OperatingSystem, URI, parseGlob } from '@opensumi/ide-core-common/lib/utils';
|
|
8
8
|
import {
|
|
9
9
|
EditorDocumentModelCreationEvent,
|
|
10
10
|
EditorDocumentModelRemovalEvent,
|
|
@@ -15,8 +15,12 @@ import { EditorSelectionChangeEvent } from '@opensumi/ide-editor/lib/browser/typ
|
|
|
15
15
|
import { FileType, IFileServiceClient } from '@opensumi/ide-file-service';
|
|
16
16
|
import { IMarkerService } from '@opensumi/ide-markers/lib/common/types';
|
|
17
17
|
import { Range } from '@opensumi/ide-monaco';
|
|
18
|
+
import { ITerminalApiService } from '@opensumi/ide-terminal-next';
|
|
19
|
+
import { isString, match } from '@opensumi/ide-utils';
|
|
18
20
|
|
|
19
21
|
import { AttachFileContext, FileContext, LLMContextService, SerializedContext } from '../../common/llm-context';
|
|
22
|
+
import { ProjectRule } from '../../common/types';
|
|
23
|
+
import { RulesService } from '../rules/rules.service';
|
|
20
24
|
|
|
21
25
|
@Injectable()
|
|
22
26
|
export class LLMContextServiceImpl extends WithEventBus implements LLMContextService {
|
|
@@ -32,6 +36,18 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
32
36
|
@Autowired(IFileServiceClient)
|
|
33
37
|
protected readonly fileService: IFileServiceClient;
|
|
34
38
|
|
|
39
|
+
@Autowired(RulesServiceToken)
|
|
40
|
+
protected readonly rulesService: RulesService;
|
|
41
|
+
|
|
42
|
+
@Autowired(PreferenceService)
|
|
43
|
+
protected readonly preferenceService: PreferenceService;
|
|
44
|
+
|
|
45
|
+
@Autowired(ITerminalApiService)
|
|
46
|
+
protected readonly terminalService: ITerminalApiService;
|
|
47
|
+
|
|
48
|
+
@Autowired(IApplicationService)
|
|
49
|
+
protected readonly applicationService: IApplicationService;
|
|
50
|
+
|
|
35
51
|
private isAutoCollecting = false;
|
|
36
52
|
|
|
37
53
|
private contextVersion = 0;
|
|
@@ -41,11 +57,13 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
41
57
|
private readonly maxViewFilesLimit = 20;
|
|
42
58
|
private attachedFiles: FileContext[] = [];
|
|
43
59
|
private attachedFolders: FileContext[] = [];
|
|
60
|
+
private attachedRules: ProjectRule[] = [];
|
|
44
61
|
private readonly recentlyViewFiles: FileContext[] = [];
|
|
45
62
|
private readonly onDidContextFilesChangeEmitter = new Emitter<{
|
|
46
63
|
viewed: FileContext[];
|
|
47
64
|
attached: FileContext[];
|
|
48
65
|
attachedFolders: FileContext[];
|
|
66
|
+
attachedRules: ProjectRule[];
|
|
49
67
|
version: number;
|
|
50
68
|
}>();
|
|
51
69
|
private hasUserManualReference = false;
|
|
@@ -80,6 +98,24 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
80
98
|
}
|
|
81
99
|
}
|
|
82
100
|
|
|
101
|
+
addRuleToContext(uri: URI): void {
|
|
102
|
+
if (!uri) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (this.attachedRules.some((rule) => rule.path === uri.toString())) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const rule = this.rulesService.projectRules.find((rule) => rule.path === uri.toString());
|
|
111
|
+
if (!rule) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.attachedRules.push(rule);
|
|
116
|
+
this.notifyContextChange();
|
|
117
|
+
}
|
|
118
|
+
|
|
83
119
|
addFileToContext(uri: URI, selection?: [number, number], isManual = false): void {
|
|
84
120
|
if (!uri) {
|
|
85
121
|
return;
|
|
@@ -117,6 +153,7 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
117
153
|
this.attachedFiles = [];
|
|
118
154
|
this.attachedFolders = [];
|
|
119
155
|
this.hasUserManualReference = false;
|
|
156
|
+
this.attachedRules = [];
|
|
120
157
|
this.notifyContextChange();
|
|
121
158
|
}
|
|
122
159
|
|
|
@@ -125,6 +162,7 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
125
162
|
viewed: this.recentlyViewFiles,
|
|
126
163
|
attached: this.attachedFiles,
|
|
127
164
|
attachedFolders: this.attachedFolders,
|
|
165
|
+
attachedRules: this.attachedRules,
|
|
128
166
|
version: this.contextVersion++,
|
|
129
167
|
};
|
|
130
168
|
}
|
|
@@ -143,6 +181,24 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
143
181
|
this.notifyContextChange();
|
|
144
182
|
}
|
|
145
183
|
|
|
184
|
+
removeFolderFromContext(uri: URI): void {
|
|
185
|
+
const targetList = this.attachedFolders;
|
|
186
|
+
const index = targetList.findIndex((folder) => folder.uri.toString() === uri.toString());
|
|
187
|
+
if (index > -1) {
|
|
188
|
+
targetList.splice(index, 1);
|
|
189
|
+
}
|
|
190
|
+
this.notifyContextChange();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
removeRuleFromContext(uri: URI): void {
|
|
194
|
+
const targetList = this.attachedRules;
|
|
195
|
+
const index = targetList.findIndex((rule) => rule.path === uri.toString());
|
|
196
|
+
if (index > -1) {
|
|
197
|
+
targetList.splice(index, 1);
|
|
198
|
+
}
|
|
199
|
+
this.notifyContextChange();
|
|
200
|
+
}
|
|
201
|
+
|
|
146
202
|
startAutoCollection(): void {
|
|
147
203
|
if (this.isAutoCollecting) {
|
|
148
204
|
return;
|
|
@@ -217,25 +273,35 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
217
273
|
return {
|
|
218
274
|
recentlyViewFiles: this.serializeRecentlyViewFiles(files.viewed, workspaceRoot),
|
|
219
275
|
attachedFiles: this.serializeAttachedFiles(files.attached, workspaceRoot),
|
|
220
|
-
attachedFolders: await this.serializeAttachedFolders(files.attachedFolders
|
|
276
|
+
attachedFolders: await this.serializeAttachedFolders(files.attachedFolders),
|
|
277
|
+
attachedRules: this.serializeAttachedRules(files.attachedRules),
|
|
278
|
+
globalRules: this.serializeGlobalRules(),
|
|
221
279
|
};
|
|
222
280
|
}
|
|
223
281
|
|
|
224
|
-
private async serializeAttachedFolders(folders: FileContext[]
|
|
282
|
+
private async serializeAttachedFolders(folders: FileContext[]): Promise<string[]> {
|
|
225
283
|
// 去重
|
|
226
284
|
const folderPath = Array.from(new Set(folders.map((folder) => folder.uri.toString())));
|
|
227
|
-
|
|
285
|
+
const header = 'Here are some folder(s) I manually attached to my message:';
|
|
286
|
+
const folderSections = await Promise.all(
|
|
228
287
|
folderPath.map(async (folder) => {
|
|
229
288
|
const folderUri = new URI(folder);
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
289
|
+
const absolutePath = folderUri.codeUri.fsPath;
|
|
290
|
+
const folderStructure = await this.getFormattedFolderStructure(absolutePath);
|
|
291
|
+
|
|
292
|
+
return `Folder: ${absolutePath}
|
|
293
|
+
Contents of directory:
|
|
294
|
+
|
|
295
|
+
${folderStructure}`;
|
|
234
296
|
}),
|
|
235
297
|
);
|
|
298
|
+
if (folderSections.length > 0) {
|
|
299
|
+
return [header, ...folderSections, ''];
|
|
300
|
+
}
|
|
301
|
+
return [];
|
|
236
302
|
}
|
|
237
303
|
|
|
238
|
-
private async
|
|
304
|
+
private async getFormattedFolderStructure(folder: string): Promise<string> {
|
|
239
305
|
const result: string[] = [];
|
|
240
306
|
try {
|
|
241
307
|
const stat = await this.fileService.getFileStat(folder);
|
|
@@ -247,28 +313,27 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
247
313
|
// 处理软链接
|
|
248
314
|
const target = await this.fileService.getFileStat(child.realUri || child.uri);
|
|
249
315
|
if (target) {
|
|
250
|
-
result.push(
|
|
316
|
+
result.push(`[link] ${relativePath} -> ${target}`);
|
|
251
317
|
} else {
|
|
252
|
-
result.push(
|
|
318
|
+
result.push(`[link] ${relativePath} (broken)`);
|
|
253
319
|
}
|
|
254
320
|
continue;
|
|
255
321
|
}
|
|
256
322
|
|
|
257
323
|
if (child.type === FileType.Directory) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
324
|
+
// 计算目录下的项目数量
|
|
325
|
+
const childStat = await this.fileService.getFileStat(child.uri);
|
|
326
|
+
const itemCount = childStat?.children?.length || 0;
|
|
327
|
+
result.push(`[dir] ${relativePath}/ (${itemCount} items)`);
|
|
263
328
|
} else if (child.type === FileType.File) {
|
|
264
|
-
result.push(relativePath);
|
|
329
|
+
result.push(`[file] ${relativePath}`);
|
|
265
330
|
}
|
|
266
331
|
}
|
|
267
332
|
} catch {
|
|
268
|
-
return
|
|
333
|
+
return '';
|
|
269
334
|
}
|
|
270
335
|
|
|
271
|
-
return result;
|
|
336
|
+
return result.join('\n');
|
|
272
337
|
}
|
|
273
338
|
|
|
274
339
|
private serializeRecentlyViewFiles(files: FileContext[], workspaceRoot: URI): string[] {
|
|
@@ -295,6 +360,7 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
295
360
|
lineErrors: this.getFileErrors(file.uri),
|
|
296
361
|
path: workspaceRoot.relative(file.uri)!.toString(),
|
|
297
362
|
language: ref.instance.languageId!,
|
|
363
|
+
selection: file.selection,
|
|
298
364
|
};
|
|
299
365
|
} catch (e) {
|
|
300
366
|
return null;
|
|
@@ -310,4 +376,99 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
310
376
|
})
|
|
311
377
|
.map((marker) => marker.message);
|
|
312
378
|
}
|
|
379
|
+
|
|
380
|
+
private serializeGlobalRules(): string[] {
|
|
381
|
+
const globalRules = this.preferenceService.get<string>(AINativeSettingSectionsId.GlobalRules);
|
|
382
|
+
if (!globalRules) {
|
|
383
|
+
return [];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const platform =
|
|
387
|
+
this.applicationService.backendOS === OperatingSystem.Windows
|
|
388
|
+
? 'windows'
|
|
389
|
+
: this.applicationService.backendOS === OperatingSystem.Linux
|
|
390
|
+
? 'linux'
|
|
391
|
+
: 'darwin';
|
|
392
|
+
const shell = this.preferenceService.get<string>('terminal.type', 'zsh');
|
|
393
|
+
let shellName = shell;
|
|
394
|
+
if (shell === 'default') {
|
|
395
|
+
shellName = this.applicationService.backendOS === OperatingSystem.Windows ? 'cmd' : 'zsh';
|
|
396
|
+
}
|
|
397
|
+
const userInfoSection = `<user_info>
|
|
398
|
+
The user's OS version is ${platform}. The absolute path of the user's workspace is ${this.appConfig.workspaceDir}. The user's shell is /bin/${shellName}.
|
|
399
|
+
</user_info>`;
|
|
400
|
+
|
|
401
|
+
const rulesSection = `
|
|
402
|
+
|
|
403
|
+
<rules>
|
|
404
|
+
The rules section has a number of possible rules/memories/context that you should consider. In each subsection, we provide instructions about what information the subsection contains and how you should consider/follow the contents of the subsection.
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
<user_specific_rule description="This is a rule set by the user that the agent must follow.">
|
|
408
|
+
${globalRules}
|
|
409
|
+
</user_specific_rule>
|
|
410
|
+
|
|
411
|
+
</rules>`;
|
|
412
|
+
|
|
413
|
+
return [userInfoSection, rulesSection];
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private findApplicableRules(attachedRules: ProjectRule[]): ProjectRule[] {
|
|
417
|
+
const otherRules = this.rulesService.projectRules.filter(
|
|
418
|
+
(rule) => !attachedRules.some((attachedRule) => attachedRule.path === rule.path),
|
|
419
|
+
);
|
|
420
|
+
const requestedByAgentRules = otherRules.filter((rule) => rule.description);
|
|
421
|
+
const alwaysApplyRules = otherRules.filter((rule) => rule.alwaysApply);
|
|
422
|
+
const requestedByFileRules = this.findFileMatchingRules(otherRules);
|
|
423
|
+
|
|
424
|
+
return [...requestedByFileRules, ...requestedByAgentRules, ...alwaysApplyRules];
|
|
425
|
+
}
|
|
426
|
+
private findFileMatchingRules(otherRules: ProjectRule[]): ProjectRule[] {
|
|
427
|
+
const requestedByFileRules = otherRules.filter((rule) => rule.globs);
|
|
428
|
+
const filePaths = this.attachedFiles.map((file) => file.uri.toString());
|
|
429
|
+
const folderPaths = this.attachedFolders.map((folder) => folder.uri.toString());
|
|
430
|
+
|
|
431
|
+
return requestedByFileRules.filter((rule) => {
|
|
432
|
+
let globs = rule.globs;
|
|
433
|
+
if (isString(globs)) {
|
|
434
|
+
globs = this.normalizeGlobs(globs.split(','));
|
|
435
|
+
} else {
|
|
436
|
+
globs = this.normalizeGlobs(globs || []);
|
|
437
|
+
}
|
|
438
|
+
const patterns = globs.map((pattern) => parseGlob(pattern));
|
|
439
|
+
return patterns.some((match) => filePaths.some((path) => match(path)) || folderPaths.some((path) => match(path)));
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
private normalizeGlobs(globs: string | string[]): string[] {
|
|
443
|
+
const globArray = isString(globs) ? globs.split(',') : globs || [];
|
|
444
|
+
return globArray.map((glob) => {
|
|
445
|
+
const p = glob.trim();
|
|
446
|
+
return p.startsWith('**') ? p : `**/${p}`;
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
private serializeAttachedRules(rules: ProjectRule[] = []): string[] {
|
|
451
|
+
rules = this.findApplicableRules(rules);
|
|
452
|
+
if (rules.length === 0) {
|
|
453
|
+
return [];
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const header =
|
|
457
|
+
'\n<rules_context>\n\nRules are extra documentation provided by the user to help the AI understand the codebase.\nUse them if they seem useful to the users most recent query, but do not use them if they seem unrelated.\n\n';
|
|
458
|
+
|
|
459
|
+
const rulesSections = rules
|
|
460
|
+
.map((rule) => {
|
|
461
|
+
const ruleName =
|
|
462
|
+
rule.path
|
|
463
|
+
.split('/')
|
|
464
|
+
.pop()
|
|
465
|
+
?.replace(/.md(c)?$/, '') || 'Unnamed Rule';
|
|
466
|
+
return `Rule Name: ${ruleName}\nDescription: \n${rule.description || rule.content}`;
|
|
467
|
+
})
|
|
468
|
+
.join('\n\n');
|
|
469
|
+
|
|
470
|
+
const footer = '\n</rules_context>\n';
|
|
471
|
+
|
|
472
|
+
return [header, rulesSections, footer];
|
|
473
|
+
}
|
|
313
474
|
}
|
package/src/browser/contrib/intelligent-completions/decoration/additions-deletions.decoration.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ICodeEditor,
|
|
1
|
+
import { ICodeEditor, IRange, TrackedRangeStickiness } from '@opensumi/ide-monaco';
|
|
2
2
|
|
|
3
3
|
import { EnhanceDecorationsCollection } from '../../../model/enhanceDecorationsCollection';
|
|
4
4
|
import { REWRITE_DECORATION_INLINE_ADD } from '../../../widget/rewrite/rewrite-widget';
|
|
@@ -267,7 +267,7 @@ export const computeMultiLineDiffChanges = (
|
|
|
267
267
|
lineNumber: number,
|
|
268
268
|
eol: string,
|
|
269
269
|
) => {
|
|
270
|
-
|
|
270
|
+
const rewriteDiffResult: IMultiLineDiffChangeResult[] =
|
|
271
271
|
rewriteDiffComputer.diff(originalContent, modifiedContent) || [];
|
|
272
272
|
let multiLineDiffResult: IMultiLineDiffChangeResult[] =
|
|
273
273
|
multiLineDiffComputer.diff(originalContent, modifiedContent) || [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Injectable } from '@opensumi/di';
|
|
2
2
|
import { CancellationToken, Disposable } from '@opensumi/ide-core-common';
|
|
3
|
-
import { IReadableStream, isReadableStream, listenGroupReadable
|
|
3
|
+
import { IReadableStream, isReadableStream, listenGroupReadable } from '@opensumi/ide-utils/lib/stream';
|
|
4
4
|
|
|
5
5
|
import { ITerminalCommandSuggestionDesc } from '../../../common/index';
|
|
6
6
|
import {
|
package/src/browser/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
IntelligentCompletionsRegistryToken,
|
|
18
18
|
MCPConfigServiceToken,
|
|
19
19
|
ProblemFixRegistryToken,
|
|
20
|
+
RulesServiceToken,
|
|
20
21
|
TerminalRegistryToken,
|
|
21
22
|
} from '@opensumi/ide-core-common';
|
|
22
23
|
import { FolderFilePreferenceProvider } from '@opensumi/ide-preferences/lib/browser/folder-file-preference-provider';
|
|
@@ -77,6 +78,8 @@ import { ListDirTool } from './mcp/tools/listDir';
|
|
|
77
78
|
import { ReadFileTool } from './mcp/tools/readFile';
|
|
78
79
|
import { RunTerminalCommandTool } from './mcp/tools/runTerminalCmd';
|
|
79
80
|
import { AINativePreferencesContribution } from './preferences';
|
|
81
|
+
import { RulesContribution } from './rules/rules.contribution';
|
|
82
|
+
import { RulesService } from './rules/rules.service';
|
|
80
83
|
import { AINativeCoreContribution, MCPServerContribution, TokenMCPServerRegistry } from './types';
|
|
81
84
|
import { InlineChatFeatureRegistry } from './widget/inline-chat/inline-chat.feature.registry';
|
|
82
85
|
import { InlineChatService } from './widget/inline-chat/inline-chat.service';
|
|
@@ -119,6 +122,7 @@ export class AINativeModule extends BrowserModule {
|
|
|
119
122
|
|
|
120
123
|
// Context Service
|
|
121
124
|
LlmContextContribution,
|
|
125
|
+
RulesContribution,
|
|
122
126
|
{
|
|
123
127
|
token: LLMContextServiceToken,
|
|
124
128
|
useClass: LLMContextServiceImpl,
|
|
@@ -216,6 +220,10 @@ export class AINativeModule extends BrowserModule {
|
|
|
216
220
|
token: MCPConfigServiceToken,
|
|
217
221
|
useClass: MCPConfigService,
|
|
218
222
|
},
|
|
223
|
+
{
|
|
224
|
+
token: RulesServiceToken,
|
|
225
|
+
useClass: RulesService,
|
|
226
|
+
},
|
|
219
227
|
{
|
|
220
228
|
token: FolderFilePreferenceProvider,
|
|
221
229
|
useClass: MCPFolderPreferenceProvider,
|