11import * as vscode from "vscode"
22import { buildPreviewPath , getPreviewCommand , getPreviewDir , parseImage , trimEntries } from "../image-preview"
3- import { isAbsolutePath } from "../path-utils"
3+ import { escapeGlob , isAbsolutePath } from "../path-utils"
4+ import { validateFiles } from "./file-links"
45import type { DiffVirtualFile , DiffVirtualProvider } from "../DiffVirtualProvider"
56
67type EditorOpenMessage = {
@@ -68,11 +69,14 @@ export function handleEditorAction(
6869 initialDiffStyle ?: unknown
6970 dataUrl ?: string
7071 filename ?: string
72+ id ?: string
73+ paths ?: string [ ]
7174 } ,
7275 opts : {
7376 dir : ( ) => string
7477 diff ?: DiffVirtualProvider
7578 storage ?: vscode . Uri
79+ post ?: ( msg : unknown ) => void
7680 } ,
7781) : boolean {
7882 if ( message . type === "openFile" ) {
@@ -83,6 +87,18 @@ export function handleEditorAction(
8387 if ( message . content ) openContent ( message . content , message . language )
8488 return true
8589 }
90+ if ( message . type === "validateFiles" ) {
91+ const id = message . id
92+ const paths = message . paths
93+ if ( id && paths && opts . post ) {
94+ const post = opts . post
95+ validateFiles ( opts . dir ( ) , paths ) . then (
96+ ( existing ) => post ( { type : "validateFilesResult" , id, existing } ) ,
97+ ( err ) => console . error ( "[Kilo New] KiloProvider: validateFiles failed:" , err ) ,
98+ )
99+ }
100+ return true
101+ }
86102 if ( message . type === "openExternal" ) {
87103 openExternal ( message . url )
88104 return true
@@ -105,6 +121,56 @@ function openContent(content: string, language?: string): void {
105121 )
106122}
107123
124+ function show ( uri : vscode . Uri , line ?: number , column ?: number ) : void {
125+ vscode . workspace . openTextDocument ( uri ) . then (
126+ ( doc ) => {
127+ const options : vscode . TextDocumentShowOptions = { preview : true }
128+ if ( line !== undefined && line > 0 ) {
129+ const col = column !== undefined && column > 0 ? column - 1 : 0
130+ const pos = new vscode . Position ( line - 1 , col )
131+ options . selection = new vscode . Range ( pos , pos )
132+ }
133+ vscode . window
134+ . showTextDocument ( doc , options )
135+ . then ( undefined , ( err ) => console . error ( "[Kilo New] KiloProvider: Failed to show document:" , uri . fsPath , err ) )
136+ } ,
137+ ( err ) => console . error ( "[Kilo New] KiloProvider: Failed to open file:" , uri . fsPath , err ) ,
138+ )
139+ }
140+
141+ /**
142+ * Fallback when the exact path does not exist: search the session directory by
143+ * filename. Opens the file directly on a single match, prompts on multiple,
144+ * warns on none. The search is scoped to `dir` (the active session's directory)
145+ * via a RelativePattern so it can't cross into another worktree/branch.
146+ */
147+ function findFallback ( dir : string , filePath : string , line ?: number , column ?: number ) : void {
148+ const name = filePath . split ( / [ \\ / ] / ) . pop ( ) || filePath
149+ // VS Code globs don't honor backslash escapes, so bracket-escape metacharacters
150+ // (e.g. `[id].tsx`) instead — otherwise such names never match.
151+ const pattern = new vscode . RelativePattern ( vscode . Uri . file ( dir ) , `**/${ escapeGlob ( name ) } ` )
152+ Promise . resolve ( vscode . workspace . findFiles ( pattern , "**/node_modules/**" , 5 ) ) . then (
153+ ( matches ) => {
154+ if ( matches . length === 1 ) {
155+ show ( matches [ 0 ] , line , column )
156+ return
157+ }
158+ if ( matches . length > 1 ) {
159+ const items = matches . map ( ( m ) => ( { label : vscode . workspace . asRelativePath ( m ) , uri : m } ) )
160+ vscode . window . showQuickPick ( items , { placeHolder : `Multiple matches for "${ name } "` } ) . then (
161+ ( pick ) => {
162+ if ( pick ) show ( pick . uri , line , column )
163+ } ,
164+ ( err ) => console . error ( "[Kilo New] KiloProvider: showQuickPick failed:" , err ) ,
165+ )
166+ return
167+ }
168+ vscode . window . showWarningMessage ( `File not found: ${ filePath } ` )
169+ } ,
170+ ( err : unknown ) => console . error ( "[Kilo New] KiloProvider: findFiles failed:" , err ) ,
171+ )
172+ }
173+
108174function openFile ( dir : string , filePath : string , line ?: number , column ?: number ) : void {
109175 const uri = isAbsolutePath ( filePath ) ? vscode . Uri . file ( filePath ) : vscode . Uri . joinPath ( vscode . Uri . file ( dir ) , filePath )
110176 vscode . workspace . fs . stat ( uri ) . then (
@@ -113,19 +179,8 @@ function openFile(dir: string, filePath: string, line?: number, column?: number)
113179 vscode . commands . executeCommand ( "revealInExplorer" , uri )
114180 return
115181 }
116- vscode . workspace . openTextDocument ( uri ) . then (
117- ( doc ) => {
118- const options : vscode . TextDocumentShowOptions = { preview : true }
119- if ( line !== undefined && line > 0 ) {
120- const col = column !== undefined && column > 0 ? column - 1 : 0
121- const pos = new vscode . Position ( line - 1 , col )
122- options . selection = new vscode . Range ( pos , pos )
123- }
124- vscode . window . showTextDocument ( doc , options )
125- } ,
126- ( err ) => console . error ( "[Kilo New] KiloProvider: Failed to open file:" , uri . fsPath , err ) ,
127- )
182+ show ( uri , line , column )
128183 } ,
129- ( err ) => console . error ( "[Kilo New] KiloProvider: Path does not exist:" , uri . fsPath , err ) ,
184+ ( ) => findFallback ( dir , filePath , line , column ) ,
130185 )
131186}
0 commit comments