@opensumi/ide-ai-native 3.8.1-next-1740478950.0 → 3.8.1-next-1740571693.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.contextkeys.d.ts +1 -1
- package/lib/browser/ai-core.contextkeys.d.ts.map +1 -1
- package/lib/browser/ai-core.contextkeys.js +1 -1
- package/lib/browser/ai-core.contextkeys.js.map +1 -1
- package/lib/browser/chat/chat-manager.service.d.ts +0 -5
- package/lib/browser/chat/chat-manager.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-manager.service.js +1 -18
- package/lib/browser/chat/chat-manager.service.js.map +1 -1
- package/lib/browser/chat/chat-model.d.ts +0 -2
- package/lib/browser/chat/chat-model.d.ts.map +1 -1
- package/lib/browser/chat/chat-model.js +2 -8
- package/lib/browser/chat/chat-model.js.map +1 -1
- package/lib/browser/chat/chat.module.less +2 -1
- package/lib/browser/chat/chat.view.d.ts.map +1 -1
- package/lib/browser/chat/chat.view.js +38 -6
- package/lib/browser/chat/chat.view.js.map +1 -1
- package/lib/browser/components/ChatContext/index.js +2 -2
- package/lib/browser/components/ChatContext/index.js.map +1 -1
- package/lib/browser/components/ChatInput.d.ts.map +1 -1
- package/lib/browser/components/ChatInput.js +1 -25
- package/lib/browser/components/ChatInput.js.map +1 -1
- package/lib/browser/components/ChatToolRender.d.ts.map +1 -1
- package/lib/browser/components/ChatToolRender.js +3 -2
- package/lib/browser/components/ChatToolRender.js.map +1 -1
- package/lib/browser/components/chat-history.css +1 -1
- package/lib/browser/components/components.module.less +0 -20
- package/lib/browser/context/llm-context.service.d.ts +5 -16
- package/lib/browser/context/llm-context.service.d.ts.map +1 -1
- package/lib/browser/context/llm-context.service.js +47 -78
- package/lib/browser/context/llm-context.service.js.map +1 -1
- package/lib/browser/contrib/inline-completions/inline-completions.controller.js +1 -1
- package/lib/browser/contrib/inline-completions/inline-completions.controller.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/index.d.ts +2 -1
- package/lib/browser/contrib/intelligent-completions/index.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/index.js +4 -1
- package/lib/browser/contrib/intelligent-completions/index.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js +2 -2
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js +5 -4
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/view/code-edits-previewer.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/view/code-edits-previewer.js +4 -2
- package/lib/browser/contrib/intelligent-completions/view/code-edits-previewer.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/view/default.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/view/default.js +17 -11
- package/lib/browser/contrib/intelligent-completions/view/default.js.map +1 -1
- package/lib/browser/layout/layout.module.less +4 -4
- package/lib/browser/mcp/tools/components/index.module.less +0 -1
- package/lib/browser/mcp/tools/createNewFileWithText.d.ts.map +1 -1
- package/lib/browser/mcp/tools/createNewFileWithText.js +0 -1
- package/lib/browser/mcp/tools/createNewFileWithText.js.map +1 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts.map +1 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js +0 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.js +0 -2
- package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.js +0 -1
- package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -1
- package/lib/common/llm-context.d.ts +9 -12
- package/lib/common/llm-context.d.ts.map +1 -1
- package/lib/common/llm-context.js.map +1 -1
- package/lib/common/prompts/context-prompt-provider.d.ts +3 -2
- package/lib/common/prompts/context-prompt-provider.d.ts.map +1 -1
- package/lib/common/prompts/context-prompt-provider.js +22 -21
- package/lib/common/prompts/context-prompt-provider.js.map +1 -1
- package/lib/node/base-language-model.d.ts.map +1 -1
- package/lib/node/base-language-model.js +5 -4
- package/lib/node/base-language-model.js.map +1 -1
- package/package.json +23 -23
- package/src/browser/ai-core.contextkeys.ts +3 -3
- package/src/browser/chat/chat-manager.service.ts +1 -17
- package/src/browser/chat/chat-model.ts +3 -18
- package/src/browser/chat/chat.module.less +2 -1
- package/src/browser/chat/chat.view.tsx +70 -7
- package/src/browser/components/ChatContext/index.tsx +2 -2
- package/src/browser/components/ChatInput.tsx +4 -67
- package/src/browser/components/ChatToolRender.tsx +2 -1
- package/src/browser/components/chat-history.css +1 -1
- package/src/browser/components/components.module.less +0 -20
- package/src/browser/context/llm-context.service.ts +54 -90
- package/src/browser/contrib/inline-completions/inline-completions.controller.ts +1 -1
- package/src/browser/contrib/intelligent-completions/index.ts +5 -1
- package/src/browser/contrib/intelligent-completions/intelligent-completions.contribution.ts +3 -3
- package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +6 -5
- package/src/browser/contrib/intelligent-completions/view/code-edits-previewer.ts +4 -2
- package/src/browser/contrib/intelligent-completions/view/default.ts +27 -19
- package/src/browser/layout/layout.module.less +4 -4
- package/src/browser/mcp/tools/components/index.module.less +0 -1
- package/src/browser/mcp/tools/createNewFileWithText.ts +0 -1
- package/src/browser/mcp/tools/getDiagnosticsByPath.ts +0 -1
- package/src/browser/mcp/tools/handlers/RunCommand.ts +0 -2
- package/src/browser/mcp/tools/runTerminalCmd.ts +0 -1
- package/src/common/llm-context.ts +4 -10
- package/src/common/prompts/context-prompt-provider.ts +28 -26
- package/src/node/base-language-model.ts +7 -4
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import { EditorSelectionChangeEvent } from '@opensumi/ide-editor/lib/browser/types';
|
|
13
13
|
import { IMarkerService } from '@opensumi/ide-markers/lib/common/types';
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { FileContext, LLMContextService, SerializedContext } from '../../common/llm-context';
|
|
16
16
|
|
|
17
17
|
@Injectable()
|
|
18
18
|
export class LLMContextServiceImpl extends WithEventBus implements LLMContextService {
|
|
@@ -27,65 +27,40 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
27
27
|
|
|
28
28
|
private isAutoCollecting = false;
|
|
29
29
|
|
|
30
|
-
private
|
|
31
|
-
private readonly maxViewFilesLimit = 20;
|
|
32
|
-
private readonly attachedFiles: FileContext[] = [];
|
|
33
|
-
private readonly recentlyViewFiles: FileContext[] = [];
|
|
34
|
-
private readonly onDidContextFilesChangeEmitter = new Emitter<{ viewed: FileContext[]; attached: FileContext[] }>();
|
|
35
|
-
onDidContextFilesChangeEvent = this.onDidContextFilesChangeEmitter.event;
|
|
30
|
+
private contextFiles: FileContext[] = [];
|
|
36
31
|
|
|
37
|
-
private
|
|
38
|
-
const existingIndex = list.findIndex((f) => f.uri.toString() === file.uri.toString());
|
|
39
|
-
if (existingIndex > -1) {
|
|
40
|
-
list.splice(existingIndex, 1);
|
|
41
|
-
}
|
|
32
|
+
private maxFiles: number = 10; // 上下文的最大长度限制
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
list.shift();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
34
|
+
private onDidContextFilesChangeEmitter = new Emitter<FileContext[]>();
|
|
35
|
+
onDidContextFilesChangeEvent = this.onDidContextFilesChangeEmitter.event;
|
|
48
36
|
|
|
49
|
-
addFileToContext(uri: URI, selection?: [number, number], isManual =
|
|
50
|
-
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
37
|
+
addFileToContext(uri: URI, selection?: [number, number], isManual = true): void {
|
|
38
|
+
this.removeFileFromContext(uri);
|
|
53
39
|
|
|
54
|
-
|
|
55
|
-
const targetList = isManual ? this.attachedFiles : this.recentlyViewFiles;
|
|
56
|
-
const maxLimit = isManual ? this.maxAttachFilesLimit : this.maxViewFilesLimit;
|
|
40
|
+
this.contextFiles.push({ uri, selection, isManual });
|
|
57
41
|
|
|
58
|
-
if (
|
|
59
|
-
this.
|
|
42
|
+
if (this.contextFiles.length > this.maxFiles) {
|
|
43
|
+
this.contextFiles.shift();
|
|
60
44
|
}
|
|
61
45
|
|
|
62
|
-
this.addFileToList(file, targetList, maxLimit);
|
|
63
|
-
this.notifyContextChange();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private notifyContextChange(): void {
|
|
67
46
|
this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
|
|
68
47
|
}
|
|
69
48
|
|
|
70
49
|
cleanFileContext() {
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
50
|
+
this.contextFiles = [];
|
|
51
|
+
this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
|
|
73
52
|
}
|
|
74
53
|
|
|
75
54
|
private getAllContextFiles() {
|
|
76
|
-
return
|
|
77
|
-
viewed: this.recentlyViewFiles,
|
|
78
|
-
attached: this.attachedFiles,
|
|
79
|
-
};
|
|
55
|
+
return [...this.contextFiles];
|
|
80
56
|
}
|
|
81
57
|
|
|
82
|
-
removeFileFromContext(uri: URI
|
|
83
|
-
const
|
|
84
|
-
const index = targetList.findIndex((file) => file.uri.toString() === uri.toString());
|
|
58
|
+
removeFileFromContext(uri: URI): void {
|
|
59
|
+
const index = this.contextFiles.findIndex((file) => file.uri.toString() === uri.toString());
|
|
85
60
|
if (index > -1) {
|
|
86
|
-
|
|
61
|
+
this.contextFiles.splice(index, 1);
|
|
62
|
+
this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
|
|
87
63
|
}
|
|
88
|
-
this.notifyContextChange();
|
|
89
64
|
}
|
|
90
65
|
|
|
91
66
|
startAutoCollection(): void {
|
|
@@ -103,7 +78,8 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
103
78
|
if (event.payload.uri.scheme !== 'file') {
|
|
104
79
|
return;
|
|
105
80
|
}
|
|
106
|
-
|
|
81
|
+
// FIXME: 暂时不自动添加
|
|
82
|
+
// this.addFileToContext(event.payload.uri);
|
|
107
83
|
}),
|
|
108
84
|
);
|
|
109
85
|
|
|
@@ -112,8 +88,6 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
112
88
|
if (event.payload.scheme !== 'file') {
|
|
113
89
|
return;
|
|
114
90
|
}
|
|
115
|
-
|
|
116
|
-
this.removeFileFromContext(event.payload, false);
|
|
117
91
|
}),
|
|
118
92
|
);
|
|
119
93
|
|
|
@@ -135,12 +109,11 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
135
109
|
].sort() as [number, number];
|
|
136
110
|
|
|
137
111
|
if (selection[0] === selection[1]) {
|
|
138
|
-
this.addFileToContext(event.payload.editorUri, undefined
|
|
112
|
+
this.addFileToContext(event.payload.editorUri, undefined);
|
|
139
113
|
} else {
|
|
140
114
|
this.addFileToContext(
|
|
141
115
|
event.payload.editorUri,
|
|
142
116
|
selection.sort((a, b) => a - b),
|
|
143
|
-
false,
|
|
144
117
|
);
|
|
145
118
|
}
|
|
146
119
|
}
|
|
@@ -154,51 +127,42 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
|
|
|
154
127
|
|
|
155
128
|
serialize(): SerializedContext {
|
|
156
129
|
const files = this.getAllContextFiles();
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return files
|
|
167
|
-
.map((file) => workspaceRoot.relative(file.uri)?.toString() || file.uri.parent.toString())
|
|
130
|
+
const recentlyViewFiles = files
|
|
131
|
+
.filter((v) => !v.selection)
|
|
132
|
+
.map((file) => {
|
|
133
|
+
const relativePath = URI.file(this.appConfig.workspaceDir).relative(file.uri);
|
|
134
|
+
if (relativePath) {
|
|
135
|
+
return relativePath.toString();
|
|
136
|
+
}
|
|
137
|
+
return file.uri.parent.toString();
|
|
138
|
+
})
|
|
168
139
|
.filter(Boolean);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private serializeAttachedFiles(files: FileContext[], workspaceRoot: URI): AttachFileContext[] {
|
|
172
|
-
return files
|
|
173
|
-
.map((file) => this.serializeAttachedFile(file, workspaceRoot))
|
|
174
|
-
.filter(Boolean) as unknown as AttachFileContext[];
|
|
175
|
-
}
|
|
176
140
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return this.markerService
|
|
197
|
-
.getManager()
|
|
198
|
-
.getMarkers({
|
|
199
|
-
resource: uri.toString(),
|
|
200
|
-
severities: MarkerSeverity.Error,
|
|
141
|
+
const attachedFiles = files
|
|
142
|
+
.filter((v) => v.selection)
|
|
143
|
+
.map((file) => {
|
|
144
|
+
const ref = this.docModelManager.getModelReference(file.uri);
|
|
145
|
+
const content = ref!.instance.getText();
|
|
146
|
+
const lineErrors = this.markerService
|
|
147
|
+
.getManager()
|
|
148
|
+
.getMarkers({
|
|
149
|
+
resource: file.uri.toString(),
|
|
150
|
+
severities: MarkerSeverity.Error,
|
|
151
|
+
})
|
|
152
|
+
.map((marker) => marker.message);
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
content,
|
|
156
|
+
lineErrors,
|
|
157
|
+
path: URI.file(this.appConfig.workspaceDir).relative(file.uri)!.toString(),
|
|
158
|
+
language: ref?.instance.languageId!,
|
|
159
|
+
};
|
|
201
160
|
})
|
|
202
|
-
.
|
|
161
|
+
.filter(Boolean);
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
recentlyViewFiles,
|
|
165
|
+
attachedFiles,
|
|
166
|
+
};
|
|
203
167
|
}
|
|
204
168
|
}
|
|
@@ -170,7 +170,7 @@ export class InlineCompletionsController extends BaseAIMonacoEditorController {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
// 如果上一次补全结果还在,则不重复请求
|
|
173
|
-
const isVisible = this.aiNativeContextKey.
|
|
173
|
+
const isVisible = this.aiNativeContextKey.codeEditsIsVisible.get();
|
|
174
174
|
if (isVisible) {
|
|
175
175
|
return;
|
|
176
176
|
}
|
|
@@ -69,7 +69,11 @@ export class CodeEditsResultValue<T extends ICodeEdit = ICodeEdit> extends Dispo
|
|
|
69
69
|
}));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
public get
|
|
72
|
+
public get firstRange(): IRange {
|
|
73
73
|
return this.raw.items[0].range;
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
public get firstText(): string {
|
|
77
|
+
return this.raw.items[0].insertText;
|
|
78
|
+
}
|
|
75
79
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
KeybindingScope,
|
|
9
9
|
} from '@opensumi/ide-core-browser';
|
|
10
10
|
import { AI_CODE_EDITS_COMMANDS } from '@opensumi/ide-core-browser/lib/ai-native/command';
|
|
11
|
-
import {
|
|
11
|
+
import { CodeEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
|
|
12
12
|
import { CommandContribution, CommandRegistry, Domain } from '@opensumi/ide-core-common';
|
|
13
13
|
import { WorkbenchEditorService } from '@opensumi/ide-editor';
|
|
14
14
|
import { WorkbenchEditorServiceImpl } from '@opensumi/ide-editor/lib/browser/workbench-editor.service';
|
|
@@ -61,7 +61,7 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
|
|
|
61
61
|
keybindings.registerKeybinding({
|
|
62
62
|
command: AI_CODE_EDITS_COMMANDS.DISCARD.id,
|
|
63
63
|
keybinding: Key.ESCAPE.code,
|
|
64
|
-
when:
|
|
64
|
+
when: CodeEditsIsVisible.raw,
|
|
65
65
|
priority: 100,
|
|
66
66
|
});
|
|
67
67
|
|
|
@@ -69,7 +69,7 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
|
|
|
69
69
|
{
|
|
70
70
|
command: AI_CODE_EDITS_COMMANDS.ACCEPT.id,
|
|
71
71
|
keybinding: Key.TAB.code,
|
|
72
|
-
when:
|
|
72
|
+
when: CodeEditsIsVisible.raw,
|
|
73
73
|
},
|
|
74
74
|
KeybindingScope.USER,
|
|
75
75
|
);
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
KeybindingScope,
|
|
6
6
|
PreferenceService,
|
|
7
7
|
} from '@opensumi/ide-core-browser';
|
|
8
|
-
import {
|
|
8
|
+
import { CodeEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
|
|
9
9
|
import {
|
|
10
10
|
AINativeSettingSectionsId,
|
|
11
11
|
CodeEditsRT,
|
|
@@ -98,13 +98,13 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
|
|
|
98
98
|
this.monacoEditor,
|
|
99
99
|
]);
|
|
100
100
|
|
|
101
|
-
const multiLineEditsIsVisibleKey = new Set([
|
|
101
|
+
const multiLineEditsIsVisibleKey = new Set([CodeEditsIsVisible.raw]);
|
|
102
102
|
this.multiLineEditsIsVisibleObs = observableFromEvent(
|
|
103
103
|
this,
|
|
104
104
|
Event.filter(this.aiNativeContextKey.contextKeyService!.onDidChangeContext, (e: ContextKeyChangeEvent) =>
|
|
105
105
|
e.payload.affectsSome(multiLineEditsIsVisibleKey),
|
|
106
106
|
),
|
|
107
|
-
() => !!this.aiNativeContextKey.
|
|
107
|
+
() => !!this.aiNativeContextKey.codeEditsIsVisible.get(),
|
|
108
108
|
);
|
|
109
109
|
|
|
110
110
|
this.registerFeature(this.monacoEditor);
|
|
@@ -205,7 +205,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
|
|
|
205
205
|
|
|
206
206
|
public hide() {
|
|
207
207
|
this.cancelToken();
|
|
208
|
-
this.aiNativeContextKey.
|
|
208
|
+
this.aiNativeContextKey.codeEditsIsVisible.reset();
|
|
209
209
|
this.codeEditsPreviewer.hide();
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -273,6 +273,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
|
|
|
273
273
|
public trigger(tx: ITransaction): void {
|
|
274
274
|
const triggerSource = this.codeEditsSourceCollection.getSource(TriggerCodeEditsSource) as TriggerCodeEditsSource;
|
|
275
275
|
if (triggerSource) {
|
|
276
|
+
this.hide();
|
|
276
277
|
triggerSource.triggerSignal.trigger(tx);
|
|
277
278
|
}
|
|
278
279
|
}
|
|
@@ -314,7 +315,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
|
|
|
314
315
|
handleChange: (context) => {
|
|
315
316
|
if (context.didChange(this.codeEditsSourceCollection.codeEditsContextBean)) {
|
|
316
317
|
// 如果上一次补全结果还在,则不重复请求
|
|
317
|
-
const isVisible = this.aiNativeContextKey.
|
|
318
|
+
const isVisible = this.aiNativeContextKey.codeEditsIsVisible.get();
|
|
318
319
|
return !isVisible;
|
|
319
320
|
}
|
|
320
321
|
return false;
|
|
@@ -51,19 +51,21 @@ export class CodeEditsPreviewer extends Disposable {
|
|
|
51
51
|
|
|
52
52
|
public render(completionModel: CodeEditsResultValue) {
|
|
53
53
|
this.view?.render(completionModel);
|
|
54
|
-
this.aiNativeContextKey.
|
|
54
|
+
this.aiNativeContextKey.codeEditsIsVisible.set(true);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
public hide() {
|
|
58
58
|
this.view?.hide();
|
|
59
|
-
this.aiNativeContextKey.
|
|
59
|
+
this.aiNativeContextKey.codeEditsIsVisible.set(false);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
public accept() {
|
|
63
63
|
this.view?.accept();
|
|
64
|
+
this.aiNativeContextKey.codeEditsIsVisible.set(false);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
public discard() {
|
|
67
68
|
this.view?.discard();
|
|
69
|
+
this.aiNativeContextKey.codeEditsIsVisible.set(false);
|
|
68
70
|
}
|
|
69
71
|
}
|
|
@@ -80,17 +80,23 @@ export class DefaultCodeEditsView extends BaseCodeEditsView {
|
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
83
|
+
const position = this.editorObs.positions.get()?.[0];
|
|
84
|
+
if (!position) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
const model = this.editorObs.model.get();
|
|
89
|
+
if (!model) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
93
92
|
|
|
93
|
+
const originalContent = model.getValueInRange(completionModel.firstRange);
|
|
94
|
+
// edits 的内容与原内容一样就不展示
|
|
95
|
+
if (originalContent === completionModel.firstText) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
asyncTransaction(async (tx) => {
|
|
94
100
|
const versionId = this.editorObs.versionId.get();
|
|
95
101
|
const context: InlineCompletionContext = {
|
|
96
102
|
triggerKind: InlineCompletionTriggerKind.Automatic,
|
|
@@ -103,16 +109,16 @@ export class DefaultCodeEditsView extends BaseCodeEditsView {
|
|
|
103
109
|
const inlineEdits: InlineCompletionProviderResult = await provideInlineCompletions(
|
|
104
110
|
{
|
|
105
111
|
all: () => [
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
{
|
|
113
|
+
provideInlineCompletions: () => {},
|
|
114
|
+
provideInlineEditsForRange(model, range, context, token) {
|
|
115
|
+
return completionModel;
|
|
116
|
+
},
|
|
117
|
+
freeInlineCompletions: () => [],
|
|
118
|
+
} as InlineCompletionsProvider<ICodeEditsResult<ICodeEdit>>,
|
|
119
|
+
],
|
|
114
120
|
} as unknown as LanguageFeatureRegistry<InlineCompletionsProvider>,
|
|
115
|
-
Range.lift(completionModel.
|
|
121
|
+
Range.lift(completionModel.firstRange),
|
|
116
122
|
model,
|
|
117
123
|
context,
|
|
118
124
|
);
|
|
@@ -122,9 +128,11 @@ export class DefaultCodeEditsView extends BaseCodeEditsView {
|
|
|
122
128
|
request,
|
|
123
129
|
model,
|
|
124
130
|
this.editorObs.versionId,
|
|
125
|
-
constObservable(
|
|
131
|
+
constObservable(4000),
|
|
126
132
|
);
|
|
133
|
+
|
|
127
134
|
source.inlineCompletions.set(completions, tx);
|
|
135
|
+
source.loading.set(false, tx);
|
|
128
136
|
});
|
|
129
137
|
}
|
|
130
138
|
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
padding: 8px 12px;
|
|
15
15
|
min-width: initial;
|
|
16
16
|
margin: 0;
|
|
17
|
+
|
|
18
|
+
::after {
|
|
19
|
+
content: '';
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
.rce-mbox-text {
|
|
20
24
|
line-height: 18px;
|
|
21
25
|
width: inherit;
|
|
22
26
|
font-size: 12px;
|
|
23
|
-
|
|
24
|
-
&::after {
|
|
25
|
-
display: none;
|
|
26
|
-
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.rce-smsg {
|
|
@@ -27,7 +27,6 @@ export class CreateNewFileWithTextTool implements MCPServerContribution {
|
|
|
27
27
|
getToolDefinition(): MCPToolDefinition {
|
|
28
28
|
return {
|
|
29
29
|
name: 'create_new_file_with_text',
|
|
30
|
-
label: 'Create File',
|
|
31
30
|
description:
|
|
32
31
|
'Creates a new file at the specified path within the project directory and populates it with the provided text. ' +
|
|
33
32
|
'Use this tool to generate new files in your project structure. ' +
|
|
@@ -29,7 +29,6 @@ export class GetDiagnosticsByPathTool implements MCPServerContribution {
|
|
|
29
29
|
getToolDefinition(): MCPToolDefinition {
|
|
30
30
|
return {
|
|
31
31
|
name: 'get_diagnostics_by_path',
|
|
32
|
-
label: 'Get Diagnostics',
|
|
33
32
|
description:
|
|
34
33
|
'Retrieves diagnostic information (errors, warnings, etc.) from a specific file in the project. ' +
|
|
35
34
|
'Use this tool to get information about problems in any project file. ' +
|
|
@@ -49,7 +49,6 @@ export class RunCommandHandler {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async handler(args: z.infer<typeof inputSchema> & { toolCallId: string }, logger: MCPLogger) {
|
|
52
|
-
logger.appendLine(`Executing command: ${args.command}`);
|
|
53
52
|
if (args.require_user_approval) {
|
|
54
53
|
const def = new Deferred<boolean>();
|
|
55
54
|
this.approvalDeferredMap.set(args.toolCallId, def);
|
|
@@ -90,7 +89,6 @@ export class RunCommandHandler {
|
|
|
90
89
|
content: result,
|
|
91
90
|
});
|
|
92
91
|
|
|
93
|
-
logger.appendLine(`Command ${args.command} finished with exit code: ${e.code}`);
|
|
94
92
|
terminalClient.term.writeln(
|
|
95
93
|
`\n${color.italic}> Command ${args.command} executed successfully. Terminal will close in ${
|
|
96
94
|
3000 / 1000
|
|
@@ -32,7 +32,6 @@ export class RunTerminalCommandTool implements MCPServerContribution {
|
|
|
32
32
|
getToolDefinition(): MCPToolDefinition {
|
|
33
33
|
return {
|
|
34
34
|
name: 'run_terminal_cmd',
|
|
35
|
-
label: 'Run Command',
|
|
36
35
|
description:
|
|
37
36
|
"PROPOSE a command to run on behalf of the user.\nIf you have this tool, note that you DO have the ability to run commands directly on the USER's system.\n\nAdhere to these rules:\n1. Based on the contents of the conversation, you will be told if you are in the same shell as a previous step or a new shell.\n2. If in a new shell, you should `cd` to the right directory and do necessary setup in addition to running the command.\n3. If in the same shell, the state will persist, no need to do things like `cd` to the same directory.\n4. For ANY commands that would use a pager, you should append ` | cat` to the command (or whatever is appropriate). You MUST do this for: git, less, head, tail, more, etc.\n5. For commands that are long running/expected to run indefinitely until interruption, please run them in the background. To run jobs in the background, set `is_background` to true rather than changing the details of the command.\n6. Dont include any newlines in the command.",
|
|
38
37
|
inputSchema,
|
|
@@ -15,13 +15,13 @@ export interface LLMContextService {
|
|
|
15
15
|
*/
|
|
16
16
|
cleanFileContext(): void;
|
|
17
17
|
|
|
18
|
-
onDidContextFilesChangeEvent: Event<
|
|
18
|
+
onDidContextFilesChangeEvent: Event<FileContext[]>;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* 从 context 中移除文件
|
|
22
22
|
* @param uri URI
|
|
23
23
|
*/
|
|
24
|
-
removeFileFromContext(uri: URI
|
|
24
|
+
removeFileFromContext(uri: URI): void;
|
|
25
25
|
|
|
26
26
|
/** 导出为可序列化格式 */
|
|
27
27
|
serialize(): SerializedContext;
|
|
@@ -30,18 +30,12 @@ export interface LLMContextService {
|
|
|
30
30
|
export interface FileContext {
|
|
31
31
|
uri: URI;
|
|
32
32
|
selection?: [number, number];
|
|
33
|
+
isManual: boolean;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export const LLMContextServiceToken = Symbol('LLMContextService');
|
|
36
37
|
|
|
37
|
-
export interface AttachFileContext {
|
|
38
|
-
content: string;
|
|
39
|
-
lineErrors: string[];
|
|
40
|
-
path: string;
|
|
41
|
-
language: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
38
|
export interface SerializedContext {
|
|
45
39
|
recentlyViewFiles: string[];
|
|
46
|
-
attachedFiles: Array<
|
|
40
|
+
attachedFiles: Array<{ content: string; lineErrors: string[]; path: string; language: string }>;
|
|
47
41
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Injectable } from '@opensumi/di';
|
|
2
|
+
import { MaybePromise } from '@opensumi/ide-core-common/lib/utils';
|
|
2
3
|
|
|
3
4
|
import { SerializedContext } from '../llm-context';
|
|
4
5
|
|
|
@@ -9,36 +10,37 @@ export interface ChatAgentPromptProvider {
|
|
|
9
10
|
* 提供上下文提示
|
|
10
11
|
* @param context 上下文
|
|
11
12
|
*/
|
|
12
|
-
provideContextPrompt(context: SerializedContext, userMessage: string): string
|
|
13
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): MaybePromise<string>;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
@Injectable()
|
|
16
17
|
export class DefaultChatAgentPromptProvider implements ChatAgentPromptProvider {
|
|
17
|
-
provideContextPrompt(context: SerializedContext, userMessage: string): string {
|
|
18
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): MaybePromise<string> {
|
|
18
19
|
return `
|
|
19
|
-
<additional_data>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
${context.recentlyViewFiles.map((file, idx) =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
20
|
+
<additional_data>
|
|
21
|
+
Below are some potentially helpful/relevant pieces of information for figuring out to respond
|
|
22
|
+
<recently_viewed_files>
|
|
23
|
+
${context.recentlyViewFiles.map((file, idx) => `${idx + 1} : ${file}`)}
|
|
24
|
+
</recently_viewed_files>
|
|
25
|
+
<attached_files>
|
|
26
|
+
${context.attachedFiles.map(
|
|
27
|
+
(file) =>
|
|
28
|
+
`
|
|
29
|
+
<file_contents>
|
|
30
|
+
\`\`\`${file.language} ${file.path}
|
|
31
|
+
${file.content}
|
|
32
|
+
\`\`\`
|
|
33
|
+
</file_contents>
|
|
34
|
+
<linter_errors>
|
|
35
|
+
${file.lineErrors.join('\n')}
|
|
36
|
+
</linter_errors>
|
|
37
|
+
`,
|
|
38
|
+
)}
|
|
39
|
+
|
|
40
|
+
</attached_files>
|
|
41
|
+
</additional_data>
|
|
42
|
+
<user_query>
|
|
43
|
+
${userMessage}
|
|
44
|
+
</user_query>`;
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -41,11 +41,14 @@ export abstract class BaseLanguageModel {
|
|
|
41
41
|
): Promise<any> {
|
|
42
42
|
const provider = this.initializeProvider(options);
|
|
43
43
|
const clientId = options.clientId;
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
|
|
45
|
+
let allFunctions: ToolRequest[] = [];
|
|
46
|
+
// 如果没有传入 clientId,则不使用工具
|
|
47
|
+
if (clientId) {
|
|
48
|
+
const registry = this.toolInvocationRegistryManager.getRegistry(clientId);
|
|
49
|
+
allFunctions = options.noTool ? [] : registry.getAllFunctions();
|
|
46
50
|
}
|
|
47
|
-
|
|
48
|
-
const allFunctions = options.noTool ? [] : registry.getAllFunctions();
|
|
51
|
+
|
|
49
52
|
return this.handleStreamingRequest(
|
|
50
53
|
provider,
|
|
51
54
|
request,
|