@@ -14,7 +14,7 @@ import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
14
14
import { IDiffProviderFactoryService } from 'vs/editor/browser/widget/diffEditor/diffProviderFactoryService' ;
15
15
import { EditOperation } from 'vs/editor/common/core/editOperation' ;
16
16
import { Range } from 'vs/editor/common/core/range' ;
17
- import { ITextModel } from 'vs/editor/common/model' ;
17
+ import { EndOfLineSequence , ITextModel } from 'vs/editor/common/model' ;
18
18
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker' ;
19
19
import { IModelService } from 'vs/editor/common/services/model' ;
20
20
import { TestDiffProviderFactoryService } from 'vs/editor/test/browser/diff/testDiffProviderFactoryService' ;
@@ -27,16 +27,16 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
27
27
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock' ;
28
28
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService' ;
29
29
import { IEditorProgressService , IProgressRunner } from 'vs/platform/progress/common/progress' ;
30
- import { IViewDescriptorService } from 'vs/workbench/common/views' ;
30
+ import { IView , IViewDescriptorService } from 'vs/workbench/common/views' ;
31
31
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration' ;
32
32
import { IAccessibleViewService } from 'vs/platform/accessibility/browser/accessibleView' ;
33
- import { IChatAccessibilityService , IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat' ;
33
+ import { IChatAccessibilityService , IChatWidget , IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat' ;
34
34
import { ChatAgentLocation , ChatAgentService , IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents' ;
35
35
import { IChatResponseViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel' ;
36
36
import { InlineChatController , InlineChatRunOptions , State } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController' ;
37
37
import { Session } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession' ;
38
38
import { CTX_INLINE_CHAT_USER_DID_EDIT , EditMode , InlineChatConfigKeys } from 'vs/workbench/contrib/inlineChat/common/inlineChat' ;
39
- import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices' ;
39
+ import { TestViewsService , workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices' ;
40
40
import { IInlineChatSavingService } from '../../browser/inlineChatSavingService' ;
41
41
import { IInlineChatSessionService } from '../../browser/inlineChatSessionService' ;
42
42
import { InlineChatSessionServiceImpl } from '../../browser/inlineChatSessionServiceImpl' ;
@@ -61,6 +61,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
61
61
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices' ;
62
62
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService' ;
63
63
import { RerunAction } from 'vs/workbench/contrib/inlineChat/browser/inlineChatActions' ;
64
+ import { CancellationToken } from 'vs/base/common/cancellation' ;
64
65
65
66
suite ( 'InteractiveChatController' , function ( ) {
66
67
@@ -127,10 +128,13 @@ suite('InteractiveChatController', function () {
127
128
let model : ITextModel ;
128
129
let ctrl : TestController ;
129
130
let contextKeyService : MockContextKeyService ;
131
+ let chatService : IChatService ;
130
132
let chatAgentService : IChatAgentService ;
131
133
let inlineChatSessionService : IInlineChatSessionService ;
132
134
let instaService : TestInstantiationService ;
133
135
136
+ let chatWidget : IChatWidget ;
137
+
134
138
setup ( function ( ) {
135
139
136
140
const serviceCollection = new ServiceCollection (
@@ -141,7 +145,11 @@ suite('InteractiveChatController', function () {
141
145
[ IHoverService , NullHoverService ] ,
142
146
[ IExtensionService , new TestExtensionService ( ) ] ,
143
147
[ IContextKeyService , new MockContextKeyService ( ) ] ,
144
- [ IViewsService , new TestExtensionService ( ) ] ,
148
+ [ IViewsService , new class extends TestViewsService {
149
+ override async openView < T extends IView > ( id : string , focus ?: boolean | undefined ) : Promise < T | null > {
150
+ return { widget : chatWidget ?? null } as any ;
151
+ }
152
+ } ( ) ] ,
145
153
[ IWorkspaceContextService , new TestContextService ( ) ] ,
146
154
[ IChatWidgetHistoryService , new SyncDescriptor ( ChatWidgetHistoryService ) ] ,
147
155
[ IChatWidgetService , new SyncDescriptor ( ChatWidgetService ) ] ,
@@ -193,12 +201,13 @@ suite('InteractiveChatController', function () {
193
201
configurationService . setUserConfiguration ( 'editor' , { } ) ;
194
202
195
203
contextKeyService = instaService . get ( IContextKeyService ) as MockContextKeyService ;
196
-
204
+ chatService = instaService . get ( IChatService ) ;
197
205
chatAgentService = instaService . get ( IChatAgentService ) ;
198
206
199
207
inlineChatSessionService = store . add ( instaService . get ( IInlineChatSessionService ) ) ;
200
208
201
209
model = store . add ( instaService . get ( IModelService ) . createModel ( 'Hello\nWorld\nHello Again\nHello World\n' , null ) ) ;
210
+ model . setEOL ( EndOfLineSequence . LF ) ;
202
211
editor = store . add ( instantiateTestCodeEditor ( instaService , model ) ) ;
203
212
204
213
store . add ( chatAgentService . registerDynamicAgent ( { id : 'testEditorAgent' , ...agentData , } , {
@@ -494,4 +503,143 @@ suite('InteractiveChatController', function () {
494
503
ctrl . finishExistingSession ( ) ;
495
504
await r ;
496
505
} ) ;
506
+
507
+ test ( 'Retry undoes all changes, not just those from the request#5736' , async function ( ) {
508
+
509
+ const text = [
510
+ 'eins-' ,
511
+ 'zwei-' ,
512
+ 'drei-'
513
+ ] ;
514
+
515
+ store . add ( chatAgentService . registerDynamicAgent ( {
516
+ id : 'testEditorAgent2' ,
517
+ ...agentData
518
+ } , {
519
+ async invoke ( request , progress , history , token ) {
520
+ progress ( { kind : 'textEdit' , uri : model . uri , edits : [ { range : new Range ( 1 , 1 , 1 , 1 ) , text : text . shift ( ) ?? '' } ] } ) ;
521
+ return { } ;
522
+ } ,
523
+ } ) ) ;
524
+
525
+ ctrl = instaService . createInstance ( TestController , editor ) ;
526
+ const rerun = new RerunAction ( ) ;
527
+
528
+ model . setValue ( '' ) ;
529
+
530
+ // REQUEST 1
531
+ const p = ctrl . waitFor ( [ ...TestController . INIT_SEQUENCE , State . SHOW_REQUEST , State . SHOW_RESPONSE , State . WAIT_FOR_INPUT ] ) ;
532
+ const r = ctrl . run ( { message : '1' , autoSend : true } ) ;
533
+ await p ;
534
+
535
+ assert . strictEqual ( model . getValue ( ) , 'eins-' ) ;
536
+
537
+ // REQUEST 2
538
+ const p2 = ctrl . waitFor ( [ State . SHOW_REQUEST , State . SHOW_RESPONSE , State . WAIT_FOR_INPUT ] ) ;
539
+ await ctrl . acceptInput ( ) ;
540
+ await p2 ;
541
+
542
+ assert . strictEqual ( model . getValue ( ) , 'zwei-eins-' ) ;
543
+
544
+ // REQUEST 2 - RERUN
545
+ const p3 = ctrl . waitFor ( [ State . SHOW_REQUEST , State . SHOW_RESPONSE , State . WAIT_FOR_INPUT ] ) ;
546
+ await instaService . invokeFunction ( rerun . runInlineChatCommand , ctrl , editor ) ;
547
+ await p3 ;
548
+
549
+ assert . strictEqual ( model . getValue ( ) , 'drei-eins-' ) ;
550
+
551
+ ctrl . finishExistingSession ( ) ;
552
+ await r ;
553
+
554
+ } ) ;
555
+
556
+ test ( 'moving inline chat to another model undoes changes' , async function ( ) {
557
+ const text = [
558
+ 'eins\n' ,
559
+ 'zwei\n'
560
+ ] ;
561
+
562
+ store . add ( chatAgentService . registerDynamicAgent ( {
563
+ id : 'testEditorAgent2' ,
564
+ ...agentData
565
+ } , {
566
+ async invoke ( request , progress , history , token ) {
567
+ progress ( { kind : 'textEdit' , uri : model . uri , edits : [ { range : new Range ( 1 , 1 , 1 , 1 ) , text : text . shift ( ) ?? '' } ] } ) ;
568
+ return { } ;
569
+ } ,
570
+ } ) ) ;
571
+ ctrl = instaService . createInstance ( TestController , editor ) ;
572
+
573
+ // REQUEST 1
574
+ const p = ctrl . waitFor ( [ ...TestController . INIT_SEQUENCE , State . SHOW_REQUEST , State . SHOW_RESPONSE , State . WAIT_FOR_INPUT ] ) ;
575
+ ctrl . run ( { message : '1' , autoSend : true } ) ;
576
+ await p ;
577
+
578
+
579
+ assert . strictEqual ( model . getValue ( ) , 'eins\nHello\nWorld\nHello Again\nHello World\n' ) ;
580
+
581
+ const targetModel = chatService . startSession ( ChatAgentLocation . Editor , CancellationToken . None ) ! ;
582
+ store . add ( targetModel ) ;
583
+ chatWidget = new class extends mock < IChatWidget > ( ) {
584
+ override get viewModel ( ) {
585
+ return { model : targetModel } as any ;
586
+ }
587
+ override focusLastMessage ( ) { }
588
+ } ;
589
+
590
+ const r = ctrl . joinCurrentRun ( ) ;
591
+ await ctrl . viewInChat ( ) ;
592
+
593
+ assert . strictEqual ( model . getValue ( ) , 'Hello\nWorld\nHello Again\nHello World\n' ) ;
594
+ await r ;
595
+ } ) ;
596
+
597
+ test ( 'moving inline chat to another model undoes changes (2 requests)' , async function ( ) {
598
+ const text = [
599
+ 'eins\n' ,
600
+ 'zwei\n'
601
+ ] ;
602
+
603
+ store . add ( chatAgentService . registerDynamicAgent ( {
604
+ id : 'testEditorAgent2' ,
605
+ ...agentData
606
+ } , {
607
+ async invoke ( request , progress , history , token ) {
608
+ progress ( { kind : 'textEdit' , uri : model . uri , edits : [ { range : new Range ( 1 , 1 , 1 , 1 ) , text : text . shift ( ) ?? '' } ] } ) ;
609
+ return { } ;
610
+ } ,
611
+ } ) ) ;
612
+ ctrl = instaService . createInstance ( TestController , editor ) ;
613
+
614
+ // REQUEST 1
615
+ const p = ctrl . waitFor ( [ ...TestController . INIT_SEQUENCE , State . SHOW_REQUEST , State . SHOW_RESPONSE , State . WAIT_FOR_INPUT ] ) ;
616
+ ctrl . run ( { message : '1' , autoSend : true } ) ;
617
+ await p ;
618
+
619
+ assert . strictEqual ( model . getValue ( ) , 'eins\nHello\nWorld\nHello Again\nHello World\n' ) ;
620
+
621
+ // REQUEST 2
622
+ const p2 = ctrl . waitFor ( [ State . SHOW_REQUEST , State . SHOW_RESPONSE , State . WAIT_FOR_INPUT ] ) ;
623
+ await ctrl . acceptInput ( ) ;
624
+ await p2 ;
625
+
626
+ assert . strictEqual ( model . getValue ( ) , 'zwei\neins\nHello\nWorld\nHello Again\nHello World\n' ) ;
627
+
628
+ const targetModel = chatService . startSession ( ChatAgentLocation . Editor , CancellationToken . None ) ! ;
629
+ store . add ( targetModel ) ;
630
+ chatWidget = new class extends mock < IChatWidget > ( ) {
631
+ override get viewModel ( ) {
632
+ return { model : targetModel } as any ;
633
+ }
634
+ override focusLastMessage ( ) { }
635
+ } ;
636
+
637
+ const r = ctrl . joinCurrentRun ( ) ;
638
+
639
+ await ctrl . viewInChat ( ) ;
640
+
641
+ assert . strictEqual ( model . getValue ( ) , 'Hello\nWorld\nHello Again\nHello World\n' ) ;
642
+
643
+ await r ;
644
+ } ) ;
497
645
} ) ;
0 commit comments