44} from '@codebuff/common/util/file'
55import { sampleSizeWithSeed } from '@codebuff/common/util/random'
66
7- import { countTokens , countTokensJson } from '../util/token-counter'
7+ import { countTokens } from '../util/token-counter'
88
99import type { Logger } from '@codebuff/common/types/contracts/logger'
1010import type {
@@ -32,7 +32,7 @@ export const truncateFileTreeBasedOnTokenBudget = (params: {
3232 const filteredTree = removeUnimportantFiles ( fileTree )
3333
3434 const treeWithTokens = printFileTreeWithTokens ( filteredTree , fileTokenScores )
35- const treeWithTokensCount = countTokensJson ( treeWithTokens )
35+ const treeWithTokensCount = countTokens ( treeWithTokens )
3636
3737 if ( treeWithTokensCount <= tokenBudget ) {
3838 return {
@@ -43,14 +43,14 @@ export const truncateFileTreeBasedOnTokenBudget = (params: {
4343 }
4444
4545 const printedFilteredTree = printFileTree ( filteredTree )
46- const filteredTreeNoTokensCount = countTokensJson ( printedFilteredTree )
46+ const filteredTreeNoTokensCount = countTokens ( printedFilteredTree )
4747
4848 if ( filteredTreeNoTokensCount <= tokenBudget ) {
4949 const filteredTreeWithTokens = printFileTreeWithTokens (
5050 filteredTree ,
5151 fileTokenScores ,
5252 )
53- const filteredTreeWithTokensCount = countTokensJson ( filteredTreeWithTokens )
53+ const filteredTreeWithTokensCount = countTokens ( filteredTreeWithTokens )
5454 if ( filteredTreeWithTokensCount <= tokenBudget ) {
5555 if ( DEBUG ) {
5656 logger . debug (
@@ -120,10 +120,11 @@ export const truncateFileTreeBasedOnTokenBudget = (params: {
120120
121121 // Sample 30 random files and count their tokens together
122122 const sampleCount = Math . min ( 30 , sortedFiles . length )
123+ const sampleSeed = `${ sortedFiles . length } :${ sampleCount } :${ sortedFiles [ 0 ] ?. path ?? '' } :${ sortedFiles [ sortedFiles . length - 1 ] ?. path ?? '' } `
123124 const sampleFiles = sampleSizeWithSeed (
124125 sortedFiles ,
125126 sampleCount ,
126- JSON . stringify ( sortedFiles ) + JSON . stringify ( sampleCount ) ,
127+ sampleSeed ,
127128 )
128129 const sampleText = sampleFiles . map ( ( f ) => f . node . name ) . join ( ' ' )
129130 const sampleTokens = countTokens ( sampleText )
@@ -168,7 +169,7 @@ export const truncateFileTreeBasedOnTokenBudget = (params: {
168169 . filter ( ( n ) : n is FileTreeNode => n !== null )
169170
170171 currentPrintedTree = printFileTree ( currentTree )
171- currentTokenCount = countTokensJson ( currentPrintedTree )
172+ currentTokenCount = countTokens ( currentPrintedTree )
172173
173174 // Safety check - if we're not making progress, break
174175 if ( currentTokenCount >= previousTokenCount ) {
@@ -241,7 +242,7 @@ function pruneFileTokenScores(params: {
241242 . sort ( ( a , b ) => a . score - b . score )
242243
243244 let printedTree = printFileTreeWithTokens ( fileTree , fileTokenScores )
244- let totalTokens = countTokensJson ( printedTree )
245+ let totalTokens = countTokens ( printedTree )
245246
246247 if ( totalTokens <= tokenBudget ) {
247248 return { pruned : fileTokenScores , printedTree, tokenCount : totalTokens }
@@ -263,7 +264,7 @@ function pruneFileTokenScores(params: {
263264
264265 let index = initialKeepIndex
265266 printedTree = printFileTreeWithTokens ( fileTree , pruned )
266- totalTokens = countTokensJson ( printedTree )
267+ totalTokens = countTokens ( printedTree )
267268
268269 while ( totalTokens > tokenBudget && index < sortedTokens . length ) {
269270 const remainingToRemove = totalTokens - tokenBudget
@@ -282,7 +283,7 @@ function pruneFileTokenScores(params: {
282283
283284 // Note: The below function can take a while, so we optimized to have few loop iterations.
284285 printedTree = printFileTreeWithTokens ( fileTree , pruned )
285- totalTokens = countTokensJson ( printedTree )
286+ totalTokens = countTokens ( printedTree )
286287 index += batchSize
287288 }
288289
@@ -309,9 +310,8 @@ const removeUnimportantFiles = (fileTree: FileTreeNode[]): FileTreeNode[] => {
309310 if ( node . type === 'directory' ) {
310311 // Filter out common build/cache directories
311312 const dirPath = node . filePath . toLowerCase ( )
312- const isUnimportantDir = unimportantExtensions . some (
313- ( ext ) =>
314- ext . startsWith ( '/' ) && ext . endsWith ( '/' ) && dirPath . includes ( ext ) ,
313+ const isUnimportantDir = UNIMPORTANT_DIR_PATTERNS . some ( ( dir ) =>
314+ dirPath . includes ( dir ) ,
315315 )
316316 if ( isUnimportantDir ) {
317317 return false
@@ -323,15 +323,26 @@ const removeUnimportantFiles = (fileTree: FileTreeNode[]): FileTreeNode[] => {
323323 }
324324
325325 const filePath = node . filePath . toLowerCase ( )
326- return ! unimportantExtensions . some (
327- ( ext ) => ! ext . startsWith ( '/' ) && filePath . endsWith ( ext ) ,
328- )
326+ return ! UNIMPORTANT_EXTENSIONS . some ( ( ext ) => filePath . endsWith ( ext ) )
329327 }
330328
331329 return fileTree . filter ( shouldKeepFile )
332330}
333331
334- const unimportantExtensions = [
332+ const UNIMPORTANT_DIR_PATTERNS = [
333+ // Build output directories
334+ '/dist/' ,
335+ '/build/' ,
336+ '/out/' ,
337+ '/target/' ,
338+
339+ // Package manager directories
340+ '/node_modules/' ,
341+ '/.venv/' ,
342+ '/vendor/' ,
343+ ] as const
344+
345+ const UNIMPORTANT_EXTENSIONS = [
335346 // Generated JavaScript/TypeScript files
336347 '.min.js' ,
337348 '.min.css' ,
@@ -356,17 +367,6 @@ const unimportantExtensions = [
356367 '.gem' ,
357368 '.rbc' ,
358369
359- // Build output directories
360- '/dist/' ,
361- '/build/' ,
362- '/out/' ,
363- '/target/' ,
364-
365- // Package manager directories
366- '/node_modules/' ,
367- '/.venv/' ,
368- '/vendor/' ,
369-
370370 // Logs and temporary files
371371 '.log' ,
372372 '.tmp' ,
@@ -394,7 +394,6 @@ const unimportantExtensions = [
394394 '.exe' ,
395395 '.dll' ,
396396 '.lib' ,
397- '.so' ,
398397
399398 // Media and binary files
400399 '.jpg' ,
@@ -411,4 +410,4 @@ const unimportantExtensions = [
411410 '.tiff' ,
412411 '.tif' ,
413412 '.webp' ,
414- ]
413+ ] as const
0 commit comments