@@ -3,6 +3,7 @@ import { findUriInDirs } from "../../util/uri";
33import { ContextRetrievalService } from "../context/ContextRetrievalService" ;
44import { GetLspDefinitionsFunction } from "../types" ;
55import { HelperVars } from "../util/HelperVars" ;
6+ import { openedFilesLruCache } from "../util/openedFilesLruCache" ;
67import { getDiffsFromCache } from "./gitDiffCache" ;
78
89import {
@@ -22,6 +23,7 @@ export interface SnippetPayload {
2223 recentlyVisitedRangesSnippets : AutocompleteCodeSnippet [ ] ;
2324 diffSnippets : AutocompleteDiffSnippet [ ] ;
2425 clipboardSnippets : AutocompleteClipboardSnippet [ ] ;
26+ recentlyOpenedFileSnippets : AutocompleteCodeSnippet [ ] ;
2527}
2628
2729function racePromise < T > ( promise : Promise < T [ ] > , timeout = 100 ) : Promise < T [ ] > {
@@ -103,6 +105,65 @@ const getDiffSnippets = async (
103105 } ) ;
104106} ;
105107
108+ const getSnippetsFromRecentlyOpenedFiles = async (
109+ helper : HelperVars ,
110+ ide : IDE ,
111+ ) : Promise < AutocompleteCodeSnippet [ ] > => {
112+ if ( helper . options . useRecentlyOpened === false ) {
113+ return [ ] ;
114+ }
115+
116+ try {
117+ const currentFileUri = `${ helper . filepath } ` ;
118+
119+ // Get all file URIs excluding the current file
120+ const fileUrisToRead = [ ...openedFilesLruCache . entriesDescending ( ) ]
121+ . filter ( ( [ fileUri , _ ] ) => fileUri !== currentFileUri )
122+ . map ( ( [ fileUri , _ ] ) => fileUri ) ;
123+
124+ // Create an array of promises that each read a file with timeout
125+ const fileReadPromises = fileUrisToRead . map ( ( fileUri ) => {
126+ // Create a promise that resolves to a snippet or null
127+ const readPromise = new Promise < AutocompleteCodeSnippet | null > (
128+ ( resolve ) => {
129+ ide
130+ . readFile ( fileUri )
131+ . then ( ( fileContent ) => {
132+ if ( ! fileContent || fileContent . trim ( ) === "" ) {
133+ resolve ( null ) ;
134+ return ;
135+ }
136+
137+ resolve ( {
138+ filepath : fileUri ,
139+ content : fileContent ,
140+ type : AutocompleteSnippetType . Code ,
141+ } ) ;
142+ } )
143+ . catch ( ( e ) => {
144+ console . error ( `Failed to read file ${ fileUri } :` , e ) ;
145+ resolve ( null ) ;
146+ } ) ;
147+ } ,
148+ ) ;
149+ // Cut off at 80ms via racing promises
150+ return Promise . race ( [
151+ readPromise ,
152+ new Promise < null > ( ( resolve ) => setTimeout ( ( ) => resolve ( null ) , 80 ) ) ,
153+ ] ) ;
154+ } ) ;
155+
156+ // Execute all file reads in parallel
157+ const results = await Promise . all ( fileReadPromises ) ;
158+
159+ // Filter out null results
160+ return results . filter ( Boolean ) as AutocompleteCodeSnippet [ ] ;
161+ } catch ( e ) {
162+ console . error ( "Error processing opened files cache:" , e ) ;
163+ return [ ] ;
164+ }
165+ } ;
166+
106167export const getAllSnippets = async ( {
107168 helper,
108169 ide,
@@ -123,6 +184,7 @@ export const getAllSnippets = async ({
123184 ideSnippets ,
124185 diffSnippets ,
125186 clipboardSnippets ,
187+ recentlyOpenedFileSnippets ,
126188 ] = await Promise . all ( [
127189 racePromise ( contextRetrievalService . getRootPathSnippets ( helper ) ) ,
128190 racePromise (
@@ -133,6 +195,7 @@ export const getAllSnippets = async ({
133195 : [ ] ,
134196 [ ] , // racePromise(getDiffSnippets(ide)) // temporarily disabled, see https://github.com/continuedev/continue/pull/5882,
135197 racePromise ( getClipboardSnippets ( ide ) ) ,
198+ racePromise ( getSnippetsFromRecentlyOpenedFiles ( helper , ide ) ) , // giving this one a little more time to complete
136199 ] ) ;
137200
138201 return {
@@ -143,5 +206,6 @@ export const getAllSnippets = async ({
143206 diffSnippets,
144207 clipboardSnippets,
145208 recentlyVisitedRangesSnippets : helper . input . recentlyVisitedRanges ,
209+ recentlyOpenedFileSnippets,
146210 } ;
147211} ;
0 commit comments