@@ -8,7 +8,7 @@ export interface LineRange {
88
99export interface FileMetadata {
1010 fileName : string
11- mtime : string
11+ mtime : number
1212 lineRanges : LineRange [ ]
1313}
1414
@@ -24,9 +24,9 @@ export interface ConversationMessage {
2424}
2525
2626type CacheResult =
27- | { status : "ALLOW_ALL" }
27+ | { status : "ALLOW_ALL" ; rangesToRead : LineRange [ ] }
2828 | { status : "ALLOW_PARTIAL" ; rangesToRead : LineRange [ ] }
29- | { status : "REJECT_ALL" }
29+ | { status : "REJECT_ALL" ; rangesToRead : LineRange [ ] }
3030
3131/**
3232 * Checks if two line ranges overlap.
@@ -44,7 +44,7 @@ function rangesOverlap(r1: LineRange, r2: LineRange): boolean {
4444 * @param toSubtract - The range to subtract.
4545 * @returns An array of ranges remaining after subtraction.
4646 */
47- function subtractRange ( from : LineRange , toSubtract : LineRange ) : LineRange [ ] {
47+ export function subtractRange ( from : LineRange , toSubtract : LineRange ) : LineRange [ ] {
4848 // No overlap
4949 if ( from . end < toSubtract . start || from . start > toSubtract . end ) {
5050 return [ from ]
@@ -61,6 +61,19 @@ function subtractRange(from: LineRange, toSubtract: LineRange): LineRange[] {
6161 return remainingRanges
6262}
6363
64+ /**
65+ * Subtracts a set of ranges from another set of ranges.
66+ */
67+ export function subtractRanges ( originals : LineRange [ ] , toRemoves : LineRange [ ] ) : LineRange [ ] {
68+ let remaining = [ ...originals ]
69+
70+ for ( const toRemove of toRemoves ) {
71+ remaining = remaining . flatMap ( ( original ) => subtractRange ( original , toRemove ) )
72+ }
73+
74+ return remaining
75+ }
76+
6477/**
6578 * Processes a read request against cached file data in conversation history.
6679 * @param requestedFilePath - The full path of the file being requested.
@@ -85,7 +98,7 @@ export async function processAndFilterReadRequest(
8598 // This logic is simplified; in a real scenario, you'd get the line count.
8699 // For this example, we'll assume we can't determine the full range without reading the file,
87100 // so we proceed with ALLOW_ALL if no ranges are specified.
88- return { status : "ALLOW_ALL" }
101+ return { status : "ALLOW_ALL" , rangesToRead : requestedRanges }
89102 }
90103
91104 for ( const message of conversationHistory ) {
@@ -107,20 +120,20 @@ export async function processAndFilterReadRequest(
107120 }
108121
109122 if ( rangesToRead . length === 0 ) {
110- return { status : "REJECT_ALL" }
123+ return { status : "REJECT_ALL" , rangesToRead : [ ] }
111124 } else if ( rangesToRead . length < requestedRanges . length ) {
112125 return { status : "ALLOW_PARTIAL" , rangesToRead }
113126 } else {
114- return { status : "ALLOW_ALL" }
127+ return { status : "ALLOW_ALL" , rangesToRead : requestedRanges }
115128 }
116129 } catch ( error ) {
117130 // If we can't get file stats, it's safer to allow the read.
118131 if ( error . code === "ENOENT" ) {
119132 // File doesn't exist, let the regular tool handle it.
120- return { status : "ALLOW_ALL" }
133+ return { status : "ALLOW_ALL" , rangesToRead : requestedRanges }
121134 }
122135 console . error ( `Error processing file read request for ${ requestedFilePath } :` , error )
123136 // On other errors, allow the read to proceed to handle it.
124- return { status : "ALLOW_ALL" }
137+ return { status : "ALLOW_ALL" , rangesToRead : requestedRanges }
125138 }
126139}
0 commit comments