11import * as vscode from 'vscode'
22import * as fs from 'fs'
3+ import * as path from 'path'
34import { OriginalFileState } from './types/original-file-state'
45import { handle_restore_preview } from './handlers/restore-preview-handler'
5- import { parse_response , FileItem , DiffItem } from './utils/clipboard-parser'
6+ import {
7+ parse_response ,
8+ FileItem ,
9+ DiffItem ,
10+ RelevantFilesItem
11+ } from './utils/clipboard-parser'
612import { create_safe_path } from '@/utils/path-sanitizer'
713import { dictionary } from '@shared/constants/dictionary'
814import { Logger } from '@shared/utils/logger'
@@ -22,7 +28,8 @@ import {
2228 handle_truncated_edit ,
2329 is_truncation_line
2430} from './handlers/truncated-handler'
25- import { Diff } from 'diff'
31+ import { WorkspaceProvider } from '@/context/providers/workspace/workspace-provider'
32+ import { natural_sort } from '@/utils/natural-sort'
2633
2734export type PreviewData = {
2835 original_states : OriginalFileState [ ]
@@ -45,7 +52,8 @@ export const process_chat_response = async (
4552 args : CommandArgs | undefined ,
4653 chat_response : string ,
4754 context : vscode . ExtensionContext ,
48- panel_provider : PanelProvider
55+ panel_provider : PanelProvider ,
56+ workspace_provider : WorkspaceProvider
4957) : Promise < PreviewData | null > => {
5058 if ( args ?. files_with_content ) {
5159 const result = await handle_restore_preview ( args . files_with_content )
@@ -92,83 +100,72 @@ export const process_chat_response = async (
92100 is_single_root_folder_workspace
93101 } )
94102
95- if ( clipboard_items . some ( ( item ) => item . type == 'completion' ) ) {
96- const completion = clipboard_items . find (
97- ( item ) => item . type == 'completion'
98- ) !
99- const workspace_map = new Map < string , string > ( )
100- vscode . workspace . workspaceFolders ! . forEach ( ( folder ) => {
101- workspace_map . set ( folder . name , folder . uri . fsPath )
102- } )
103- const default_workspace = vscode . workspace . workspaceFolders ! [ 0 ] . uri . fsPath
104- let workspace_root = default_workspace
105- if (
106- completion . workspace_name &&
107- workspace_map . has ( completion . workspace_name )
108- ) {
109- workspace_root = workspace_map . get ( completion . workspace_name ) !
110- }
111- const safe_path = create_safe_path ( workspace_root , completion . file_path )
112- if ( ! safe_path || ! fs . existsSync ( safe_path ) ) {
113- vscode . window . showErrorMessage (
114- dictionary . error_message . FILE_NOT_FOUND ( completion . file_path )
115- )
116- Logger . warn ( {
117- function_name : 'process_chat_response' ,
118- message : 'File not found for code completion.' ,
119- data : { file_path : completion . file_path , safe_path }
120- } )
121- return null
122- }
103+ if ( clipboard_items . some ( ( item ) => item . type == 'relevant-files' ) ) {
104+ const relevant_files_item = clipboard_items . find (
105+ ( item ) => item . type == 'relevant-files'
106+ ) as RelevantFilesItem
123107
124- const document = await vscode . workspace . openTextDocument ( safe_path )
125- const original_content = document . getText ( )
126- const line_index = completion . line - 1
127- const char_index = completion . character - 1
128-
129- if (
130- line_index < 0 ||
131- char_index < 0 ||
132- line_index >= document . lineCount ||
133- char_index > document . lineAt ( line_index ) . text . length
134- ) {
135- vscode . window . showErrorMessage (
136- dictionary . error_message . INVALID_POSITION_FOR_CODE_COMPLETION (
137- completion . file_path
138- )
139- )
140- return null
141- }
142-
143- const position_offset = document . offsetAt (
144- new vscode . Position ( line_index , char_index )
108+ const current_checked_files = workspace_provider . get_checked_files ( )
109+ const relevant_paths_normalized = new Set (
110+ relevant_files_item . file_paths . map ( ( p ) => p . replace ( / \\ / g, '/' ) )
145111 )
146- const new_content =
147- original_content . slice ( 0 , position_offset ) +
148- completion . content +
149- original_content . slice ( position_offset )
150-
151- if ( ! args ) args = { }
152- if ( ! args . original_editor_state ) {
153- args . original_editor_state = {
154- file_path : safe_path ,
155- position : {
156- line : line_index ,
157- character : char_index
112+
113+ const quick_pick_items : {
114+ label : string
115+ picked : boolean
116+ description ?: string
117+ } [ ] = relevant_files_item . file_paths . map ( ( path ) => ( {
118+ label : path ,
119+ picked : true
120+ } ) )
121+
122+ for ( const file_path of current_checked_files ) {
123+ const workspace_root =
124+ workspace_provider . get_workspace_root_for_file ( file_path )
125+ if ( workspace_root ) {
126+ const relative_path = path
127+ . relative ( workspace_root , file_path )
128+ . replace ( / \\ / g, '/' )
129+ if ( ! relevant_paths_normalized . has ( relative_path ) ) {
130+ if ( ! quick_pick_items . some ( ( item ) => item . label == relative_path ) ) {
131+ quick_pick_items . push ( {
132+ label : relative_path ,
133+ picked : false
134+ } )
135+ }
158136 }
159137 }
160138 }
161139
162- clipboard_items = [
163- {
164- type : 'file' ,
165- file_path : completion . file_path ,
166- content : new_content ,
167- workspace_name : completion . workspace_name
140+ quick_pick_items . sort ( ( a , b ) => natural_sort ( a . label , b . label ) )
141+
142+ const selected_items = await vscode . window . showQuickPick ( quick_pick_items , {
143+ canPickMany : true ,
144+ placeHolder : 'Confirm context pruning'
145+ } )
146+
147+ if ( selected_items && selected_items . length > 0 ) {
148+ const workspace_roots = workspace_provider . get_workspace_roots ( )
149+ const files_to_check : string [ ] = [ ]
150+
151+ for ( const selection of selected_items ) {
152+ for ( const root of workspace_roots ) {
153+ const potential_path = path . join ( root , selection . label )
154+ if ( fs . existsSync ( potential_path ) ) {
155+ files_to_check . push ( potential_path )
156+ break
157+ }
158+ }
159+ }
160+
161+ if ( files_to_check . length > 0 ) {
162+ await workspace_provider . set_checked_files ( files_to_check )
163+ vscode . window . showInformationMessage ( `Context updated successfully.` )
168164 }
169- ]
170- }
171- if ( clipboard_items . some ( ( item ) => item . type == 'diff' ) ) {
165+ }
166+
167+ return null
168+ } else if ( clipboard_items . some ( ( item ) => item . type == 'diff' ) ) {
172169 const patches = clipboard_items . filter (
173170 ( item ) : item is DiffItem => item . type == 'diff'
174171 )
@@ -291,6 +288,83 @@ export const process_chat_response = async (
291288
292289 return null
293290 } else {
291+ if ( clipboard_items . some ( ( item ) => item . type == 'completion' ) ) {
292+ const completion = clipboard_items . find (
293+ ( item ) => item . type == 'completion'
294+ ) !
295+ const workspace_map = new Map < string , string > ( )
296+ vscode . workspace . workspaceFolders ! . forEach ( ( folder ) => {
297+ workspace_map . set ( folder . name , folder . uri . fsPath )
298+ } )
299+ const default_workspace = vscode . workspace . workspaceFolders ! [ 0 ] . uri . fsPath
300+ let workspace_root = default_workspace
301+ if (
302+ completion . workspace_name &&
303+ workspace_map . has ( completion . workspace_name )
304+ ) {
305+ workspace_root = workspace_map . get ( completion . workspace_name ) !
306+ }
307+ const safe_path = create_safe_path ( workspace_root , completion . file_path )
308+ if ( ! safe_path || ! fs . existsSync ( safe_path ) ) {
309+ vscode . window . showErrorMessage (
310+ dictionary . error_message . FILE_NOT_FOUND ( completion . file_path )
311+ )
312+ Logger . warn ( {
313+ function_name : 'process_chat_response' ,
314+ message : 'File not found for code completion.' ,
315+ data : { file_path : completion . file_path , safe_path }
316+ } )
317+ return null
318+ }
319+
320+ const document = await vscode . workspace . openTextDocument ( safe_path )
321+ const original_content = document . getText ( )
322+ const line_index = completion . line - 1
323+ const char_index = completion . character - 1
324+
325+ if (
326+ line_index < 0 ||
327+ char_index < 0 ||
328+ line_index >= document . lineCount ||
329+ char_index > document . lineAt ( line_index ) . text . length
330+ ) {
331+ vscode . window . showErrorMessage (
332+ dictionary . error_message . INVALID_POSITION_FOR_CODE_COMPLETION (
333+ completion . file_path
334+ )
335+ )
336+ return null
337+ }
338+
339+ const position_offset = document . offsetAt (
340+ new vscode . Position ( line_index , char_index )
341+ )
342+ const new_content =
343+ original_content . slice ( 0 , position_offset ) +
344+ completion . content +
345+ original_content . slice ( position_offset )
346+
347+ if ( ! args ) args = { }
348+ if ( ! args . original_editor_state ) {
349+ args . original_editor_state = {
350+ file_path : safe_path ,
351+ position : {
352+ line : line_index ,
353+ character : char_index
354+ }
355+ }
356+ }
357+
358+ clipboard_items = [
359+ {
360+ type : 'file' ,
361+ file_path : completion . file_path ,
362+ content : new_content ,
363+ workspace_name : completion . workspace_name
364+ }
365+ ]
366+ }
367+
294368 const files = clipboard_items . filter (
295369 ( item ) : item is FileItem => item . type == 'file'
296370 )
0 commit comments