@opensumi/ide-ai-native 3.8.1-next-1740726474.0 → 3.8.1-next-1740735952.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 +1 -4
- package/lib/browser/ai-core.contribution.d.ts.map +1 -1
- package/lib/browser/ai-core.contribution.js +1 -20
- package/lib/browser/ai-core.contribution.js.map +1 -1
- package/lib/browser/chat/chat-manager.service.d.ts +0 -6
- package/lib/browser/chat/chat-manager.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-manager.service.js +1 -31
- 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.internal.service.d.ts +0 -1
- package/lib/browser/chat/chat.internal.service.d.ts.map +1 -1
- package/lib/browser/chat/chat.internal.service.js +0 -3
- package/lib/browser/chat/chat.internal.service.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/ChatHistory.d.ts +1 -0
- package/lib/browser/components/ChatHistory.d.ts.map +1 -1
- package/lib/browser/components/ChatHistory.js +14 -14
- package/lib/browser/components/ChatHistory.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.module.less → 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/layout/layout.module.less +4 -4
- package/lib/browser/mcp/base-apply.service.d.ts +40 -31
- package/lib/browser/mcp/base-apply.service.d.ts.map +1 -1
- package/lib/browser/mcp/base-apply.service.js +167 -233
- package/lib/browser/mcp/base-apply.service.js.map +1 -1
- package/lib/browser/mcp/tools/components/EditFile.d.ts.map +1 -1
- package/lib/browser/mcp/tools/components/EditFile.js +41 -55
- package/lib/browser/mcp/tools/components/EditFile.js.map +1 -1
- package/lib/browser/mcp/tools/components/index.module.less +3 -23
- 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/editFile.js +1 -1
- package/lib/browser/mcp/tools/editFile.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/EditFile.d.ts +1 -5
- package/lib/browser/mcp/tools/handlers/EditFile.d.ts.map +1 -1
- package/lib/browser/mcp/tools/handlers/EditFile.js +4 -4
- package/lib/browser/mcp/tools/handlers/EditFile.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/browser/model/msg-history-manager.d.ts +0 -1
- package/lib/browser/model/msg-history-manager.d.ts.map +1 -1
- package/lib/browser/model/msg-history-manager.js +2 -12
- package/lib/browser/model/msg-history-manager.js.map +1 -1
- package/lib/browser/types.d.ts +1 -1
- package/lib/browser/types.d.ts.map +1 -1
- package/lib/browser/widget/inline-diff/inline-diff-widget.module.less +0 -12
- package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts +0 -2
- package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts.map +1 -1
- package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js +4 -11
- package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.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 -4
- package/lib/common/prompts/context-prompt-provider.d.ts.map +1 -1
- package/lib/common/prompts/context-prompt-provider.js +22 -33
- package/lib/common/prompts/context-prompt-provider.js.map +1 -1
- package/lib/common/types.d.ts +0 -17
- package/lib/common/types.d.ts.map +1 -1
- package/lib/common/types.js.map +1 -1
- package/lib/node/base-language-model.d.ts +1 -1
- package/lib/node/base-language-model.d.ts.map +1 -1
- package/lib/node/base-language-model.js +3 -54
- package/lib/node/base-language-model.js.map +1 -1
- package/package.json +23 -23
- package/src/browser/ai-core.contribution.ts +1 -25
- package/src/browser/chat/chat-manager.service.ts +1 -29
- package/src/browser/chat/chat-model.ts +3 -18
- package/src/browser/chat/chat.internal.service.ts +0 -4
- 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/ChatHistory.tsx +15 -21
- package/src/browser/components/ChatInput.tsx +4 -67
- package/src/browser/components/ChatToolRender.tsx +2 -1
- package/src/browser/components/{chat-history.module.less → 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/layout/layout.module.less +4 -4
- package/src/browser/mcp/base-apply.service.ts +213 -266
- package/src/browser/mcp/tools/components/EditFile.tsx +60 -82
- package/src/browser/mcp/tools/components/index.module.less +3 -23
- package/src/browser/mcp/tools/createNewFileWithText.ts +0 -1
- package/src/browser/mcp/tools/editFile.ts +2 -2
- package/src/browser/mcp/tools/getDiagnosticsByPath.ts +0 -1
- package/src/browser/mcp/tools/handlers/EditFile.ts +4 -4
- package/src/browser/mcp/tools/handlers/RunCommand.ts +0 -2
- package/src/browser/mcp/tools/runTerminalCmd.ts +0 -1
- package/src/browser/model/msg-history-manager.ts +2 -12
- package/src/browser/types.ts +1 -1
- package/src/browser/widget/inline-diff/inline-diff-widget.module.less +0 -12
- package/src/browser/widget/inline-stream-diff/inline-stream-diff.handler.tsx +4 -13
- package/src/common/llm-context.ts +4 -10
- package/src/common/prompts/context-prompt-provider.ts +29 -38
- package/src/common/types.ts +0 -20
- package/src/node/base-language-model.ts +1 -63
- package/lib/browser/widget/inline-diff/inline-diff-manager.d.ts +0 -6
- package/lib/browser/widget/inline-diff/inline-diff-manager.d.ts.map +0 -1
- package/lib/browser/widget/inline-diff/inline-diff-manager.js +0 -27
- package/lib/browser/widget/inline-diff/inline-diff-manager.js.map +0 -1
- package/src/browser/widget/inline-diff/inline-diff-manager.tsx +0 -38
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cls from 'classnames';
|
|
2
|
-
import React, { useEffect, useMemo
|
|
2
|
+
import React, { useEffect, useMemo } from 'react';
|
|
3
3
|
|
|
4
4
|
import { Icon, Popover } from '@opensumi/ide-components';
|
|
5
5
|
import {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
Uri,
|
|
11
11
|
detectModeId,
|
|
12
12
|
path,
|
|
13
|
+
useAutorun,
|
|
13
14
|
useInjectable,
|
|
14
15
|
} from '@opensumi/ide-core-browser';
|
|
15
16
|
import { Loading } from '@opensumi/ide-core-browser/lib/components/ai-native';
|
|
@@ -17,24 +18,61 @@ import { ILanguageService } from '@opensumi/monaco-editor-core/esm/vs/editor/com
|
|
|
17
18
|
import { IModelService } from '@opensumi/monaco-editor-core/esm/vs/editor/common/services/model';
|
|
18
19
|
import { StandaloneServices } from '@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
|
|
19
20
|
|
|
20
|
-
import { CodeBlockData } from '../../../../common/types';
|
|
21
21
|
import { ChatMarkdown } from '../../../components/ChatMarkdown';
|
|
22
22
|
import { IMCPServerToolComponentProps } from '../../../types';
|
|
23
|
-
import { BaseApplyService } from '../../base-apply.service';
|
|
23
|
+
import { BaseApplyService, CodeBlockData } from '../../base-apply.service';
|
|
24
24
|
|
|
25
25
|
import styles from './index.module.less';
|
|
26
26
|
|
|
27
|
+
const renderStatus = (codeBlockData: CodeBlockData) => {
|
|
28
|
+
const status = codeBlockData.status;
|
|
29
|
+
switch (status) {
|
|
30
|
+
case 'generating':
|
|
31
|
+
return <Loading />;
|
|
32
|
+
case 'pending':
|
|
33
|
+
return (
|
|
34
|
+
<Popover title={status} id={'edit-file-tool-status-pending'}>
|
|
35
|
+
<Icon iconClass='codicon codicon-circle-large' />
|
|
36
|
+
</Popover>
|
|
37
|
+
);
|
|
38
|
+
case 'success':
|
|
39
|
+
return (
|
|
40
|
+
<Popover title={status} id={'edit-file-tool-status-success'}>
|
|
41
|
+
<Icon iconClass='codicon codicon-check-all' />
|
|
42
|
+
</Popover>
|
|
43
|
+
);
|
|
44
|
+
case 'failed':
|
|
45
|
+
return (
|
|
46
|
+
<Popover title={status} id={'edit-file-tool-status-failed'}>
|
|
47
|
+
<Icon iconClass='codicon codicon-error' color='var(--vscode-input-errorForeground)' />
|
|
48
|
+
</Popover>
|
|
49
|
+
);
|
|
50
|
+
case 'cancelled':
|
|
51
|
+
return (
|
|
52
|
+
<Popover title={status} id={'edit-file-tool-status-cancelled'}>
|
|
53
|
+
<Icon iconClass='codicon codicon-close' color='var(--vscode-input-placeholderForeground)' />
|
|
54
|
+
</Popover>
|
|
55
|
+
);
|
|
56
|
+
default:
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
27
61
|
export const EditFileToolComponent = (props: IMCPServerToolComponentProps) => {
|
|
28
62
|
const { args, messageId, toolCallId } = props;
|
|
29
|
-
const [mode, setMode] = useState<'code' | 'diff'>('code');
|
|
30
63
|
const labelService = useInjectable(LabelService);
|
|
31
64
|
const appConfig = useInjectable<AppConfig>(AppConfig);
|
|
32
65
|
const applyService = useInjectable<BaseApplyService>(BaseApplyService);
|
|
33
66
|
const { target_file = '', code_edit, instructions } = args || {};
|
|
34
67
|
const absolutePath = path.join(appConfig.workspaceDir, target_file);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
68
|
+
|
|
69
|
+
const codeBlockData = applyService.getCodeBlock(absolutePath, messageId);
|
|
70
|
+
|
|
71
|
+
useAutorun(applyService.codeBlockMapObservable);
|
|
72
|
+
|
|
73
|
+
if (toolCallId && codeBlockData) {
|
|
74
|
+
applyService.initToolCallId(codeBlockData.id, toolCallId);
|
|
75
|
+
}
|
|
38
76
|
|
|
39
77
|
const icon = useMemo(() => {
|
|
40
78
|
if (!target_file) {
|
|
@@ -53,66 +91,40 @@ export const EditFileToolComponent = (props: IMCPServerToolComponentProps) => {
|
|
|
53
91
|
return detectedModeId;
|
|
54
92
|
}, [target_file, absolutePath]);
|
|
55
93
|
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
const disposable = applyService.onCodeBlockUpdate((codeBlockData) => {
|
|
58
|
-
setCodeBlockData({ ...codeBlockData });
|
|
59
|
-
});
|
|
60
|
-
return () => {
|
|
61
|
-
disposable.dispose();
|
|
62
|
-
};
|
|
63
|
-
}, []);
|
|
64
|
-
|
|
65
94
|
// 多次迭代时,仅在首处tool组件中展示
|
|
66
|
-
|
|
67
|
-
if (!args || !codeBlockData) {
|
|
95
|
+
if (!args || !codeBlockData || (toolCallId && toolCallId !== codeBlockData.initToolCallId)) {
|
|
68
96
|
return null;
|
|
69
97
|
}
|
|
70
98
|
|
|
71
99
|
return [
|
|
72
100
|
instructions && <p>{instructions}</p>,
|
|
73
|
-
<div className={styles['edit-file-tool']} key={
|
|
101
|
+
<div className={styles['edit-file-tool']} key={`edit-file-tool-${codeBlockData.id}`}>
|
|
74
102
|
<div
|
|
75
103
|
className={cls(styles['edit-file-tool-header'], {
|
|
76
104
|
clickable: codeBlockData.status === 'pending' || codeBlockData.status === 'success',
|
|
77
105
|
})}
|
|
78
106
|
onClick={() => {
|
|
79
107
|
if (codeBlockData.status === 'pending') {
|
|
80
|
-
applyService.
|
|
108
|
+
applyService.reRenderPendingApply();
|
|
81
109
|
} else if (codeBlockData.status === 'success') {
|
|
82
|
-
applyService.revealApplyPosition(codeBlockData);
|
|
110
|
+
applyService.revealApplyPosition(codeBlockData.id);
|
|
83
111
|
}
|
|
84
112
|
}}
|
|
85
113
|
>
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
{codeBlockData.iterationCount
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
{renderStatus(codeBlockData)}
|
|
93
|
-
</div>
|
|
94
|
-
<div className={styles.right}>
|
|
95
|
-
<Popover title={'Show Code'} id={'edit-file-tool-show-code'}>
|
|
96
|
-
<Icon iconClass='codicon codicon-file-code' onClick={() => setMode('code')} />
|
|
97
|
-
</Popover>
|
|
98
|
-
{codeBlockData.applyResult?.diff && (
|
|
99
|
-
<Popover title={'Show Diff'} id={'edit-file-tool-show-diff'}>
|
|
100
|
-
<Icon iconClass='codicon codicon-diff-multiple' onClick={() => setMode('diff')} />
|
|
101
|
-
</Popover>
|
|
102
|
-
)}
|
|
103
|
-
</div>
|
|
114
|
+
{icon && <span className={icon}></span>}
|
|
115
|
+
<span className={styles['edit-file-tool-file-name']}>{target_file}</span>
|
|
116
|
+
{codeBlockData.iterationCount > 1 && (
|
|
117
|
+
<span className={styles['edit-file-tool-iteration-count']}>{codeBlockData.iterationCount}/3</span>
|
|
118
|
+
)}
|
|
119
|
+
{renderStatus(codeBlockData)}
|
|
104
120
|
</div>
|
|
105
|
-
<ChatMarkdown
|
|
106
|
-
markdown={
|
|
107
|
-
mode === 'code'
|
|
108
|
-
? `\`\`\`${languageId || ''}\n${code_edit}\n\`\`\``
|
|
109
|
-
: `\`\`\`diff\n${codeBlockData.applyResult?.diff}\n\`\`\``
|
|
110
|
-
}
|
|
111
|
-
hideInsert={true}
|
|
112
|
-
/>
|
|
121
|
+
<ChatMarkdown markdown={`\`\`\`${languageId || ''}\n${code_edit}\n\`\`\``} hideInsert={true} />
|
|
113
122
|
</div>,
|
|
114
123
|
codeBlockData.applyResult && codeBlockData.applyResult.diagnosticInfos.length > 0 && (
|
|
115
|
-
<div
|
|
124
|
+
<div
|
|
125
|
+
className={styles['edit-file-tool-diagnostic-errors']}
|
|
126
|
+
key={`edit-file-tool-diagnostic-errors-${codeBlockData.id}`}
|
|
127
|
+
>
|
|
116
128
|
<div className={styles['title']}>Found Lints:</div>
|
|
117
129
|
{codeBlockData.applyResult?.diagnosticInfos.map((info) => (
|
|
118
130
|
<div
|
|
@@ -130,37 +142,3 @@ export const EditFileToolComponent = (props: IMCPServerToolComponentProps) => {
|
|
|
130
142
|
),
|
|
131
143
|
];
|
|
132
144
|
};
|
|
133
|
-
|
|
134
|
-
const renderStatus = (codeBlockData: CodeBlockData) => {
|
|
135
|
-
const status = codeBlockData.status;
|
|
136
|
-
switch (status) {
|
|
137
|
-
case 'generating':
|
|
138
|
-
return <Loading />;
|
|
139
|
-
case 'pending':
|
|
140
|
-
return (
|
|
141
|
-
<Popover title='Pending' id={'edit-file-tool-status-pending'}>
|
|
142
|
-
<Icon iconClass='codicon codicon-circle-large' />
|
|
143
|
-
</Popover>
|
|
144
|
-
);
|
|
145
|
-
case 'success':
|
|
146
|
-
return (
|
|
147
|
-
<Popover title='Success' id={'edit-file-tool-status-success'}>
|
|
148
|
-
<Icon iconClass='codicon codicon-check-all' />
|
|
149
|
-
</Popover>
|
|
150
|
-
);
|
|
151
|
-
case 'failed':
|
|
152
|
-
return (
|
|
153
|
-
<Popover title='Failed' id={'edit-file-tool-status-failed'}>
|
|
154
|
-
<Icon iconClass='codicon codicon-error' style={{ color: 'var(--debugConsole-errorForeground)' }} />
|
|
155
|
-
</Popover>
|
|
156
|
-
);
|
|
157
|
-
case 'cancelled':
|
|
158
|
-
return (
|
|
159
|
-
<Popover title='Cancelled' id={'edit-file-tool-status-cancelled'}>
|
|
160
|
-
<Icon iconClass='codicon codicon-close' style={{ color: 'var(--input-placeholderForeground)' }} />
|
|
161
|
-
</Popover>
|
|
162
|
-
);
|
|
163
|
-
default:
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
.edit-file-tool-header {
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: center;
|
|
4
|
-
justify-content: space-between;
|
|
5
4
|
padding: 2px 8px;
|
|
6
5
|
border-bottom: 1px solid var(--vscode-commandCenter-inactiveBorder);
|
|
7
6
|
background-color: var(--design-block-background);
|
|
8
7
|
font-size: 10px;
|
|
9
8
|
margin-bottom: -4px;
|
|
10
9
|
border-radius: 8px 8px 0 0;
|
|
11
|
-
|
|
10
|
+
> span {
|
|
11
|
+
margin-right: 4px;
|
|
12
|
+
}
|
|
12
13
|
:global(span.codicon) {
|
|
13
14
|
font-size: 12px;
|
|
14
15
|
}
|
|
@@ -17,26 +18,6 @@
|
|
|
17
18
|
align-items: center;
|
|
18
19
|
justify-content: center;
|
|
19
20
|
}
|
|
20
|
-
.left,
|
|
21
|
-
.right {
|
|
22
|
-
display: flex;
|
|
23
|
-
align-items: center;
|
|
24
|
-
}
|
|
25
|
-
&::after {
|
|
26
|
-
display: none;
|
|
27
|
-
}
|
|
28
|
-
.left {
|
|
29
|
-
> span {
|
|
30
|
-
margin-right: 4px;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
.right > div {
|
|
34
|
-
margin-left: 4px;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
.edit-file-tool-file-name {
|
|
38
|
-
text-overflow: ellipsis;
|
|
39
|
-
overflow: hidden;
|
|
40
21
|
}
|
|
41
22
|
.edit-file-tool {
|
|
42
23
|
border: 1px solid var(--vscode-commandCenter-inactiveBorder);
|
|
@@ -154,7 +135,6 @@
|
|
|
154
135
|
background-color: var(--design-chatInput-background);
|
|
155
136
|
padding: 10px;
|
|
156
137
|
border-radius: 4px;
|
|
157
|
-
margin: 10px 0px;
|
|
158
138
|
|
|
159
139
|
.command_title {
|
|
160
140
|
display: flex;
|
|
@@ -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. ' +
|
|
@@ -69,8 +69,8 @@ You should specify the following arguments before the others: [target_file]`,
|
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
private async handler(args: z.infer<typeof inputSchema
|
|
73
|
-
const result = await this.editFileHandler.handler(args, args.
|
|
72
|
+
private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
|
|
73
|
+
const result = await this.editFileHandler.handler(args.targetFile, args.codeEdit, args.instructions);
|
|
74
74
|
return {
|
|
75
75
|
content: [
|
|
76
76
|
{
|
|
@@ -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. ' +
|
|
@@ -12,10 +12,10 @@ export class EditFileHandler {
|
|
|
12
12
|
@Autowired(BaseApplyService)
|
|
13
13
|
private applyService: BaseApplyService;
|
|
14
14
|
|
|
15
|
-
async handler(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const blockData = await this.applyService.apply(
|
|
15
|
+
async handler(relativePath: string, updateContent: string, instructions?: string) {
|
|
16
|
+
// TODO: ignore file
|
|
17
|
+
this.applyService.registerCodeBlock(relativePath, updateContent);
|
|
18
|
+
const blockData = await this.applyService.apply(relativePath, updateContent, instructions);
|
|
19
19
|
return blockData;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -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,
|
|
@@ -66,11 +66,6 @@ export class MsgHistoryManager extends Disposable {
|
|
|
66
66
|
return this.startIndex;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
public get lastMessageId(): string | undefined {
|
|
70
|
-
const list = this.messageList;
|
|
71
|
-
return list[list.length - 1]?.id;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
69
|
public getMessages(maxTokens?: number): IHistoryChatMessage[] {
|
|
75
70
|
if (maxTokens && this.totalTokens > maxTokens) {
|
|
76
71
|
while (this.totalTokens > maxTokens) {
|
|
@@ -114,14 +109,9 @@ export class MsgHistoryManager extends Disposable {
|
|
|
114
109
|
return;
|
|
115
110
|
}
|
|
116
111
|
|
|
117
|
-
|
|
118
|
-
const newAdditional = {
|
|
119
|
-
...oldAdditional,
|
|
120
|
-
...additional,
|
|
121
|
-
};
|
|
112
|
+
this.messageAdditionalMap.set(id, additional);
|
|
122
113
|
|
|
123
|
-
this.
|
|
124
|
-
this._onMessageAdditionalChange.fire(newAdditional);
|
|
114
|
+
this._onMessageAdditionalChange.fire(additional);
|
|
125
115
|
}
|
|
126
116
|
|
|
127
117
|
public getMessageAdditional(id: string): Record<string, any> {
|
package/src/browser/types.ts
CHANGED
|
@@ -19,15 +19,3 @@
|
|
|
19
19
|
display: flex;
|
|
20
20
|
position: relative;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
.inlineDiffManager {
|
|
24
|
-
display: flex;
|
|
25
|
-
padding: 12px 16px;
|
|
26
|
-
justify-content: center;
|
|
27
|
-
position: absolute;
|
|
28
|
-
bottom: 0;
|
|
29
|
-
left: 50%;
|
|
30
|
-
transform: translateX(-50%);
|
|
31
|
-
gap: 12px;
|
|
32
|
-
z-index: 999;
|
|
33
|
-
}
|
|
@@ -52,9 +52,6 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
|
|
|
52
52
|
protected readonly _onDidEditChange = this.registerDispose(new Emitter<void>());
|
|
53
53
|
public readonly onDidEditChange: Event<void> = this._onDidEditChange.event;
|
|
54
54
|
|
|
55
|
-
protected readonly onDiffFinishedEmitter = this.registerDispose(new Emitter<IComputeDiffData>());
|
|
56
|
-
public readonly onDiffFinished: Event<IComputeDiffData> = this.onDiffFinishedEmitter.event;
|
|
57
|
-
|
|
58
55
|
public previewerOptions: IDiffPreviewerOptions;
|
|
59
56
|
|
|
60
57
|
private originalModel: ITextModel;
|
|
@@ -448,8 +445,6 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
|
|
|
448
445
|
this.diffModel.set(currentDiffModel, tx);
|
|
449
446
|
});
|
|
450
447
|
|
|
451
|
-
this.onDiffFinishedEmitter.fire(currentDiffModel);
|
|
452
|
-
|
|
453
448
|
if (this.originalModel.id === this.monacoEditor.getModel()?.id) {
|
|
454
449
|
this.renderDiffEdits(currentDiffModel);
|
|
455
450
|
}
|
|
@@ -476,13 +471,10 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
|
|
|
476
471
|
}
|
|
477
472
|
|
|
478
473
|
public pushRateFinallyDiffStack(diffModel: IComputeDiffData): void {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
this.finallyRender(diffModel);
|
|
484
|
-
}
|
|
485
|
-
});
|
|
474
|
+
// 可能存在 rate editor controller 处理完之后接口层流式才结束
|
|
475
|
+
if (this.isEditing === false) {
|
|
476
|
+
this.finallyRender(diffModel);
|
|
477
|
+
}
|
|
486
478
|
}
|
|
487
479
|
|
|
488
480
|
public finallyRender(diffModel: IComputeDiffData): void {
|
|
@@ -495,7 +487,6 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
|
|
|
495
487
|
return;
|
|
496
488
|
}
|
|
497
489
|
|
|
498
|
-
this.onDiffFinishedEmitter.fire(diffModel);
|
|
499
490
|
this.renderPartialEditWidgets(diffModel);
|
|
500
491
|
this.renderDiffEdits(diffModel);
|
|
501
492
|
this.pushStackElement();
|
|
@@ -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,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Injectable } from '@opensumi/di';
|
|
2
|
+
import { MaybePromise } from '@opensumi/ide-core-common/lib/utils';
|
|
3
3
|
|
|
4
4
|
import { SerializedContext } from '../llm-context';
|
|
5
5
|
|
|
@@ -10,46 +10,37 @@ export interface ChatAgentPromptProvider {
|
|
|
10
10
|
* 提供上下文提示
|
|
11
11
|
* @param context 上下文
|
|
12
12
|
*/
|
|
13
|
-
provideContextPrompt(context: SerializedContext, userMessage: string): string
|
|
13
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): MaybePromise<string>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
@Injectable()
|
|
17
17
|
export class DefaultChatAgentPromptProvider implements ChatAgentPromptProvider {
|
|
18
|
-
|
|
19
|
-
protected readonly workbenchEditorService: WorkbenchEditorService;
|
|
20
|
-
|
|
21
|
-
provideContextPrompt(context: SerializedContext, userMessage: string): string {
|
|
22
|
-
const editor = this.workbenchEditorService.currentEditor;
|
|
23
|
-
const currentModel = editor?.currentDocumentModel;
|
|
18
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): MaybePromise<string> {
|
|
24
19
|
return `
|
|
25
|
-
<additional_data>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
${context.recentlyViewFiles.map((file, idx) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
</additional_data>
|
|
51
|
-
<user_query>
|
|
52
|
-
${userMessage}
|
|
53
|
-
</user_query>`;
|
|
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>`;
|
|
54
45
|
}
|
|
55
46
|
}
|
package/src/common/types.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { IMarker } from '@opensumi/ide-core-browser';
|
|
2
|
-
|
|
3
1
|
export enum NearestCodeBlockType {
|
|
4
2
|
Block = 'block',
|
|
5
3
|
Line = 'line',
|
|
@@ -48,21 +46,3 @@ export interface MCPTool {
|
|
|
48
46
|
inputSchema: any;
|
|
49
47
|
providerName: string;
|
|
50
48
|
}
|
|
51
|
-
|
|
52
|
-
export interface CodeBlockData {
|
|
53
|
-
toolCallId: string;
|
|
54
|
-
codeEdit: string;
|
|
55
|
-
updatedCode?: string;
|
|
56
|
-
relativePath: string;
|
|
57
|
-
status: CodeBlockStatus;
|
|
58
|
-
iterationCount: number;
|
|
59
|
-
createdAt: number;
|
|
60
|
-
version: number;
|
|
61
|
-
instructions?: string;
|
|
62
|
-
applyResult?: {
|
|
63
|
-
diff: string;
|
|
64
|
-
diagnosticInfos: IMarker[];
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export type CodeBlockStatus = 'generating' | 'pending' | 'success' | 'rejected' | 'failed' | 'cancelled';
|
|
@@ -60,7 +60,6 @@ export abstract class BaseLanguageModel {
|
|
|
60
60
|
options.topP,
|
|
61
61
|
options.topK,
|
|
62
62
|
options.providerOptions,
|
|
63
|
-
options.trimTexts,
|
|
64
63
|
cancellationToken,
|
|
65
64
|
);
|
|
66
65
|
}
|
|
@@ -88,7 +87,6 @@ export abstract class BaseLanguageModel {
|
|
|
88
87
|
topP?: number,
|
|
89
88
|
topK?: number,
|
|
90
89
|
providerOptions?: Record<string, any>,
|
|
91
|
-
trimTexts?: [string, string],
|
|
92
90
|
cancellationToken?: CancellationToken,
|
|
93
91
|
): Promise<any> {
|
|
94
92
|
try {
|
|
@@ -122,42 +120,9 @@ export abstract class BaseLanguageModel {
|
|
|
122
120
|
providerOptions,
|
|
123
121
|
});
|
|
124
122
|
|
|
125
|
-
// 状态跟踪变量
|
|
126
|
-
let isFirstChunk = true;
|
|
127
|
-
let bufferedText = '';
|
|
128
|
-
const pendingLines: string[] = [];
|
|
129
123
|
for await (const chunk of stream.fullStream) {
|
|
130
124
|
if (chunk.type === 'text-delta') {
|
|
131
|
-
|
|
132
|
-
// 将收到的文本追加到缓冲区
|
|
133
|
-
bufferedText += chunk.textDelta;
|
|
134
|
-
|
|
135
|
-
// 处理第一个文本块的前缀(只处理一次)
|
|
136
|
-
if (isFirstChunk && bufferedText.includes(trimTexts[0])) {
|
|
137
|
-
bufferedText = bufferedText.substring(bufferedText.indexOf(trimTexts[0]) + trimTexts[0].length);
|
|
138
|
-
isFirstChunk = false;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// 检查是否有完整的行,并将它们添加到待发送行队列
|
|
142
|
-
const lines = bufferedText.split('\n');
|
|
143
|
-
|
|
144
|
-
// 最后一个元素可能是不完整的行,保留在缓冲区
|
|
145
|
-
bufferedText = lines.pop() || '';
|
|
146
|
-
|
|
147
|
-
// 将完整的行添加到待发送队列
|
|
148
|
-
if (lines.length > 0) {
|
|
149
|
-
pendingLines.push(...lines);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 发送除最后几行外的所有行(保留足够的行以处理后缀)
|
|
153
|
-
while (pendingLines.length > 3) {
|
|
154
|
-
// 保留最后3行以确保能完整识别后缀
|
|
155
|
-
const lineToSend = pendingLines.shift() + '\n';
|
|
156
|
-
chatReadableStream.emitData({ kind: 'content', content: lineToSend });
|
|
157
|
-
}
|
|
158
|
-
} else {
|
|
159
|
-
chatReadableStream.emitData({ kind: 'content', content: chunk.textDelta });
|
|
160
|
-
}
|
|
125
|
+
chatReadableStream.emitData({ kind: 'content', content: chunk.textDelta });
|
|
161
126
|
} else if (chunk.type === 'tool-call') {
|
|
162
127
|
chatReadableStream.emitData({
|
|
163
128
|
kind: 'toolCall',
|
|
@@ -204,33 +169,6 @@ export abstract class BaseLanguageModel {
|
|
|
204
169
|
}
|
|
205
170
|
}
|
|
206
171
|
|
|
207
|
-
if (trimTexts?.[1]) {
|
|
208
|
-
// 完成处理所有块后,检查并发送剩余文本
|
|
209
|
-
|
|
210
|
-
// 将剩余缓冲区加入待发送行
|
|
211
|
-
if (bufferedText) {
|
|
212
|
-
pendingLines.push(bufferedText);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// 处理最后一行可能存在的后缀
|
|
216
|
-
if (pendingLines.length > 0) {
|
|
217
|
-
let lastLine = pendingLines[pendingLines.length - 1];
|
|
218
|
-
|
|
219
|
-
if (lastLine.endsWith(trimTexts[1])) {
|
|
220
|
-
// 移除后缀
|
|
221
|
-
lastLine = lastLine.substring(0, lastLine.length - trimTexts[1].length);
|
|
222
|
-
pendingLines[pendingLines.length - 1] = lastLine;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// 发送所有剩余的行
|
|
227
|
-
for (let i = 0; i < pendingLines.length; i++) {
|
|
228
|
-
const isLastLine = i === pendingLines.length - 1;
|
|
229
|
-
const lineToSend = pendingLines[i] + (isLastLine ? '' : '\n');
|
|
230
|
-
chatReadableStream.emitData({ kind: 'content', content: lineToSend });
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
172
|
chatReadableStream.end();
|
|
235
173
|
} catch (error) {
|
|
236
174
|
// Use a logger service in production instead of console
|