fix(shell): search past file completion limit - #2551
Conversation
|
|
||
| self._cached_paths = paths | ||
| self._cache_scope = scope | ||
| self._cache_query = fragment if self._is_git is False and scope is None else None |
There was a problem hiding this comment.
🟡 Completion suggestions for one search can be reused for a different search in projects where git listing fails
The completion cache is tagged as having no specific search text (self._cache_query = ... else None at src/kimi_cli/ui/shell/prompt.py:745) even when the file results were actually narrowed to a single search text, so a later different search reuses the earlier search's suggestions.
Impact: In an affected project, typing one @ query and then a different one within a couple of seconds can show stale or empty completion results.
Mechanism: query-specific fallback results cached with a null query key
When _is_git is truthy but list_files_git returns None (git is present but git ls-files fails/times out), paths stays None and the code falls through to the query-aware walk with query=fragment (src/kimi_cli/ui/shell/prompt.py:735-741). The returned paths are therefore filtered to fragment. However, self._cache_query is written as fragment if self._is_git is False and scope is None else None (src/kimi_cli/ui/shell/prompt.py:745) — since _is_git is True, it is set to None. On the next call with a different fragment, the invalidation guard if cache_valid and self._is_git is False and scope is None: cache_valid = self._cache_query == fragment (src/kimi_cli/ui/shell/prompt.py:716-717) does not fire (because _is_git is True), and if the .git/index mtime is unchanged the cache is treated as valid, returning the previous query's filtered paths. The downstream FuzzyCompleter then re-filters that stale subset against the new fragment, typically yielding wrong or empty suggestions until the 2s refresh interval expires. The cache key should track whether the query walk was actually used (i.e. whenever the fallback walk ran with a non-None query), not whether _is_git is False.
Prompt for agents
In _get_deep_paths in src/kimi_cli/ui/shell/prompt.py, the fallback walk is invoked with query=fragment whenever scope is None and the git listing did not produce results (this includes the case where _is_git is True but list_files_git returned None). However both the cache-write (self._cache_query = fragment if self._is_git is False and scope is None else None) and the cache-validity guard (if cache_valid and self._is_git is False and scope is None: cache_valid = self._cache_query == fragment) only account for the _is_git is False case. As a result, when git is detected but ls-files fails, query-specific fallback results get cached under a None query key and are incorrectly reused for a different subsequent query within the refresh interval. Fix by keying the cache on whether the query walk actually ran (e.g. track a boolean of whether paths came from list_files_walk with a non-None query, and store/compare _cache_query accordingly), rather than conditioning on _is_git is False. Ensure the validity guard uses the same condition as the write side.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
@completion queriesReproduction and verification
A non-Git directory with 1100 early-sorting files deterministically hid a later matching target. The bounded query-aware scan now finds it, and a second regression test verifies consecutive different queries do not reuse stale subsets.
Closes #1610