@@ -12,7 +12,7 @@ import {
1212import { EditorSelectionChangeEvent } from '@opensumi/ide-editor/lib/browser/types' ;
1313import { IMarkerService } from '@opensumi/ide-markers/lib/common/types' ;
1414
15- import { FileContext , LLMContextService , SerializedContext } from '../../common/llm-context' ;
15+ import { AttachFileContext , FileContext , LLMContextService , SerializedContext } from '../../common/llm-context' ;
1616
1717@Injectable ( )
1818export class LLMContextServiceImpl extends WithEventBus implements LLMContextService {
@@ -27,40 +27,61 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
2727
2828 private isAutoCollecting = false ;
2929
30- private contextFiles : FileContext [ ] = [ ] ;
31-
32- private maxFiles : number = 10 ; // 上下文的最大长度限制
33-
34- private onDidContextFilesChangeEmitter = new Emitter < FileContext [ ] > ( ) ;
30+ private readonly maxAttachFilesLimit = 10 ;
31+ private readonly maxViewFilesLimit = 20 ;
32+ private readonly attachedFiles : FileContext [ ] = [ ] ;
33+ private readonly recentlyViewFiles : FileContext [ ] = [ ] ;
34+ private readonly onDidContextFilesChangeEmitter = new Emitter < { viewed : FileContext [ ] ; attached : FileContext [ ] } > ( ) ;
3535 onDidContextFilesChangeEvent = this . onDidContextFilesChangeEmitter . event ;
3636
37- addFileToContext ( uri : URI , selection ?: [ number , number ] , isManual = true ) : void {
38- this . removeFileFromContext ( uri ) ;
37+ private addFileToList ( file : FileContext , list : FileContext [ ] , maxLimit : number ) {
38+ const existingIndex = list . findIndex ( ( f ) => f . uri . toString ( ) === file . uri . toString ( ) ) ;
39+ if ( existingIndex > - 1 ) {
40+ list . splice ( existingIndex , 1 ) ;
41+ }
3942
40- this . contextFiles . push ( { uri, selection, isManual } ) ;
43+ list . push ( file ) ;
44+ if ( list . length > maxLimit ) {
45+ list . shift ( ) ;
46+ }
47+ }
4148
42- if ( this . contextFiles . length > this . maxFiles ) {
43- this . contextFiles . shift ( ) ;
49+ addFileToContext ( uri : URI , selection ?: [ number , number ] , isManual = false ) : void {
50+ if ( ! uri ) {
51+ return ;
4452 }
4553
54+ const file = { uri, selection } ;
55+ const targetList = isManual ? this . attachedFiles : this . recentlyViewFiles ;
56+ const maxLimit = isManual ? this . maxAttachFilesLimit : this . maxViewFilesLimit ;
57+
58+ this . addFileToList ( file , targetList , maxLimit ) ;
59+ this . notifyContextChange ( ) ;
60+ }
61+
62+ private notifyContextChange ( ) : void {
4663 this . onDidContextFilesChangeEmitter . fire ( this . getAllContextFiles ( ) ) ;
4764 }
4865
4966 cleanFileContext ( ) {
50- this . contextFiles = [ ] ;
51- this . onDidContextFilesChangeEmitter . fire ( this . getAllContextFiles ( ) ) ;
67+ this . attachedFiles . length = 0 ;
68+ this . notifyContextChange ( ) ;
5269 }
5370
5471 private getAllContextFiles ( ) {
55- return [ ...this . contextFiles ] ;
72+ return {
73+ viewed : this . recentlyViewFiles ,
74+ attached : this . attachedFiles ,
75+ } ;
5676 }
5777
58- removeFileFromContext ( uri : URI ) : void {
59- const index = this . contextFiles . findIndex ( ( file ) => file . uri . toString ( ) === uri . toString ( ) ) ;
78+ removeFileFromContext ( uri : URI , isManual = false ) : void {
79+ const targetList = isManual ? this . attachedFiles : this . recentlyViewFiles ;
80+ const index = targetList . findIndex ( ( file ) => file . uri . toString ( ) === uri . toString ( ) ) ;
6081 if ( index > - 1 ) {
61- this . contextFiles . splice ( index , 1 ) ;
62- this . onDidContextFilesChangeEmitter . fire ( this . getAllContextFiles ( ) ) ;
82+ targetList . splice ( index , 1 ) ;
6383 }
84+ this . notifyContextChange ( ) ;
6485 }
6586
6687 startAutoCollection ( ) : void {
@@ -78,8 +99,7 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
7899 if ( event . payload . uri . scheme !== 'file' ) {
79100 return ;
80101 }
81- // FIXME: 暂时不自动添加
82- // this.addFileToContext(event.payload.uri);
102+ this . addFileToContext ( event . payload . uri , undefined , false ) ;
83103 } ) ,
84104 ) ;
85105
@@ -88,6 +108,8 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
88108 if ( event . payload . scheme !== 'file' ) {
89109 return ;
90110 }
111+
112+ this . removeFileFromContext ( event . payload , false ) ;
91113 } ) ,
92114 ) ;
93115
@@ -109,11 +131,12 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
109131 ] . sort ( ) as [ number , number ] ;
110132
111133 if ( selection [ 0 ] === selection [ 1 ] ) {
112- this . addFileToContext ( event . payload . editorUri , undefined ) ;
134+ this . addFileToContext ( event . payload . editorUri , undefined , false ) ;
113135 } else {
114136 this . addFileToContext (
115137 event . payload . editorUri ,
116138 selection . sort ( ( a , b ) => a - b ) ,
139+ false ,
117140 ) ;
118141 }
119142 }
@@ -127,42 +150,51 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
127150
128151 serialize ( ) : SerializedContext {
129152 const files = this . getAllContextFiles ( ) ;
130- const recentlyViewFiles = files
131- . filter ( ( v ) => ! v . selection )
132- . map ( ( file ) => {
133- const relativePath = URI . file ( this . appConfig . workspaceDir ) . relative ( file . uri ) ;
134- if ( relativePath ) {
135- return relativePath . toString ( ) ;
136- }
137- return file . uri . parent . toString ( ) ;
138- } )
139- . filter ( Boolean ) ;
140-
141- const attachedFiles = files
142- . filter ( ( v ) => v . selection )
143- . map ( ( file ) => {
144- const ref = this . docModelManager . getModelReference ( file . uri ) ;
145- const content = ref ! . instance . getText ( ) ;
146- const lineErrors = this . markerService
147- . getManager ( )
148- . getMarkers ( {
149- resource : file . uri . toString ( ) ,
150- severities : MarkerSeverity . Error ,
151- } )
152- . map ( ( marker ) => marker . message ) ;
153-
154- return {
155- content,
156- lineErrors,
157- path : URI . file ( this . appConfig . workspaceDir ) . relative ( file . uri ) ! . toString ( ) ,
158- language : ref ?. instance . languageId ! ,
159- } ;
160- } )
161- . filter ( Boolean ) ;
153+ const workspaceRoot = URI . file ( this . appConfig . workspaceDir ) ;
162154
163155 return {
164- recentlyViewFiles,
165- attachedFiles,
156+ recentlyViewFiles : this . serializeRecentlyViewFiles ( files . viewed , workspaceRoot ) ,
157+ attachedFiles : this . serializeAttachedFiles ( files . attached , workspaceRoot ) ,
166158 } ;
167159 }
160+
161+ private serializeRecentlyViewFiles ( files : FileContext [ ] , workspaceRoot : URI ) : string [ ] {
162+ return files
163+ . map ( ( file ) => workspaceRoot . relative ( file . uri ) ?. toString ( ) || file . uri . parent . toString ( ) )
164+ . filter ( Boolean ) ;
165+ }
166+
167+ private serializeAttachedFiles ( files : FileContext [ ] , workspaceRoot : URI ) : AttachFileContext [ ] {
168+ return files
169+ . map ( ( file ) => this . serializeAttachedFile ( file , workspaceRoot ) )
170+ . filter ( Boolean ) as unknown as AttachFileContext [ ] ;
171+ }
172+
173+ private serializeAttachedFile ( file : FileContext , workspaceRoot : URI ) {
174+ try {
175+ const ref = this . docModelManager . getModelReference ( file . uri ) ;
176+ if ( ! ref ) {
177+ return null ;
178+ }
179+
180+ return {
181+ content : ref . instance . getText ( ) ,
182+ lineErrors : this . getFileErrors ( file . uri ) ,
183+ path : workspaceRoot . relative ( file . uri ) ! . toString ( ) ,
184+ language : ref . instance . languageId ! ,
185+ } ;
186+ } catch ( e ) {
187+ return null ;
188+ }
189+ }
190+
191+ private getFileErrors ( uri : URI ) : string [ ] {
192+ return this . markerService
193+ . getManager ( )
194+ . getMarkers ( {
195+ resource : uri . toString ( ) ,
196+ severities : MarkerSeverity . Error ,
197+ } )
198+ . map ( ( marker ) => marker . message ) ;
199+ }
168200}
0 commit comments