@codingame/monaco-vscode-a793b3ee-7ba9-5176-a019-30ec806fdd95-common 20.0.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/empty.js +1 -0
- package/package.json +50 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.d.ts +159 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.js +1318 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.d.ts +172 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.js +482 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSessionServiceImpl.d.ts +86 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSessionServiceImpl.js +377 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.d.ts +70 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.js +456 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.d.ts +40 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.js +276 -0
- package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.d.ts +22 -0
- package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.js +318 -0
- package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/notebookVisibleCellObserver.d.ts +18 -0
- package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/notebookVisibleCellObserver.js +59 -0
- package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.d.ts +69 -0
- package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.js +318 -0
@@ -0,0 +1,1318 @@
|
|
1
|
+
|
2
|
+
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
3
|
+
import { alert } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/aria/aria';
|
4
|
+
import { Barrier, DeferredPromise, Queue, raceCancellation } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
5
|
+
import { CancellationTokenSource, CancellationToken } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
6
|
+
import { toErrorMessage } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errorMessage';
|
7
|
+
import { onUnexpectedError } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
|
8
|
+
import { Emitter, Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
9
|
+
import { Lazy } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lazy';
|
10
|
+
import { DisposableStore, MutableDisposable, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
11
|
+
import { Schemas } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network';
|
12
|
+
import { MovingAverage } from '@codingame/monaco-vscode-api/vscode/vs/base/common/numbers';
|
13
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
14
|
+
import { isEqual } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
|
15
|
+
import { StopWatch } from '@codingame/monaco-vscode-api/vscode/vs/base/common/stopwatch';
|
16
|
+
import { assertType } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types';
|
17
|
+
import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
|
18
|
+
import { generateUuid } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uuid';
|
19
|
+
import { isCodeEditor } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/editorBrowser';
|
20
|
+
import { observableCodeEditor } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/observableCodeEditor';
|
21
|
+
import { ICodeEditorService } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/services/codeEditorService.service';
|
22
|
+
import { EditorOption } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/config/editorOptions';
|
23
|
+
import { Position } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/position';
|
24
|
+
import { Range } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/range';
|
25
|
+
import { Selection, SelectionDirection } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/core/selection';
|
26
|
+
import { TextEdit } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/languages';
|
27
|
+
import { IEditorWorkerService } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/services/editorWorker.service';
|
28
|
+
import { DefaultModelSHA1Computer } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/services/modelService';
|
29
|
+
import { InlineCompletionsController } from '@codingame/monaco-vscode-api/vscode/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController';
|
30
|
+
import { MessageController } from '@codingame/monaco-vscode-api/vscode/vs/editor/contrib/message/browser/messageController';
|
31
|
+
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
32
|
+
import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
|
33
|
+
import { IContextKeyService } from '@codingame/monaco-vscode-api/vscode/vs/platform/contextkey/common/contextkey.service';
|
34
|
+
import { IDialogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service';
|
35
|
+
import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
|
36
|
+
import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
|
37
|
+
import { SIDE_GROUP } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService';
|
38
|
+
import { IEditorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService.service';
|
39
|
+
import { IViewsService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/views/common/viewsService.service';
|
40
|
+
import { showChatView } from '@codingame/monaco-vscode-b994942c-360d-5b68-8a33-77d4bde6b714-common/vscode/vs/workbench/contrib/chat/browser/chat';
|
41
|
+
import { ChatRequestRemovalReason } from '@codingame/monaco-vscode-c2deffc4-ad68-5e63-8f95-9b89e0fc6898-common/vscode/vs/workbench/contrib/chat/common/chatModel';
|
42
|
+
import { IChatService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatService.service';
|
43
|
+
import { INotebookEditorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/notebook/browser/services/notebookEditorService.service';
|
44
|
+
import { InlineChatConfigKeys, INLINE_CHAT_ID, CTX_INLINE_CHAT_VISIBLE, CTX_INLINE_CHAT_EDITING, CTX_INLINE_CHAT_RESPONSE_TYPE, CTX_INLINE_CHAT_REQUEST_IN_PROGRESS, InlineChatResponseType } from '@codingame/monaco-vscode-e28ac690-06d5-5ee9-92d1-02df70296354-common/vscode/vs/workbench/contrib/inlineChat/common/inlineChat';
|
45
|
+
import { Session } from './inlineChatSession.js';
|
46
|
+
import { IInlineChatSessionService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/inlineChat/browser/inlineChatSessionService.service';
|
47
|
+
import { InlineChatError } from './inlineChatSessionServiceImpl.js';
|
48
|
+
import { LiveStrategy, HunkAction } from './inlineChatStrategies.js';
|
49
|
+
import { InlineChatZoneWidget } from './inlineChatZoneWidget.js';
|
50
|
+
import { ChatAgentLocation } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/constants';
|
51
|
+
import { ChatContextKeys } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatContextKeys';
|
52
|
+
import { ModifiedFileEntryState } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatEditingService';
|
53
|
+
import { observableConfigValue } from '@codingame/monaco-vscode-api/vscode/vs/platform/observable/common/platformObservableUtils';
|
54
|
+
import { ISharedWebContentExtractorService } from '@codingame/monaco-vscode-api/vscode/vs/platform/webContentExtractor/common/webContentExtractor.service';
|
55
|
+
import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
|
56
|
+
import { IChatAttachmentResolveService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/chatAttachmentResolveService.service';
|
57
|
+
import { INotebookService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/notebook/common/notebookService.service';
|
58
|
+
import { isNotebookContainingCellEditor } from '@codingame/monaco-vscode-e28ac690-06d5-5ee9-92d1-02df70296354-common/vscode/vs/workbench/contrib/notebook/browser/notebookEditor';
|
59
|
+
import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
|
60
|
+
import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
|
61
|
+
import { observableSignalFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableSignalFromEvent';
|
62
|
+
import { autorun, autorunWithStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
|
63
|
+
import { observableFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableFromEvent';
|
64
|
+
import { waitForState } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/utilsCancellation';
|
65
|
+
import { transaction } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/transaction';
|
66
|
+
|
67
|
+
var InlineChatController_1, InlineChatController1_1, InlineChatController2_1;
|
68
|
+
var State;
|
69
|
+
(function (State) {
|
70
|
+
State["CREATE_SESSION"] = "CREATE_SESSION";
|
71
|
+
State["INIT_UI"] = "INIT_UI";
|
72
|
+
State["WAIT_FOR_INPUT"] = "WAIT_FOR_INPUT";
|
73
|
+
State["SHOW_REQUEST"] = "SHOW_REQUEST";
|
74
|
+
State["PAUSE"] = "PAUSE";
|
75
|
+
State["CANCEL"] = "CANCEL";
|
76
|
+
State["ACCEPT"] = "DONE";
|
77
|
+
})(State || (State = {}));
|
78
|
+
var Message;
|
79
|
+
(function (Message) {
|
80
|
+
Message[Message["NONE"] = 0] = "NONE";
|
81
|
+
Message[Message["ACCEPT_SESSION"] = 1] = "ACCEPT_SESSION";
|
82
|
+
Message[Message["CANCEL_SESSION"] = 2] = "CANCEL_SESSION";
|
83
|
+
Message[Message["PAUSE_SESSION"] = 4] = "PAUSE_SESSION";
|
84
|
+
Message[Message["CANCEL_REQUEST"] = 8] = "CANCEL_REQUEST";
|
85
|
+
Message[Message["CANCEL_INPUT"] = 16] = "CANCEL_INPUT";
|
86
|
+
Message[Message["ACCEPT_INPUT"] = 32] = "ACCEPT_INPUT";
|
87
|
+
})(Message || (Message = {}));
|
88
|
+
class InlineChatRunOptions {
|
89
|
+
static isInlineChatRunOptions(options) {
|
90
|
+
const { initialSelection, initialRange, message, autoSend, position, existingSession, attachments: attachments } = options;
|
91
|
+
if (typeof message !== 'undefined' && typeof message !== 'string'
|
92
|
+
|| typeof autoSend !== 'undefined' && typeof autoSend !== 'boolean'
|
93
|
+
|| typeof initialRange !== 'undefined' && !Range.isIRange(initialRange)
|
94
|
+
|| typeof initialSelection !== 'undefined' && !Selection.isISelection(initialSelection)
|
95
|
+
|| typeof position !== 'undefined' && !Position.isIPosition(position)
|
96
|
+
|| typeof existingSession !== 'undefined' && !(existingSession instanceof Session)
|
97
|
+
|| typeof attachments !== 'undefined' && (!Array.isArray(attachments) || !attachments.every(item => item instanceof URI))) {
|
98
|
+
return false;
|
99
|
+
}
|
100
|
+
return true;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
let InlineChatController = class InlineChatController {
|
104
|
+
static { InlineChatController_1 = this; }
|
105
|
+
static { this.ID = 'editor.contrib.inlineChatController'; }
|
106
|
+
static get(editor) {
|
107
|
+
return editor.getContribution(InlineChatController_1.ID);
|
108
|
+
}
|
109
|
+
constructor(editor, configurationService) {
|
110
|
+
const inlineChat2 = observableConfigValue(InlineChatConfigKeys.EnableV2, false, configurationService);
|
111
|
+
this._delegate = derived(r => {
|
112
|
+
if (inlineChat2.read(r)) {
|
113
|
+
return InlineChatController2.get(editor);
|
114
|
+
}
|
115
|
+
else {
|
116
|
+
return InlineChatController1.get(editor);
|
117
|
+
}
|
118
|
+
});
|
119
|
+
}
|
120
|
+
dispose() {
|
121
|
+
}
|
122
|
+
get isActive() {
|
123
|
+
return this._delegate.get().isActive;
|
124
|
+
}
|
125
|
+
async run(arg) {
|
126
|
+
return this._delegate.get().run(arg);
|
127
|
+
}
|
128
|
+
focus() {
|
129
|
+
return this._delegate.get().focus();
|
130
|
+
}
|
131
|
+
get widget() {
|
132
|
+
return this._delegate.get().widget;
|
133
|
+
}
|
134
|
+
getWidgetPosition() {
|
135
|
+
return this._delegate.get().getWidgetPosition();
|
136
|
+
}
|
137
|
+
acceptSession() {
|
138
|
+
return this._delegate.get().acceptSession();
|
139
|
+
}
|
140
|
+
};
|
141
|
+
InlineChatController = InlineChatController_1 = ( __decorate([
|
142
|
+
( __param(1, IConfigurationService))
|
143
|
+
], InlineChatController));
|
144
|
+
let InlineChatController1 = InlineChatController1_1 = class InlineChatController1 {
|
145
|
+
static get(editor) {
|
146
|
+
return editor.getContribution(INLINE_CHAT_ID);
|
147
|
+
}
|
148
|
+
get chatWidget() {
|
149
|
+
return this._ui.value.widget.chatWidget;
|
150
|
+
}
|
151
|
+
constructor(_editor, _instaService, _inlineChatSessionService, _editorWorkerService, _logService, _configurationService, _dialogService, contextKeyService, _chatService, _editorService, notebookEditorService, _webContentExtractorService, _fileService, _chatAttachmentResolveService) {
|
152
|
+
this._editor = _editor;
|
153
|
+
this._instaService = _instaService;
|
154
|
+
this._inlineChatSessionService = _inlineChatSessionService;
|
155
|
+
this._editorWorkerService = _editorWorkerService;
|
156
|
+
this._logService = _logService;
|
157
|
+
this._configurationService = _configurationService;
|
158
|
+
this._dialogService = _dialogService;
|
159
|
+
this._chatService = _chatService;
|
160
|
+
this._editorService = _editorService;
|
161
|
+
this._webContentExtractorService = _webContentExtractorService;
|
162
|
+
this._fileService = _fileService;
|
163
|
+
this._chatAttachmentResolveService = _chatAttachmentResolveService;
|
164
|
+
this._isDisposed = false;
|
165
|
+
this._store = ( new DisposableStore());
|
166
|
+
this._messages = this._store.add(( new Emitter()));
|
167
|
+
this._onDidEnterState = this._store.add(( new Emitter()));
|
168
|
+
this._sessionStore = this._store.add(( new DisposableStore()));
|
169
|
+
this._stashedSession = this._store.add(( new MutableDisposable()));
|
170
|
+
this._ctxVisible = CTX_INLINE_CHAT_VISIBLE.bindTo(contextKeyService);
|
171
|
+
this._ctxEditing = CTX_INLINE_CHAT_EDITING.bindTo(contextKeyService);
|
172
|
+
this._ctxResponseType = CTX_INLINE_CHAT_RESPONSE_TYPE.bindTo(contextKeyService);
|
173
|
+
this._ctxRequestInProgress = CTX_INLINE_CHAT_REQUEST_IN_PROGRESS.bindTo(contextKeyService);
|
174
|
+
this._ctxResponse = ChatContextKeys.isResponse.bindTo(contextKeyService);
|
175
|
+
ChatContextKeys.responseHasError.bindTo(contextKeyService);
|
176
|
+
this._ui = ( new Lazy(() => {
|
177
|
+
const location = {
|
178
|
+
location: ChatAgentLocation.Editor,
|
179
|
+
resolveData: () => {
|
180
|
+
assertType(this._editor.hasModel());
|
181
|
+
assertType(this._session);
|
182
|
+
return {
|
183
|
+
type: ChatAgentLocation.Editor,
|
184
|
+
selection: this._editor.getSelection(),
|
185
|
+
document: this._session.textModelN.uri,
|
186
|
+
wholeRange: this._session?.wholeRange.trackedInitialRange,
|
187
|
+
};
|
188
|
+
}
|
189
|
+
};
|
190
|
+
let notebookEditor;
|
191
|
+
for (const editor of notebookEditorService.listNotebookEditors()) {
|
192
|
+
for (const [, codeEditor] of editor.codeEditors) {
|
193
|
+
if (codeEditor === this._editor) {
|
194
|
+
notebookEditor = editor;
|
195
|
+
location.location = ChatAgentLocation.Notebook;
|
196
|
+
break;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
}
|
200
|
+
const zone = _instaService.createInstance(InlineChatZoneWidget, location, undefined, { editor: this._editor, notebookEditor });
|
201
|
+
this._store.add(zone);
|
202
|
+
this._store.add(zone.widget.chatWidget.onDidClear(async () => {
|
203
|
+
const r = this.joinCurrentRun();
|
204
|
+
this.cancelSession();
|
205
|
+
await r;
|
206
|
+
this.run();
|
207
|
+
}));
|
208
|
+
return zone;
|
209
|
+
}));
|
210
|
+
this._store.add(this._editor.onDidChangeModel(async (e) => {
|
211
|
+
if (this._session || !e.newModelUrl) {
|
212
|
+
return;
|
213
|
+
}
|
214
|
+
const existingSession = this._inlineChatSessionService.getSession(this._editor, e.newModelUrl);
|
215
|
+
if (!existingSession) {
|
216
|
+
return;
|
217
|
+
}
|
218
|
+
this._log('session RESUMING after model change', e);
|
219
|
+
await this.run({ existingSession });
|
220
|
+
}));
|
221
|
+
this._store.add(this._inlineChatSessionService.onDidEndSession(e => {
|
222
|
+
if (e.session === this._session && e.endedByExternalCause) {
|
223
|
+
this._log('session ENDED by external cause');
|
224
|
+
this.acceptSession();
|
225
|
+
}
|
226
|
+
}));
|
227
|
+
this._store.add(this._inlineChatSessionService.onDidMoveSession(async (e) => {
|
228
|
+
if (e.editor === this._editor) {
|
229
|
+
this._log('session RESUMING after move', e);
|
230
|
+
await this.run({ existingSession: e.session });
|
231
|
+
}
|
232
|
+
}));
|
233
|
+
this._log(`NEW controller`);
|
234
|
+
}
|
235
|
+
dispose() {
|
236
|
+
if (this._currentRun) {
|
237
|
+
this._messages.fire(this._session?.chatModel.hasRequests
|
238
|
+
? Message.PAUSE_SESSION
|
239
|
+
: Message.CANCEL_SESSION);
|
240
|
+
}
|
241
|
+
this._store.dispose();
|
242
|
+
this._isDisposed = true;
|
243
|
+
this._log('DISPOSED controller');
|
244
|
+
}
|
245
|
+
_log(message, ...more) {
|
246
|
+
if (message instanceof Error) {
|
247
|
+
this._logService.error(message, ...more);
|
248
|
+
}
|
249
|
+
else {
|
250
|
+
this._logService.trace(`[IE] (editor:${this._editor.getId()}) ${message}`, ...more);
|
251
|
+
}
|
252
|
+
}
|
253
|
+
get widget() {
|
254
|
+
return this._ui.value.widget;
|
255
|
+
}
|
256
|
+
getId() {
|
257
|
+
return INLINE_CHAT_ID;
|
258
|
+
}
|
259
|
+
getWidgetPosition() {
|
260
|
+
return this._ui.value.position;
|
261
|
+
}
|
262
|
+
async run(options = {}) {
|
263
|
+
let lastState;
|
264
|
+
const d = this._onDidEnterState.event(e => lastState = e);
|
265
|
+
try {
|
266
|
+
this.acceptSession();
|
267
|
+
if (this._currentRun) {
|
268
|
+
await this._currentRun;
|
269
|
+
}
|
270
|
+
if (options.initialSelection) {
|
271
|
+
this._editor.setSelection(options.initialSelection);
|
272
|
+
}
|
273
|
+
this._stashedSession.clear();
|
274
|
+
this._currentRun = this._nextState(State.CREATE_SESSION, options);
|
275
|
+
await this._currentRun;
|
276
|
+
}
|
277
|
+
catch (error) {
|
278
|
+
this._log('error during run', error);
|
279
|
+
onUnexpectedError(error);
|
280
|
+
if (this._session) {
|
281
|
+
this._inlineChatSessionService.releaseSession(this._session);
|
282
|
+
}
|
283
|
+
this[State.PAUSE]();
|
284
|
+
}
|
285
|
+
finally {
|
286
|
+
this._currentRun = undefined;
|
287
|
+
d.dispose();
|
288
|
+
}
|
289
|
+
return lastState !== State.CANCEL;
|
290
|
+
}
|
291
|
+
async _nextState(state, options) {
|
292
|
+
let nextState = state;
|
293
|
+
while (nextState && !this._isDisposed) {
|
294
|
+
this._log('setState to ', nextState);
|
295
|
+
const p = this[nextState](options);
|
296
|
+
this._onDidEnterState.fire(nextState);
|
297
|
+
nextState = await p;
|
298
|
+
}
|
299
|
+
}
|
300
|
+
async [State.CREATE_SESSION](options) {
|
301
|
+
assertType(this._session === undefined);
|
302
|
+
assertType(this._editor.hasModel());
|
303
|
+
let session = options.existingSession;
|
304
|
+
let initPosition;
|
305
|
+
if (options.position) {
|
306
|
+
initPosition = Position.lift(options.position).delta(-1);
|
307
|
+
delete options.position;
|
308
|
+
}
|
309
|
+
const widgetPosition = this._showWidget(session?.headless, true, initPosition);
|
310
|
+
let errorMessage = ( localize(7676, "Failed to start editor chat"));
|
311
|
+
if (!session) {
|
312
|
+
const createSessionCts = ( new CancellationTokenSource());
|
313
|
+
const msgListener = Event.once(this._messages.event)(m => {
|
314
|
+
this._log('state=_createSession) message received', m);
|
315
|
+
if (m === Message.ACCEPT_INPUT) {
|
316
|
+
options.autoSend = true;
|
317
|
+
this._ui.value.widget.updateInfo(( localize(7677, "Getting ready...")));
|
318
|
+
}
|
319
|
+
else {
|
320
|
+
createSessionCts.cancel();
|
321
|
+
}
|
322
|
+
});
|
323
|
+
try {
|
324
|
+
session = await this._inlineChatSessionService.createSession(this._editor, { wholeRange: options.initialRange }, createSessionCts.token);
|
325
|
+
}
|
326
|
+
catch (error) {
|
327
|
+
if (error instanceof InlineChatError || error?.name === InlineChatError.code) {
|
328
|
+
errorMessage = error.message;
|
329
|
+
}
|
330
|
+
}
|
331
|
+
createSessionCts.dispose();
|
332
|
+
msgListener.dispose();
|
333
|
+
if (createSessionCts.token.isCancellationRequested) {
|
334
|
+
if (session) {
|
335
|
+
this._inlineChatSessionService.releaseSession(session);
|
336
|
+
}
|
337
|
+
return State.CANCEL;
|
338
|
+
}
|
339
|
+
}
|
340
|
+
delete options.initialRange;
|
341
|
+
delete options.existingSession;
|
342
|
+
if (!session) {
|
343
|
+
MessageController.get(this._editor)?.showMessage(errorMessage, widgetPosition);
|
344
|
+
this._log('Failed to start editor chat');
|
345
|
+
return State.CANCEL;
|
346
|
+
}
|
347
|
+
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._ui.value, session.headless);
|
348
|
+
this._session = session;
|
349
|
+
return State.INIT_UI;
|
350
|
+
}
|
351
|
+
async [State.INIT_UI](options) {
|
352
|
+
assertType(this._session);
|
353
|
+
assertType(this._strategy);
|
354
|
+
InlineCompletionsController.get(this._editor)?.reject();
|
355
|
+
this._sessionStore.clear();
|
356
|
+
const wholeRangeDecoration = this._editor.createDecorationsCollection();
|
357
|
+
const handleWholeRangeChange = () => {
|
358
|
+
const newDecorations = this._strategy?.getWholeRangeDecoration() ?? [];
|
359
|
+
wholeRangeDecoration.set(newDecorations);
|
360
|
+
this._ctxEditing.set(!this._session?.wholeRange.trackedInitialRange.isEmpty());
|
361
|
+
};
|
362
|
+
this._sessionStore.add(toDisposable(() => {
|
363
|
+
wholeRangeDecoration.clear();
|
364
|
+
this._ctxEditing.reset();
|
365
|
+
}));
|
366
|
+
this._sessionStore.add(this._session.wholeRange.onDidChange(handleWholeRangeChange));
|
367
|
+
handleWholeRangeChange();
|
368
|
+
this._ui.value.widget.setChatModel(this._session.chatModel);
|
369
|
+
this._updatePlaceholder();
|
370
|
+
const isModelEmpty = !this._session.chatModel.hasRequests;
|
371
|
+
this._ui.value.widget.updateToolbar(true);
|
372
|
+
this._ui.value.widget.toggleStatus(!isModelEmpty);
|
373
|
+
this._showWidget(this._session.headless, isModelEmpty);
|
374
|
+
this._sessionStore.add(this._editor.onDidChangeModel((e) => {
|
375
|
+
const msg = this._session?.chatModel.hasRequests
|
376
|
+
? Message.PAUSE_SESSION
|
377
|
+
: Message.CANCEL_SESSION;
|
378
|
+
this._log('model changed, pause or cancel session', msg, e);
|
379
|
+
this._messages.fire(msg);
|
380
|
+
}));
|
381
|
+
this._sessionStore.add(this._editor.onDidChangeModelContent(e => {
|
382
|
+
if (this._session?.hunkData.ignoreTextModelNChanges || this._ui.value.widget.hasFocus()) {
|
383
|
+
return;
|
384
|
+
}
|
385
|
+
const wholeRange = this._session.wholeRange;
|
386
|
+
let shouldFinishSession = false;
|
387
|
+
if (this._configurationService.getValue(InlineChatConfigKeys.FinishOnType)) {
|
388
|
+
for (const { range } of e.changes) {
|
389
|
+
shouldFinishSession = !Range.areIntersectingOrTouching(range, wholeRange.value);
|
390
|
+
}
|
391
|
+
}
|
392
|
+
this._session.recordExternalEditOccurred(shouldFinishSession);
|
393
|
+
if (shouldFinishSession) {
|
394
|
+
this._log('text changed outside of whole range, FINISH session');
|
395
|
+
this.acceptSession();
|
396
|
+
}
|
397
|
+
}));
|
398
|
+
this._sessionStore.add(this._session.chatModel.onDidChange(async (e) => {
|
399
|
+
if (e.kind === 'removeRequest') {
|
400
|
+
await this._session.undoChangesUntil(e.requestId);
|
401
|
+
}
|
402
|
+
}));
|
403
|
+
const editState = this._createChatTextEditGroupState();
|
404
|
+
let didEdit = false;
|
405
|
+
for (const request of this._session.chatModel.getRequests()) {
|
406
|
+
if (!request.response || request.response.result?.errorDetails) {
|
407
|
+
break;
|
408
|
+
}
|
409
|
+
for (const part of request.response.response.value) {
|
410
|
+
if (part.kind !== 'textEditGroup' || !isEqual(part.uri, this._session.textModelN.uri)) {
|
411
|
+
continue;
|
412
|
+
}
|
413
|
+
if (part.state?.applied) {
|
414
|
+
continue;
|
415
|
+
}
|
416
|
+
for (const edit of part.edits) {
|
417
|
+
this._makeChanges(edit, undefined, !didEdit);
|
418
|
+
didEdit = true;
|
419
|
+
}
|
420
|
+
part.state ??= editState;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
if (didEdit) {
|
424
|
+
const diff = await this._editorWorkerService.computeDiff(this._session.textModel0.uri, this._session.textModelN.uri, { computeMoves: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, ignoreTrimWhitespace: false }, 'advanced');
|
425
|
+
this._session.wholeRange.fixup(diff?.changes ?? []);
|
426
|
+
await this._session.hunkData.recompute(editState, diff);
|
427
|
+
this._updateCtxResponseType();
|
428
|
+
}
|
429
|
+
options.position = await this._strategy.renderChanges();
|
430
|
+
if (this._session.chatModel.requestInProgress) {
|
431
|
+
return State.SHOW_REQUEST;
|
432
|
+
}
|
433
|
+
else {
|
434
|
+
return State.WAIT_FOR_INPUT;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
async [State.WAIT_FOR_INPUT](options) {
|
438
|
+
assertType(this._session);
|
439
|
+
assertType(this._strategy);
|
440
|
+
this._updatePlaceholder();
|
441
|
+
if (options.message) {
|
442
|
+
this._updateInput(options.message);
|
443
|
+
alert(options.message);
|
444
|
+
delete options.message;
|
445
|
+
this._showWidget(this._session.headless, false);
|
446
|
+
}
|
447
|
+
let message = Message.NONE;
|
448
|
+
let request;
|
449
|
+
const barrier = ( new Barrier());
|
450
|
+
const store = ( new DisposableStore());
|
451
|
+
store.add(this._session.chatModel.onDidChange(e => {
|
452
|
+
if (e.kind === 'addRequest') {
|
453
|
+
request = e.request;
|
454
|
+
message = Message.ACCEPT_INPUT;
|
455
|
+
barrier.open();
|
456
|
+
}
|
457
|
+
}));
|
458
|
+
store.add(this._strategy.onDidAccept(() => this.acceptSession()));
|
459
|
+
store.add(this._strategy.onDidDiscard(() => this.cancelSession()));
|
460
|
+
store.add(Event.once(this._messages.event)(m => {
|
461
|
+
this._log('state=_waitForInput) message received', m);
|
462
|
+
message = m;
|
463
|
+
barrier.open();
|
464
|
+
}));
|
465
|
+
if (options.attachments) {
|
466
|
+
await Promise.all(( options.attachments.map(async (attachment) => {
|
467
|
+
await this._ui.value.widget.chatWidget.attachmentModel.addFile(attachment);
|
468
|
+
})));
|
469
|
+
delete options.attachments;
|
470
|
+
}
|
471
|
+
if (options.autoSend) {
|
472
|
+
delete options.autoSend;
|
473
|
+
this._showWidget(this._session.headless, false);
|
474
|
+
this._ui.value.widget.chatWidget.acceptInput();
|
475
|
+
}
|
476
|
+
await barrier.wait();
|
477
|
+
store.dispose();
|
478
|
+
if (message & (Message.CANCEL_INPUT | Message.CANCEL_SESSION)) {
|
479
|
+
return State.CANCEL;
|
480
|
+
}
|
481
|
+
if (message & Message.PAUSE_SESSION) {
|
482
|
+
return State.PAUSE;
|
483
|
+
}
|
484
|
+
if (message & Message.ACCEPT_SESSION) {
|
485
|
+
this._ui.value.widget.selectAll();
|
486
|
+
return State.ACCEPT;
|
487
|
+
}
|
488
|
+
if (!request?.message.text) {
|
489
|
+
return State.WAIT_FOR_INPUT;
|
490
|
+
}
|
491
|
+
return State.SHOW_REQUEST;
|
492
|
+
}
|
493
|
+
async [State.SHOW_REQUEST](options) {
|
494
|
+
assertType(this._session);
|
495
|
+
assertType(this._strategy);
|
496
|
+
assertType(this._session.chatModel.requestInProgress);
|
497
|
+
this._ctxRequestInProgress.set(true);
|
498
|
+
const { chatModel } = this._session;
|
499
|
+
const request = chatModel.lastRequest;
|
500
|
+
assertType(request);
|
501
|
+
assertType(request.response);
|
502
|
+
this._showWidget(this._session.headless, false);
|
503
|
+
this._ui.value.widget.selectAll();
|
504
|
+
this._ui.value.widget.updateInfo('');
|
505
|
+
this._ui.value.widget.toggleStatus(true);
|
506
|
+
const { response } = request;
|
507
|
+
const responsePromise = ( new DeferredPromise());
|
508
|
+
const store = ( new DisposableStore());
|
509
|
+
const progressiveEditsCts = store.add(( new CancellationTokenSource()));
|
510
|
+
const progressiveEditsAvgDuration = ( new MovingAverage());
|
511
|
+
const progressiveEditsClock = StopWatch.create();
|
512
|
+
const progressiveEditsQueue = ( new Queue());
|
513
|
+
const origDeco = this._editor.getOption(EditorOption.renderValidationDecorations);
|
514
|
+
this._editor.updateOptions({
|
515
|
+
renderValidationDecorations: 'off'
|
516
|
+
});
|
517
|
+
store.add(toDisposable(() => {
|
518
|
+
this._editor.updateOptions({
|
519
|
+
renderValidationDecorations: origDeco
|
520
|
+
});
|
521
|
+
}));
|
522
|
+
let next = State.WAIT_FOR_INPUT;
|
523
|
+
store.add(Event.once(this._messages.event)(message => {
|
524
|
+
this._log('state=_makeRequest) message received', message);
|
525
|
+
this._chatService.cancelCurrentRequestForSession(chatModel.sessionId);
|
526
|
+
if (message & Message.CANCEL_SESSION) {
|
527
|
+
next = State.CANCEL;
|
528
|
+
}
|
529
|
+
else if (message & Message.PAUSE_SESSION) {
|
530
|
+
next = State.PAUSE;
|
531
|
+
}
|
532
|
+
else if (message & Message.ACCEPT_SESSION) {
|
533
|
+
next = State.ACCEPT;
|
534
|
+
}
|
535
|
+
}));
|
536
|
+
store.add(chatModel.onDidChange(async (e) => {
|
537
|
+
if (e.kind === 'removeRequest' && e.requestId === request.id) {
|
538
|
+
progressiveEditsCts.cancel();
|
539
|
+
responsePromise.complete();
|
540
|
+
if (e.reason === ChatRequestRemovalReason.Resend) {
|
541
|
+
next = State.SHOW_REQUEST;
|
542
|
+
}
|
543
|
+
else {
|
544
|
+
next = State.CANCEL;
|
545
|
+
}
|
546
|
+
return;
|
547
|
+
}
|
548
|
+
if (e.kind === 'move') {
|
549
|
+
assertType(this._session);
|
550
|
+
const log = (msg, ...args) => this._log('state=_showRequest) moving inline chat', msg, ...args);
|
551
|
+
log('move was requested', e.target, e.range);
|
552
|
+
const initialSelection = Selection.fromRange(Range.lift(e.range), SelectionDirection.LTR);
|
553
|
+
const editorPane = await this._editorService.openEditor({ resource: e.target, options: { selection: initialSelection } }, SIDE_GROUP);
|
554
|
+
if (!editorPane) {
|
555
|
+
log('opening editor failed');
|
556
|
+
return;
|
557
|
+
}
|
558
|
+
const newEditor = editorPane.getControl();
|
559
|
+
if (!isCodeEditor(newEditor) || !newEditor.hasModel()) {
|
560
|
+
log('new editor is either missing or not a code editor or does not have a model');
|
561
|
+
return;
|
562
|
+
}
|
563
|
+
if (this._inlineChatSessionService.getSession(newEditor, e.target)) {
|
564
|
+
log('new editor ALREADY has a session');
|
565
|
+
return;
|
566
|
+
}
|
567
|
+
const newSession = await this._inlineChatSessionService.createSession(newEditor, {
|
568
|
+
session: this._session,
|
569
|
+
}, CancellationToken.None);
|
570
|
+
InlineChatController1_1.get(newEditor)?.run({ existingSession: newSession });
|
571
|
+
next = State.CANCEL;
|
572
|
+
responsePromise.complete();
|
573
|
+
return;
|
574
|
+
}
|
575
|
+
}));
|
576
|
+
store.add(this._ui.value.widget.chatWidget.inputEditor.onDidChangeModelContent(() => {
|
577
|
+
this._chatService.cancelCurrentRequestForSession(chatModel.sessionId);
|
578
|
+
}));
|
579
|
+
let lastLength = 0;
|
580
|
+
let isFirstChange = true;
|
581
|
+
const editState = this._createChatTextEditGroupState();
|
582
|
+
let localEditGroup;
|
583
|
+
const handleResponse = () => {
|
584
|
+
this._updateCtxResponseType();
|
585
|
+
if (!localEditGroup) {
|
586
|
+
localEditGroup = response.response.value.find(part => part.kind === 'textEditGroup' && isEqual(part.uri, this._session?.textModelN.uri));
|
587
|
+
}
|
588
|
+
if (localEditGroup) {
|
589
|
+
localEditGroup.state ??= editState;
|
590
|
+
const edits = localEditGroup.edits;
|
591
|
+
const newEdits = edits.slice(lastLength);
|
592
|
+
if (newEdits.length > 0) {
|
593
|
+
this._log(`${this._session?.textModelN.uri.toString()} received ${newEdits.length} edits`);
|
594
|
+
lastLength = edits.length;
|
595
|
+
progressiveEditsAvgDuration.update(progressiveEditsClock.elapsed());
|
596
|
+
progressiveEditsClock.reset();
|
597
|
+
progressiveEditsQueue.queue(async () => {
|
598
|
+
const startThen = this._session.wholeRange.value.getStartPosition();
|
599
|
+
for (const edits of newEdits) {
|
600
|
+
await this._makeChanges(edits, {
|
601
|
+
duration: progressiveEditsAvgDuration.value,
|
602
|
+
token: progressiveEditsCts.token
|
603
|
+
}, isFirstChange);
|
604
|
+
isFirstChange = false;
|
605
|
+
}
|
606
|
+
const startNow = this._session.wholeRange.value.getStartPosition();
|
607
|
+
if (!startNow.equals(startThen) || !this._ui.value.position?.equals(startNow)) {
|
608
|
+
this._showWidget(this._session.headless, false, startNow.delta(-1));
|
609
|
+
}
|
610
|
+
});
|
611
|
+
}
|
612
|
+
}
|
613
|
+
if (response.isCanceled) {
|
614
|
+
progressiveEditsCts.cancel();
|
615
|
+
responsePromise.complete();
|
616
|
+
}
|
617
|
+
else if (response.isComplete) {
|
618
|
+
responsePromise.complete();
|
619
|
+
}
|
620
|
+
};
|
621
|
+
store.add(response.onDidChange(handleResponse));
|
622
|
+
handleResponse();
|
623
|
+
await responsePromise.p;
|
624
|
+
await progressiveEditsQueue.whenIdle();
|
625
|
+
if (response.result?.errorDetails && !response.result.errorDetails.responseIsFiltered) {
|
626
|
+
await this._session.undoChangesUntil(response.requestId);
|
627
|
+
}
|
628
|
+
store.dispose();
|
629
|
+
const diff = await this._editorWorkerService.computeDiff(this._session.textModel0.uri, this._session.textModelN.uri, { computeMoves: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, ignoreTrimWhitespace: false }, 'advanced');
|
630
|
+
this._session.wholeRange.fixup(diff?.changes ?? []);
|
631
|
+
await this._session.hunkData.recompute(editState, diff);
|
632
|
+
this._ctxRequestInProgress.set(false);
|
633
|
+
let newPosition;
|
634
|
+
if (response.result?.errorDetails) ;
|
635
|
+
else if (response.response.value.length === 0) {
|
636
|
+
const status = ( localize(7678, "No results, please refine your input and try again"));
|
637
|
+
this._ui.value.widget.updateStatus(status, { classes: ['warn'] });
|
638
|
+
}
|
639
|
+
else {
|
640
|
+
this._ui.value.widget.updateStatus('');
|
641
|
+
}
|
642
|
+
const position = await this._strategy.renderChanges();
|
643
|
+
if (position) {
|
644
|
+
const selection = this._editor.getSelection();
|
645
|
+
if (selection?.containsPosition(position)) {
|
646
|
+
if (position.lineNumber - selection.startLineNumber > 8) {
|
647
|
+
newPosition = position;
|
648
|
+
}
|
649
|
+
}
|
650
|
+
else {
|
651
|
+
newPosition = position;
|
652
|
+
}
|
653
|
+
}
|
654
|
+
this._showWidget(this._session.headless, false, newPosition);
|
655
|
+
return next;
|
656
|
+
}
|
657
|
+
async [State.PAUSE]() {
|
658
|
+
this._resetWidget();
|
659
|
+
this._strategy?.dispose?.();
|
660
|
+
this._session = undefined;
|
661
|
+
}
|
662
|
+
async [State.ACCEPT]() {
|
663
|
+
assertType(this._session);
|
664
|
+
assertType(this._strategy);
|
665
|
+
this._sessionStore.clear();
|
666
|
+
try {
|
667
|
+
await this._strategy.apply();
|
668
|
+
}
|
669
|
+
catch (err) {
|
670
|
+
this._dialogService.error(( localize(7679, "Failed to apply changes.", toErrorMessage(err))));
|
671
|
+
this._log('FAILED to apply changes');
|
672
|
+
this._log(err);
|
673
|
+
}
|
674
|
+
this._resetWidget();
|
675
|
+
this._inlineChatSessionService.releaseSession(this._session);
|
676
|
+
this._strategy?.dispose();
|
677
|
+
this._strategy = undefined;
|
678
|
+
this._session = undefined;
|
679
|
+
}
|
680
|
+
async [State.CANCEL]() {
|
681
|
+
this._resetWidget();
|
682
|
+
if (this._session) {
|
683
|
+
assertType(this._strategy);
|
684
|
+
this._sessionStore.clear();
|
685
|
+
const shouldStash = !this._session.isUnstashed && this._session.chatModel.hasRequests && this._session.hunkData.size === this._session.hunkData.pending;
|
686
|
+
let undoCancelEdits = [];
|
687
|
+
try {
|
688
|
+
undoCancelEdits = this._strategy.cancel();
|
689
|
+
}
|
690
|
+
catch (err) {
|
691
|
+
this._dialogService.error(( localize(7680, "Failed to discard changes.", toErrorMessage(err))));
|
692
|
+
this._log('FAILED to discard changes');
|
693
|
+
this._log(err);
|
694
|
+
}
|
695
|
+
this._stashedSession.clear();
|
696
|
+
if (shouldStash) {
|
697
|
+
this._stashedSession.value = this._inlineChatSessionService.stashSession(this._session, this._editor, undoCancelEdits);
|
698
|
+
}
|
699
|
+
else {
|
700
|
+
this._inlineChatSessionService.releaseSession(this._session);
|
701
|
+
}
|
702
|
+
}
|
703
|
+
this._strategy?.dispose();
|
704
|
+
this._strategy = undefined;
|
705
|
+
this._session = undefined;
|
706
|
+
}
|
707
|
+
_showWidget(headless = false, initialRender = false, position) {
|
708
|
+
assertType(this._editor.hasModel());
|
709
|
+
this._ctxVisible.set(true);
|
710
|
+
let widgetPosition;
|
711
|
+
if (position) {
|
712
|
+
widgetPosition = position;
|
713
|
+
}
|
714
|
+
else if (this._ui.rawValue?.position) {
|
715
|
+
if (this._ui.rawValue?.position.lineNumber === 1) {
|
716
|
+
widgetPosition = this._ui.rawValue?.position.delta(-1);
|
717
|
+
}
|
718
|
+
else {
|
719
|
+
widgetPosition = this._ui.rawValue?.position;
|
720
|
+
}
|
721
|
+
}
|
722
|
+
else {
|
723
|
+
widgetPosition = this._editor.getSelection().getStartPosition().delta(-1);
|
724
|
+
}
|
725
|
+
if (this._session && !position && (this._session.hasChangedText || this._session.chatModel.hasRequests)) {
|
726
|
+
widgetPosition = this._session.wholeRange.trackedInitialRange.getStartPosition().delta(-1);
|
727
|
+
}
|
728
|
+
if (initialRender && (this._editor.getOption(EditorOption.stickyScroll)).enabled) {
|
729
|
+
this._editor.revealLine(widgetPosition.lineNumber);
|
730
|
+
}
|
731
|
+
if (!headless) {
|
732
|
+
if (this._ui.rawValue?.position) {
|
733
|
+
this._ui.value.updatePositionAndHeight(widgetPosition);
|
734
|
+
}
|
735
|
+
else {
|
736
|
+
this._ui.value.show(widgetPosition);
|
737
|
+
}
|
738
|
+
}
|
739
|
+
return widgetPosition;
|
740
|
+
}
|
741
|
+
_resetWidget() {
|
742
|
+
this._sessionStore.clear();
|
743
|
+
this._ctxVisible.reset();
|
744
|
+
this._ui.rawValue?.hide();
|
745
|
+
if (this._editor.hasWidgetFocus()) {
|
746
|
+
this._editor.focus();
|
747
|
+
}
|
748
|
+
}
|
749
|
+
_updateCtxResponseType() {
|
750
|
+
if (!this._session) {
|
751
|
+
this._ctxResponseType.set(InlineChatResponseType.None);
|
752
|
+
return;
|
753
|
+
}
|
754
|
+
const hasLocalEdit = (response) => {
|
755
|
+
return ( response.value.some(
|
756
|
+
part => part.kind === 'textEditGroup' && isEqual(part.uri, this._session?.textModelN.uri)
|
757
|
+
));
|
758
|
+
};
|
759
|
+
let responseType = InlineChatResponseType.None;
|
760
|
+
for (const request of this._session.chatModel.getRequests()) {
|
761
|
+
if (!request.response) {
|
762
|
+
continue;
|
763
|
+
}
|
764
|
+
responseType = InlineChatResponseType.Messages;
|
765
|
+
if (hasLocalEdit(request.response.response)) {
|
766
|
+
responseType = InlineChatResponseType.MessagesAndEdits;
|
767
|
+
break;
|
768
|
+
}
|
769
|
+
}
|
770
|
+
this._ctxResponseType.set(responseType);
|
771
|
+
this._ctxResponse.set(responseType !== InlineChatResponseType.None);
|
772
|
+
}
|
773
|
+
_createChatTextEditGroupState() {
|
774
|
+
assertType(this._session);
|
775
|
+
const sha1 = ( new DefaultModelSHA1Computer());
|
776
|
+
const textModel0Sha1 = sha1.canComputeSHA1(this._session.textModel0)
|
777
|
+
? sha1.computeSHA1(this._session.textModel0)
|
778
|
+
: generateUuid();
|
779
|
+
return {
|
780
|
+
sha1: textModel0Sha1,
|
781
|
+
applied: 0
|
782
|
+
};
|
783
|
+
}
|
784
|
+
async _makeChanges(edits, opts, undoStopBefore) {
|
785
|
+
assertType(this._session);
|
786
|
+
assertType(this._strategy);
|
787
|
+
const moreMinimalEdits = await this._editorWorkerService.computeMoreMinimalEdits(this._session.textModelN.uri, edits);
|
788
|
+
this._log('edits from PROVIDER and after making them MORE MINIMAL', this._session.agent.extensionId, edits, moreMinimalEdits);
|
789
|
+
if (moreMinimalEdits?.length === 0) {
|
790
|
+
return;
|
791
|
+
}
|
792
|
+
const actualEdits = !opts && moreMinimalEdits ? moreMinimalEdits : edits;
|
793
|
+
const editOperations = ( actualEdits.map(TextEdit.asEditOperation));
|
794
|
+
const editsObserver = {
|
795
|
+
start: () => this._session.hunkData.ignoreTextModelNChanges = true,
|
796
|
+
stop: () => this._session.hunkData.ignoreTextModelNChanges = false,
|
797
|
+
};
|
798
|
+
if (opts) {
|
799
|
+
await this._strategy.makeProgressiveChanges(editOperations, editsObserver, opts, undoStopBefore);
|
800
|
+
}
|
801
|
+
else {
|
802
|
+
await this._strategy.makeChanges(editOperations, editsObserver, undoStopBefore);
|
803
|
+
}
|
804
|
+
}
|
805
|
+
_updatePlaceholder() {
|
806
|
+
this._ui.value.widget.placeholder = this._session?.agent.description ?? ( localize(7681, 'Ask or edit in context'));
|
807
|
+
}
|
808
|
+
_updateInput(text, selectAll = true) {
|
809
|
+
this._ui.value.widget.chatWidget.setInput(text);
|
810
|
+
if (selectAll) {
|
811
|
+
const newSelection = ( new Selection(1, 1, Number.MAX_SAFE_INTEGER, 1));
|
812
|
+
this._ui.value.widget.chatWidget.inputEditor.setSelection(newSelection);
|
813
|
+
}
|
814
|
+
}
|
815
|
+
arrowOut(up) {
|
816
|
+
if (this._ui.value.position && this._editor.hasModel()) {
|
817
|
+
const { column } = this._editor.getPosition();
|
818
|
+
const { lineNumber } = this._ui.value.position;
|
819
|
+
const newLine = up ? lineNumber : lineNumber + 1;
|
820
|
+
this._editor.setPosition({ lineNumber: newLine, column });
|
821
|
+
this._editor.focus();
|
822
|
+
}
|
823
|
+
}
|
824
|
+
focus() {
|
825
|
+
this._ui.value.widget.focus();
|
826
|
+
}
|
827
|
+
async viewInChat() {
|
828
|
+
if (!this._strategy || !this._session) {
|
829
|
+
return;
|
830
|
+
}
|
831
|
+
let someApplied = false;
|
832
|
+
let lastEdit;
|
833
|
+
const uri = this._editor.getModel()?.uri;
|
834
|
+
const requests = this._session.chatModel.getRequests();
|
835
|
+
for (const request of requests) {
|
836
|
+
if (!request.response) {
|
837
|
+
continue;
|
838
|
+
}
|
839
|
+
for (const part of request.response.response.value) {
|
840
|
+
if (part.kind === 'textEditGroup' && isEqual(part.uri, uri)) {
|
841
|
+
someApplied = someApplied || Boolean(part.state?.applied);
|
842
|
+
lastEdit = part;
|
843
|
+
part.edits = [];
|
844
|
+
part.state = undefined;
|
845
|
+
}
|
846
|
+
}
|
847
|
+
}
|
848
|
+
const doEdits = this._strategy.cancel();
|
849
|
+
if (someApplied) {
|
850
|
+
assertType(lastEdit);
|
851
|
+
lastEdit.edits = [doEdits];
|
852
|
+
}
|
853
|
+
await this._instaService.invokeFunction(moveToPanelChat, this._session?.chatModel);
|
854
|
+
this.cancelSession();
|
855
|
+
}
|
856
|
+
acceptSession() {
|
857
|
+
const response = this._session?.chatModel.getRequests().at(-1)?.response;
|
858
|
+
if (response) {
|
859
|
+
this._chatService.notifyUserAction({
|
860
|
+
sessionId: response.session.sessionId,
|
861
|
+
requestId: response.requestId,
|
862
|
+
agentId: response.agent?.id,
|
863
|
+
command: response.slashCommand?.name,
|
864
|
+
result: response.result,
|
865
|
+
action: {
|
866
|
+
kind: 'inlineChat',
|
867
|
+
action: 'accepted'
|
868
|
+
}
|
869
|
+
});
|
870
|
+
}
|
871
|
+
this._messages.fire(Message.ACCEPT_SESSION);
|
872
|
+
}
|
873
|
+
acceptHunk(hunkInfo) {
|
874
|
+
return this._strategy?.performHunkAction(hunkInfo, HunkAction.Accept);
|
875
|
+
}
|
876
|
+
discardHunk(hunkInfo) {
|
877
|
+
return this._strategy?.performHunkAction(hunkInfo, HunkAction.Discard);
|
878
|
+
}
|
879
|
+
toggleDiff(hunkInfo) {
|
880
|
+
return this._strategy?.performHunkAction(hunkInfo, HunkAction.ToggleDiff);
|
881
|
+
}
|
882
|
+
moveHunk(next) {
|
883
|
+
this.focus();
|
884
|
+
this._strategy?.performHunkAction(undefined, next ? HunkAction.MoveNext : HunkAction.MovePrev);
|
885
|
+
}
|
886
|
+
async cancelSession() {
|
887
|
+
const response = this._session?.chatModel.lastRequest?.response;
|
888
|
+
if (response) {
|
889
|
+
this._chatService.notifyUserAction({
|
890
|
+
sessionId: response.session.sessionId,
|
891
|
+
requestId: response.requestId,
|
892
|
+
agentId: response.agent?.id,
|
893
|
+
command: response.slashCommand?.name,
|
894
|
+
result: response.result,
|
895
|
+
action: {
|
896
|
+
kind: 'inlineChat',
|
897
|
+
action: 'discarded'
|
898
|
+
}
|
899
|
+
});
|
900
|
+
}
|
901
|
+
this._messages.fire(Message.CANCEL_SESSION);
|
902
|
+
}
|
903
|
+
reportIssue() {
|
904
|
+
const response = this._session?.chatModel.lastRequest?.response;
|
905
|
+
if (response) {
|
906
|
+
this._chatService.notifyUserAction({
|
907
|
+
sessionId: response.session.sessionId,
|
908
|
+
requestId: response.requestId,
|
909
|
+
agentId: response.agent?.id,
|
910
|
+
command: response.slashCommand?.name,
|
911
|
+
result: response.result,
|
912
|
+
action: { kind: 'bug' }
|
913
|
+
});
|
914
|
+
}
|
915
|
+
}
|
916
|
+
unstashLastSession() {
|
917
|
+
const result = this._stashedSession.value?.unstash();
|
918
|
+
return result;
|
919
|
+
}
|
920
|
+
joinCurrentRun() {
|
921
|
+
return this._currentRun;
|
922
|
+
}
|
923
|
+
get isActive() {
|
924
|
+
return Boolean(this._currentRun);
|
925
|
+
}
|
926
|
+
async createImageAttachment(attachment) {
|
927
|
+
if (attachment.scheme === Schemas.file) {
|
928
|
+
if (await this._fileService.canHandleResource(attachment)) {
|
929
|
+
return await this._chatAttachmentResolveService.resolveImageEditorAttachContext(attachment);
|
930
|
+
}
|
931
|
+
}
|
932
|
+
else if (attachment.scheme === Schemas.http || attachment.scheme === Schemas.https) {
|
933
|
+
const extractedImages = await this._webContentExtractorService.readImage(attachment, CancellationToken.None);
|
934
|
+
if (extractedImages) {
|
935
|
+
return await this._chatAttachmentResolveService.resolveImageEditorAttachContext(attachment, extractedImages);
|
936
|
+
}
|
937
|
+
}
|
938
|
+
return undefined;
|
939
|
+
}
|
940
|
+
};
|
941
|
+
InlineChatController1 = InlineChatController1_1 = ( __decorate([
|
942
|
+
( __param(1, IInstantiationService)),
|
943
|
+
( __param(2, IInlineChatSessionService)),
|
944
|
+
( __param(3, IEditorWorkerService)),
|
945
|
+
( __param(4, ILogService)),
|
946
|
+
( __param(5, IConfigurationService)),
|
947
|
+
( __param(6, IDialogService)),
|
948
|
+
( __param(7, IContextKeyService)),
|
949
|
+
( __param(8, IChatService)),
|
950
|
+
( __param(9, IEditorService)),
|
951
|
+
( __param(10, INotebookEditorService)),
|
952
|
+
( __param(11, ISharedWebContentExtractorService)),
|
953
|
+
( __param(12, IFileService)),
|
954
|
+
( __param(13, IChatAttachmentResolveService))
|
955
|
+
], InlineChatController1));
|
956
|
+
let InlineChatController2 = class InlineChatController2 {
|
957
|
+
static { InlineChatController2_1 = this; }
|
958
|
+
static { this.ID = 'editor.contrib.inlineChatController2'; }
|
959
|
+
static get(editor) {
|
960
|
+
return editor.getContribution(InlineChatController2_1.ID) ?? undefined;
|
961
|
+
}
|
962
|
+
get widget() {
|
963
|
+
return this._zone.value.widget;
|
964
|
+
}
|
965
|
+
get isActive() {
|
966
|
+
return Boolean(this._currentSession.get());
|
967
|
+
}
|
968
|
+
constructor(_editor, _instaService, _notebookEditorService, _inlineChatSessions, codeEditorService, contextKeyService, _webContentExtractorService, _fileService, _chatAttachmentResolveService, _editorService, inlineChatService, configurationService) {
|
969
|
+
this._editor = _editor;
|
970
|
+
this._instaService = _instaService;
|
971
|
+
this._notebookEditorService = _notebookEditorService;
|
972
|
+
this._inlineChatSessions = _inlineChatSessions;
|
973
|
+
this._webContentExtractorService = _webContentExtractorService;
|
974
|
+
this._fileService = _fileService;
|
975
|
+
this._chatAttachmentResolveService = _chatAttachmentResolveService;
|
976
|
+
this._editorService = _editorService;
|
977
|
+
this._store = ( new DisposableStore());
|
978
|
+
this._showWidgetOverrideObs = observableValue(this, false);
|
979
|
+
this._isActiveController = observableValue(this, false);
|
980
|
+
const ctxInlineChatVisible = CTX_INLINE_CHAT_VISIBLE.bindTo(contextKeyService);
|
981
|
+
this._zone = ( new Lazy(() => {
|
982
|
+
const location = {
|
983
|
+
location: ChatAgentLocation.Editor,
|
984
|
+
resolveData: () => {
|
985
|
+
assertType(this._editor.hasModel());
|
986
|
+
return {
|
987
|
+
type: ChatAgentLocation.Editor,
|
988
|
+
selection: this._editor.getSelection(),
|
989
|
+
document: this._editor.getModel().uri,
|
990
|
+
wholeRange: this._editor.getSelection(),
|
991
|
+
};
|
992
|
+
}
|
993
|
+
};
|
994
|
+
let notebookEditor;
|
995
|
+
for (const editor of this._notebookEditorService.listNotebookEditors()) {
|
996
|
+
for (const [, codeEditor] of editor.codeEditors) {
|
997
|
+
if (codeEditor === this._editor) {
|
998
|
+
location.location = ChatAgentLocation.Notebook;
|
999
|
+
notebookEditor = editor;
|
1000
|
+
if (configurationService.getValue(InlineChatConfigKeys.notebookAgent)) {
|
1001
|
+
location.resolveData = () => {
|
1002
|
+
assertType(this._editor.hasModel());
|
1003
|
+
return {
|
1004
|
+
type: ChatAgentLocation.Notebook,
|
1005
|
+
sessionInputUri: this._editor.getModel().uri,
|
1006
|
+
};
|
1007
|
+
};
|
1008
|
+
}
|
1009
|
+
break;
|
1010
|
+
}
|
1011
|
+
}
|
1012
|
+
}
|
1013
|
+
const result = this._instaService.createInstance(InlineChatZoneWidget, location, {
|
1014
|
+
enableWorkingSet: 'implicit',
|
1015
|
+
rendererOptions: {
|
1016
|
+
renderTextEditsAsSummary: _uri => true
|
1017
|
+
}
|
1018
|
+
}, { editor: this._editor, notebookEditor });
|
1019
|
+
result.domNode.classList.add('inline-chat-2');
|
1020
|
+
return result;
|
1021
|
+
}));
|
1022
|
+
const editorObs = observableCodeEditor(_editor);
|
1023
|
+
const sessionsSignal = observableSignalFromEvent(this, _inlineChatSessions.onDidChangeSessions);
|
1024
|
+
this._currentSession = derived(r => {
|
1025
|
+
sessionsSignal.read(r);
|
1026
|
+
const model = editorObs.model.read(r);
|
1027
|
+
const value = model && _inlineChatSessions.getSession2(model.uri);
|
1028
|
+
return value ?? undefined;
|
1029
|
+
});
|
1030
|
+
this._store.add(autorun(r => {
|
1031
|
+
const session = this._currentSession.read(r);
|
1032
|
+
if (!session) {
|
1033
|
+
this._isActiveController.set(false, undefined);
|
1034
|
+
return;
|
1035
|
+
}
|
1036
|
+
let foundOne = false;
|
1037
|
+
for (const editor of codeEditorService.listCodeEditors()) {
|
1038
|
+
if (Boolean(InlineChatController2_1.get(editor)?._isActiveController.get())) {
|
1039
|
+
foundOne = true;
|
1040
|
+
break;
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
if (!foundOne && editorObs.isFocused.read(r)) {
|
1044
|
+
this._isActiveController.set(true, undefined);
|
1045
|
+
}
|
1046
|
+
}));
|
1047
|
+
const visibleSessionObs = observableValue(this, undefined);
|
1048
|
+
this._store.add(autorunWithStore((r, store) => {
|
1049
|
+
const model = editorObs.model.read(r);
|
1050
|
+
const session = this._currentSession.read(r);
|
1051
|
+
const isActive = this._isActiveController.read(r);
|
1052
|
+
if (!session || !isActive || !model) {
|
1053
|
+
visibleSessionObs.set(undefined, undefined);
|
1054
|
+
return;
|
1055
|
+
}
|
1056
|
+
const { chatModel } = session;
|
1057
|
+
const showShowUntil = this._showWidgetOverrideObs.read(r);
|
1058
|
+
const hasNoRequests = chatModel.getRequests().length === 0;
|
1059
|
+
const hideOnRequest = inlineChatService.hideOnRequest.read(r);
|
1060
|
+
const responseListener = store.add(( new MutableDisposable()));
|
1061
|
+
if (hideOnRequest) {
|
1062
|
+
store.add(chatModel.onDidChange(e => {
|
1063
|
+
if (e.kind === 'addRequest') {
|
1064
|
+
transaction(tx => {
|
1065
|
+
this._showWidgetOverrideObs.set(false, tx);
|
1066
|
+
visibleSessionObs.set(undefined, tx);
|
1067
|
+
});
|
1068
|
+
const { response } = e.request;
|
1069
|
+
if (!response) {
|
1070
|
+
return;
|
1071
|
+
}
|
1072
|
+
responseListener.value = response.onDidChange(async (e) => {
|
1073
|
+
if (!response.isComplete) {
|
1074
|
+
return;
|
1075
|
+
}
|
1076
|
+
const shouldShow = response.isCanceled
|
1077
|
+
|| response.result?.errorDetails
|
1078
|
+
|| !response.response.value.find(part => part.kind === 'textEditGroup'
|
1079
|
+
&& part.edits.length > 0
|
1080
|
+
&& isEqual(part.uri, model.uri));
|
1081
|
+
if (shouldShow) {
|
1082
|
+
visibleSessionObs.set(session, undefined);
|
1083
|
+
}
|
1084
|
+
});
|
1085
|
+
}
|
1086
|
+
}));
|
1087
|
+
}
|
1088
|
+
if (showShowUntil || hasNoRequests || !hideOnRequest) {
|
1089
|
+
visibleSessionObs.set(session, undefined);
|
1090
|
+
}
|
1091
|
+
else {
|
1092
|
+
visibleSessionObs.set(undefined, undefined);
|
1093
|
+
}
|
1094
|
+
}));
|
1095
|
+
this._store.add(autorun(r => {
|
1096
|
+
const session = visibleSessionObs.read(r);
|
1097
|
+
if (!session) {
|
1098
|
+
this._zone.rawValue?.hide();
|
1099
|
+
_editor.focus();
|
1100
|
+
ctxInlineChatVisible.reset();
|
1101
|
+
}
|
1102
|
+
else {
|
1103
|
+
ctxInlineChatVisible.set(true);
|
1104
|
+
this._zone.value.widget.setChatModel(session.chatModel);
|
1105
|
+
if (!this._zone.value.position) {
|
1106
|
+
this._zone.value.show(session.initialPosition);
|
1107
|
+
}
|
1108
|
+
this._zone.value.reveal(this._zone.value.position);
|
1109
|
+
this._zone.value.widget.focus();
|
1110
|
+
this._zone.value.widget.updateToolbar(true);
|
1111
|
+
const entry = session.editingSession.getEntry(session.uri);
|
1112
|
+
entry?.autoAcceptController.get()?.cancel();
|
1113
|
+
const requestCount = observableFromEvent(this, session.chatModel.onDidChange, () => session.chatModel.getRequests().length).read(r);
|
1114
|
+
this._zone.value.widget.updateToolbar(requestCount > 0);
|
1115
|
+
}
|
1116
|
+
}));
|
1117
|
+
this._store.add(autorun(r => {
|
1118
|
+
const session = visibleSessionObs.read(r);
|
1119
|
+
const entry = session?.editingSession.readEntry(session.uri, r);
|
1120
|
+
const pane = this._editorService.visibleEditorPanes.find(candidate => candidate.getControl() === this._editor || isNotebookContainingCellEditor(candidate, this._editor));
|
1121
|
+
if (pane && entry) {
|
1122
|
+
entry?.getEditorIntegration(pane);
|
1123
|
+
}
|
1124
|
+
}));
|
1125
|
+
}
|
1126
|
+
dispose() {
|
1127
|
+
this._store.dispose();
|
1128
|
+
}
|
1129
|
+
toggleWidgetUntilNextRequest() {
|
1130
|
+
const value = this._showWidgetOverrideObs.get();
|
1131
|
+
this._showWidgetOverrideObs.set(!value, undefined);
|
1132
|
+
}
|
1133
|
+
getWidgetPosition() {
|
1134
|
+
return this._zone.rawValue?.position;
|
1135
|
+
}
|
1136
|
+
focus() {
|
1137
|
+
this._zone.rawValue?.widget.focus();
|
1138
|
+
}
|
1139
|
+
markActiveController() {
|
1140
|
+
this._isActiveController.set(true, undefined);
|
1141
|
+
}
|
1142
|
+
async run(arg) {
|
1143
|
+
assertType(this._editor.hasModel());
|
1144
|
+
this.markActiveController();
|
1145
|
+
const uri = this._editor.getModel().uri;
|
1146
|
+
const session = this._inlineChatSessions.getSession2(uri)
|
1147
|
+
?? (await this._inlineChatSessions.createSession2(this._editor, uri, CancellationToken.None));
|
1148
|
+
if (arg && InlineChatRunOptions.isInlineChatRunOptions(arg)) {
|
1149
|
+
if (arg.initialRange) {
|
1150
|
+
this._editor.revealRange(arg.initialRange);
|
1151
|
+
}
|
1152
|
+
if (arg.initialSelection) {
|
1153
|
+
this._editor.setSelection(arg.initialSelection);
|
1154
|
+
}
|
1155
|
+
if (arg.attachments) {
|
1156
|
+
await Promise.all(( arg.attachments.map(async (attachment) => {
|
1157
|
+
await this._zone.value.widget.chatWidget.attachmentModel.addFile(attachment);
|
1158
|
+
})));
|
1159
|
+
delete arg.attachments;
|
1160
|
+
}
|
1161
|
+
if (arg.message) {
|
1162
|
+
this._zone.value.widget.chatWidget.setInput(arg.message);
|
1163
|
+
if (arg.autoSend) {
|
1164
|
+
await this._zone.value.widget.chatWidget.acceptInput();
|
1165
|
+
}
|
1166
|
+
}
|
1167
|
+
}
|
1168
|
+
await Event.toPromise(session.editingSession.onDidDispose);
|
1169
|
+
const rejected = session.editingSession.getEntry(uri)?.state.get() === ModifiedFileEntryState.Rejected;
|
1170
|
+
return !rejected;
|
1171
|
+
}
|
1172
|
+
acceptSession() {
|
1173
|
+
const value = this._currentSession.get();
|
1174
|
+
value?.editingSession.accept();
|
1175
|
+
}
|
1176
|
+
async createImageAttachment(attachment) {
|
1177
|
+
const value = this._currentSession.get();
|
1178
|
+
if (!value) {
|
1179
|
+
return undefined;
|
1180
|
+
}
|
1181
|
+
if (attachment.scheme === Schemas.file) {
|
1182
|
+
if (await this._fileService.canHandleResource(attachment)) {
|
1183
|
+
return await this._chatAttachmentResolveService.resolveImageEditorAttachContext(attachment);
|
1184
|
+
}
|
1185
|
+
}
|
1186
|
+
else if (attachment.scheme === Schemas.http || attachment.scheme === Schemas.https) {
|
1187
|
+
const extractedImages = await this._webContentExtractorService.readImage(attachment, CancellationToken.None);
|
1188
|
+
if (extractedImages) {
|
1189
|
+
return await this._chatAttachmentResolveService.resolveImageEditorAttachContext(attachment, extractedImages);
|
1190
|
+
}
|
1191
|
+
}
|
1192
|
+
return undefined;
|
1193
|
+
}
|
1194
|
+
};
|
1195
|
+
InlineChatController2 = InlineChatController2_1 = ( __decorate([
|
1196
|
+
( __param(1, IInstantiationService)),
|
1197
|
+
( __param(2, INotebookEditorService)),
|
1198
|
+
( __param(3, IInlineChatSessionService)),
|
1199
|
+
( __param(4, ICodeEditorService)),
|
1200
|
+
( __param(5, IContextKeyService)),
|
1201
|
+
( __param(6, ISharedWebContentExtractorService)),
|
1202
|
+
( __param(7, IFileService)),
|
1203
|
+
( __param(8, IChatAttachmentResolveService)),
|
1204
|
+
( __param(9, IEditorService)),
|
1205
|
+
( __param(10, IInlineChatSessionService)),
|
1206
|
+
( __param(11, IConfigurationService))
|
1207
|
+
], InlineChatController2));
|
1208
|
+
async function reviewEdits(accessor, editor, stream, token) {
|
1209
|
+
if (!editor.hasModel()) {
|
1210
|
+
return false;
|
1211
|
+
}
|
1212
|
+
const chatService = accessor.get(IChatService);
|
1213
|
+
const uri = editor.getModel().uri;
|
1214
|
+
const chatModel = chatService.startSession(ChatAgentLocation.Editor, token, false);
|
1215
|
+
chatModel.startEditingSession(true);
|
1216
|
+
const editSession = await chatModel.editingSessionObs?.promise;
|
1217
|
+
const store = ( new DisposableStore());
|
1218
|
+
store.add(chatModel);
|
1219
|
+
const chatRequest = chatModel?.addRequest({ text: '', parts: [] }, { variables: [] }, 0);
|
1220
|
+
assertType(chatRequest.response);
|
1221
|
+
chatRequest.response.updateContent({ kind: 'textEdit', uri, edits: [], done: false });
|
1222
|
+
for await (const chunk of stream) {
|
1223
|
+
if (token.isCancellationRequested) {
|
1224
|
+
chatRequest.response.cancel();
|
1225
|
+
break;
|
1226
|
+
}
|
1227
|
+
chatRequest.response.updateContent({ kind: 'textEdit', uri, edits: chunk, done: false });
|
1228
|
+
}
|
1229
|
+
chatRequest.response.updateContent({ kind: 'textEdit', uri, edits: [], done: true });
|
1230
|
+
if (!token.isCancellationRequested) {
|
1231
|
+
chatModel.completeResponse(chatRequest);
|
1232
|
+
}
|
1233
|
+
const isSettled = derived(r => {
|
1234
|
+
const entry = editSession?.readEntry(uri, r);
|
1235
|
+
if (!entry) {
|
1236
|
+
return false;
|
1237
|
+
}
|
1238
|
+
const state = entry.state.read(r);
|
1239
|
+
return state === ModifiedFileEntryState.Accepted || state === ModifiedFileEntryState.Rejected;
|
1240
|
+
});
|
1241
|
+
const whenDecided = waitForState(isSettled, Boolean);
|
1242
|
+
await raceCancellation(whenDecided, token);
|
1243
|
+
store.dispose();
|
1244
|
+
return true;
|
1245
|
+
}
|
1246
|
+
async function reviewNotebookEdits(accessor, uri, stream, token) {
|
1247
|
+
const chatService = accessor.get(IChatService);
|
1248
|
+
const notebookService = accessor.get(INotebookService);
|
1249
|
+
const isNotebook = notebookService.hasSupportedNotebooks(uri);
|
1250
|
+
const chatModel = chatService.startSession(ChatAgentLocation.Editor, token, false);
|
1251
|
+
chatModel.startEditingSession(true);
|
1252
|
+
const editSession = await chatModel.editingSessionObs?.promise;
|
1253
|
+
const store = ( new DisposableStore());
|
1254
|
+
store.add(chatModel);
|
1255
|
+
const chatRequest = chatModel?.addRequest({ text: '', parts: [] }, { variables: [] }, 0);
|
1256
|
+
assertType(chatRequest.response);
|
1257
|
+
if (isNotebook) {
|
1258
|
+
chatRequest.response.updateContent({ kind: 'notebookEdit', uri, edits: [], done: false });
|
1259
|
+
}
|
1260
|
+
else {
|
1261
|
+
chatRequest.response.updateContent({ kind: 'textEdit', uri, edits: [], done: false });
|
1262
|
+
}
|
1263
|
+
for await (const chunk of stream) {
|
1264
|
+
if (token.isCancellationRequested) {
|
1265
|
+
chatRequest.response.cancel();
|
1266
|
+
break;
|
1267
|
+
}
|
1268
|
+
if (chunk.every(isCellEditOperation)) {
|
1269
|
+
chatRequest.response.updateContent({ kind: 'notebookEdit', uri, edits: chunk, done: false });
|
1270
|
+
}
|
1271
|
+
else {
|
1272
|
+
chatRequest.response.updateContent({ kind: 'textEdit', uri: chunk[0], edits: chunk[1], done: false });
|
1273
|
+
}
|
1274
|
+
}
|
1275
|
+
if (isNotebook) {
|
1276
|
+
chatRequest.response.updateContent({ kind: 'notebookEdit', uri, edits: [], done: true });
|
1277
|
+
}
|
1278
|
+
else {
|
1279
|
+
chatRequest.response.updateContent({ kind: 'textEdit', uri, edits: [], done: true });
|
1280
|
+
}
|
1281
|
+
if (!token.isCancellationRequested) {
|
1282
|
+
chatRequest.response.complete();
|
1283
|
+
}
|
1284
|
+
const isSettled = derived(r => {
|
1285
|
+
const entry = editSession?.readEntry(uri, r);
|
1286
|
+
if (!entry) {
|
1287
|
+
return false;
|
1288
|
+
}
|
1289
|
+
const state = entry.state.read(r);
|
1290
|
+
return state === ModifiedFileEntryState.Accepted || state === ModifiedFileEntryState.Rejected;
|
1291
|
+
});
|
1292
|
+
const whenDecided = waitForState(isSettled, Boolean);
|
1293
|
+
await raceCancellation(whenDecided, token);
|
1294
|
+
store.dispose();
|
1295
|
+
return true;
|
1296
|
+
}
|
1297
|
+
function isCellEditOperation(edit) {
|
1298
|
+
if (URI.isUri(edit)) {
|
1299
|
+
return false;
|
1300
|
+
}
|
1301
|
+
if (Array.isArray(edit)) {
|
1302
|
+
return false;
|
1303
|
+
}
|
1304
|
+
return true;
|
1305
|
+
}
|
1306
|
+
async function moveToPanelChat(accessor, model) {
|
1307
|
+
const viewsService = accessor.get(IViewsService);
|
1308
|
+
const chatService = accessor.get(IChatService);
|
1309
|
+
const widget = await showChatView(viewsService);
|
1310
|
+
if (widget && widget.viewModel && model) {
|
1311
|
+
for (const request of model.getRequests().slice()) {
|
1312
|
+
await chatService.adoptRequest(widget.viewModel.model.sessionId, request);
|
1313
|
+
}
|
1314
|
+
widget.focusLastMessage();
|
1315
|
+
}
|
1316
|
+
}
|
1317
|
+
|
1318
|
+
export { InlineChatController, InlineChatController1, InlineChatController2, InlineChatRunOptions, State, reviewEdits, reviewNotebookEdits };
|