@@ -124,15 +124,15 @@ function! llama#init()
124124
125125 augroup llama
126126 autocmd !
127- autocmd InsertEnter * inoremap <expr> <silent> <C-F> llama#fim_inline(v:false)
127+ autocmd InsertEnter * inoremap <expr> <silent> <C-F> llama#fim_inline(v:false, v:false )
128128 autocmd InsertLeavePre * call llama#fim_cancel ()
129129
130130 autocmd CursorMoved * call s: on_move ()
131131 autocmd CursorMovedI * call s: on_move ()
132132 autocmd CompleteChanged * call llama#fim_cancel ()
133133
134134 if g: llama_config .auto_fim
135- autocmd CursorMovedI * call llama#fim (v: true )
135+ autocmd CursorMovedI * call llama#fim (v: true, v: true )
136136 endif
137137
138138 " gather chunks upon yanking
@@ -332,14 +332,14 @@ function! s:ring_update()
332332endfunction
333333
334334" necessary for 'inoremap <expr>'
335- function ! llama#fim_inline (is_auto) abort
336- call llama#fim (a: is_auto )
335+ function ! llama#fim_inline (is_auto, cache ) abort
336+ call llama#fim (a: is_auto, a: cache )
337337 return ' '
338338endfunction
339339
340340" the main FIM call
341341" takes local context around the cursor and sends it together with the extra context to the server for completion
342- function ! llama#fim (is_auto) abort
342+ function ! llama#fim (is_auto, cache ) abort
343343 " we already have a suggestion for the current cursor position
344344 if s: hint_shown && ! a: is_auto
345345 call llama#fim_cancel ()
@@ -356,7 +356,7 @@ function! llama#fim(is_auto) abort
356356 endif
357357
358358 let s: t_fim_start = reltime ()
359- let s: timer_fim = timer_start (600 , {- > llama#fim (v: true )})
359+ let s: timer_fim = timer_start (600 , {- > llama#fim (v: true, a: cache )})
360360 return
361361 endif
362362
@@ -445,26 +445,53 @@ function! llama#fim(is_auto) abort
445445 endif
446446 let s: job_error = 0
447447
448- " Construct hash from prefix, suffix, and prompt
449- let l: request_context = l: prefix . " |" . l: suffix . " |" . l: prompt
450- let l: hash = sha256 (l: request_context )
451-
452- " Check if the completion is cached
453- let l: cached_completion = get (g: result_cache , l: hash , v: null )
448+ " Construct hash from prefix, prompt, and suffix
449+ let l: request_context = l: prefix . l: prompt . l: suffix
450+ let l: hash = sha256 (l: request_context )
451+
452+ if a: cache
453+ " Check if the completion is cached
454+ let l: cached_completion = get (g: result_cache , l: hash , v: null )
455+
456+ " ... or if there is a cached completion nearby (10 characters behind)
457+ " Looks at the previous 10 characters to see if a completion is cached. If one is found at (x,y)
458+ " then it checks that the characters typed after (x,y) match up with the cached completion result.
459+ if l: cached_completion == v: null
460+ let l: past_text = l: prefix . l: prompt
461+ for i in range (10 )
462+ let l: hash_txt = l: past_text [:- (2 + i )] . l: suffix
463+ let l: temp_hash = sha256 (l: hash_txt )
464+ if has_key (g: result_cache , l: temp_hash )
465+ let l: temp_cached_completion = get (g: result_cache , l: temp_hash )
466+ if l: temp_cached_completion == " "
467+ break
468+ endif
469+ let l: response = json_decode (l: temp_cached_completion )
470+ if l: response [' content' ][0 : len (l: past_text [- (1 + i ):])-1 ] !=# l: past_text [- (1 + i ):]
471+ break
472+ endif
473+ let l: response [' content' ] = l: response [' content' ][i + 1 :]
474+ let g: result_cache [l: hash ] = json_encode (l: response )
475+ let l: cached_completion = g: result_cache [l: hash ]
476+ break
477+ endif
478+ endfor
479+ endif
480+ endif
454481
455- if l: cached_completion != v: null
456- call s: fim_on_stdout (l: hash , s: pos_x , s: pos_y , a: is_auto , 0 , l: cached_completion )
482+ if a: cache && l: cached_completion != v: null
483+ call s: fim_on_stdout (l: hash , a: cache , s: pos_x , s: pos_y , a: is_auto , 0 , l: cached_completion )
457484 else
458485 " send the request asynchronously
459486 if s: ghost_text_nvim
460487 let s: current_job = jobstart (l: curl_command , {
461- \ ' on_stdout' : function (' s:fim_on_stdout' , [l: hash , s: pos_x , s: pos_y , a: is_auto ]),
488+ \ ' on_stdout' : function (' s:fim_on_stdout' , [l: hash , a: cache , s: pos_x , s: pos_y , a: is_auto ]),
462489 \ ' on_exit' : function (' s:fim_on_exit' ),
463490 \ ' stdout_buffered' : v: true
464491 \ })
465492 elseif s: ghost_text_vim
466493 let s: current_job = job_start (l: curl_command , {
467- \ ' out_cb' : function (' s:fim_on_stdout' , [l: hash , s: pos_x , s: pos_y , a: is_auto ]),
494+ \ ' out_cb' : function (' s:fim_on_stdout' , [l: hash , a: cache , s: pos_x , s: pos_y , a: is_auto ]),
468495 \ ' exit_cb' : function (' s:fim_on_exit' )
469496 \ })
470497 endif
@@ -552,25 +579,28 @@ function! s:on_move()
552579 call llama#fim_cancel ()
553580endfunction
554581
582+ " TODO: Currently the cache uses a random eviction policy. A more clever policy could be implemented (eg. LRU).
583+ function ! s: insert_cache (key , value)
584+ if len (keys (g: result_cache )) > (g: llama_config .max_cache_keys - 1 )
585+ let l: keys = keys (g: result_cache )
586+ let l: hash = l: keys [rand () % len (l: keys )]
587+ call remove (g: result_cache , l: hash )
588+ endif
589+ let g: result_cache [a: key ] = a: value
590+ endfunction
591+
555592" callback that processes the FIM result from the server and displays the suggestion
556- function ! s: fim_on_stdout (hash, pos_x, pos_y, is_auto, job_id, data, event = v: null )
593+ function ! s: fim_on_stdout (hash, cache, pos_x, pos_y, is_auto, job_id, data, event = v: null )
557594 " Retrieve the FIM result from cache
558- " TODO: Currently the cache uses a random eviction policy. A more clever policy could be implemented (eg. LRU).
559- if has_key (g: result_cache , a: hash )
595+ if a: cache && has_key (g: result_cache , a: hash )
560596 let l: raw = get (g: result_cache , a: hash )
561597 else
562598 if s: ghost_text_nvim
563599 let l: raw = join (a: data , " \n " )
564600 elseif s: ghost_text_vim
565601 let l: raw = a: data
566602 endif
567-
568- if len (keys (g: result_cache )) > (g: llama_config .max_cache_keys - 1 )
569- let l: keys = keys (g: result_cache )
570- let l: hash = l: keys [rand () % len (l: keys )]
571- call remove (g: result_cache , l: hash )
572- endif
573- let g: result_cache [a: hash ] = l: raw
603+ call s: insert_cache (a: hash , l: raw )
574604 endif
575605
576606 if a: pos_x != col (' .' ) - 1 || a: pos_y != line (' .' )
0 commit comments