-
Notifications
You must be signed in to change notification settings - Fork 6
🤖 Add file_list tool with recursive structure #286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
ammar-agent
wants to merge
16
commits into
main
Choose a base branch
from
add-file-list-tool
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3d6c7ef to
5bc3ea3
Compare
- Implements recursive directory listing with depth control - Returns nested JSON structure for easy model interpretation - Respects .gitignore patterns by default (configurable) - Supports glob pattern filtering (*.ts, **/*.test.ts) - Enforces hard limit of 128 entries (fails fast vs truncate) - Always hides .git directory - Includes comprehensive test suite (18 tests) - UI component with tree visualization
- Replace CSS modules with Emotion styled components (matches project pattern) - Use shared ToolPrimitives and toolUtils for consistent styling - Reduce DEFAULT_MAX_ENTRIES from 100 to 64 - Update tests to reflect new limit
The ig (ignore instance) is loaded once from .gitignore and passed through recursion for efficiency. This avoids re-parsing .gitignore at every directory level.
- Remove ig and rootPath from TraversalOptions interface - Convert buildFileTree to inner function that captures these via closure - Cleaner interface - only exposes actual options, not implementation details - Same efficiency - still loads .gitignore once - Net: -5 lines
- Remove unused FileListToolArgs import
- Remove unused 'err' variables in catch blocks
- Replace {} as any with proper AbortController signal in tests
- Return formatted tree string in 'output' field instead of recursive JSON 'entries' - Saves ~50% tokens for typical listings - Format function handles tree characters (├─, └─, │) and file sizes - Updated UI to display pre-formatted output string - Updated all tests to validate string output instead of structured data
The file_list tool is already handled by GenericToolCall at the end of ToolMessage.tsx, so the custom FileListToolCall component and routing were never actually used. Removed to fix lint errors.
- Add import for FileListToolCall component - Add isFileListTool type guard using Zod schema - Add routing case for file_list tool - Fix status type: use ToolStatus instead of custom status strings - Update status checks: 'completed'/'failed'/'executing' instead of 'complete'/'error'/'streaming' Fixes component routing so file_list tool calls render correctly in UI.
…tern - Add ToolIcon component in shared/ToolIcon.tsx - Update all tool components to use ToolIcon (except GenericToolCall) - BashToolCall: 🔧 bash - FileReadToolCall: 📖 file_read - FileListToolCall: 📖 file_list (changed from 📋) - FileEditToolCall: ✏️ file_edit_* - TodoToolCall: 📋 todo_write - ProposePlanToolCall: 📋 propose_plan (added tooltip) - GenericToolCall remains unchanged (text-only fallback) - Consistent tooltip pattern: hover over emoji shows full tool name This abstracts the emoji+tooltip pattern into a single reusable component, ensures consistency across all specialized tool displays, and unifies the file_read and file_list emojis to 📖.
Add trailing slash to displayed path in FileListToolCall to clearly indicate it's a directory being listed. Only affects display - the actual tool arg remains unchanged.
Change formatSize() to use Math.round() instead of toFixed(1): - Before: 1.5KB, 2.3MB - After: 2KB, 2MB No decimals in file sizes preserves tokens in LLM output without sacrificing meaningful precision for directory listings. Tests still pass as they use regex patterns matching both formats.
Replace fs.readdir() with fs.opendir() async iterator: - More memory efficient: doesn't allocate full array for large directories - Early termination: stops reading if we collect 2x the limit (accounts for filtering) - Proper cleanup: uses finally block to ensure dirHandle.close() For huge directories (1000+ files), this prevents unnecessary memory allocation when we only need the first 64 entries. The 2x multiplier ensures we read enough entries to account for gitignore filtering and pattern matching.
Replace try/finally with 'using' declaration for automatic resource cleanup. This prevents ERR_DIR_CLOSED errors when the async iterator auto-closes the directory handle and then finally block tries to close it again. Key changes: - Wrap Dir in AsyncDisposable object with Symbol.asyncDispose - Use Promise.resolve() to handle Bun's synchronous close() behavior - Properly catch errors if handle is already closed - Tests verify correct cleanup in all scenarios (early break, full iteration) The 'using' pattern ensures cleanup happens at scope exit, even with early returns or exceptions, while gracefully handling double-close.
5bc3ea3 to
e7d7327
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Generated with
cmuxSummary
Adds
file_listtool for directory exploration without spawning bash processes. Returns recursive JSON tree structure that models can easily interpret.Key Features
Recursive structure: Results nest via
childrenarrays - models see hierarchy directly without parsing paths.Gitignore by default: Respects
.gitignorepatterns automatically (.gitalways hidden). Setgitignore: falseto see all files.Pattern filtering: Glob support (
*.ts,**/*.test.ts). Prunes empty directories when patterns are used.Limit enforcement: 128 entry hard cap. Fails with actionable error message instead of truncating (matches bash tool philosophy).
UI: Tree visualization with file sizes and proper indentation.
Implementation
src/services/tools/file_list.ts(273 lines)minimatch(glob),ignore(.gitignore parsing)FileListToolCallcomponent with CSS modulesExample Usage
Testing