HPD-Agent.ToolHarness.FileSystem
0.9.2
dotnet add package HPD-Agent.ToolHarness.FileSystem --version 0.9.2
NuGet\Install-Package HPD-Agent.ToolHarness.FileSystem -Version 0.9.2
<PackageReference Include="HPD-Agent.ToolHarness.FileSystem" Version="0.9.2" />
<PackageVersion Include="HPD-Agent.ToolHarness.FileSystem" Version="0.9.2" />
<PackageReference Include="HPD-Agent.ToolHarness.FileSystem" />
paket add HPD-Agent.ToolHarness.FileSystem --version 0.9.2
#r "nuget: HPD-Agent.ToolHarness.FileSystem, 0.9.2"
#:package HPD-Agent.ToolHarness.FileSystem@0.9.2
#addin nuget:?package=HPD-Agent.ToolHarness.FileSystem&version=0.9.2
#tool nuget:?package=HPD-Agent.ToolHarness.FileSystem&version=0.9.2
HPD-Agent FileSystem ToolHarness
🚀 Features
Core Operations
- ReadFile - Read file contents with optional line ranges
- WriteFile - Create or update files with permission control
- ListDirectory - Browse directory contents recursively
- EditFile - Smart file editing with diff preview (inspired by Gemini CLI)
Advanced Search
- FindFiles - Glob pattern matching (
**/*.cs,src/**/*.json) - SearchContent - Regex search across files (grep-like)
Safety Features
- 🔒 Workspace isolation - All operations restricted to workspace root
- 🛡️ Permission system - Write operations require explicit approval
- 📏 Size limits - Configurable maximum file size
- 🔍 Encoding detection - Automatic charset detection using UDE
- 🎯 Context-aware - Conditional functions based on configuration
📦 Installation
Via NuGet (when published)
dotnet add package HPD.Agent.ToolHarnesses.FileSystem
Via Project Reference
<ItemGroup>
<ProjectReference Include="path/to/HPD-Agent.ToolHarnesses/HPD-Agent.ToolHarnesses.FileSystem/HPD-Agent.ToolHarnesses.FileSystem.csproj" />
</ItemGroup>
🎯 Quick Start
Option 1: Simple Usage (Default Settings)
using HPD.Agent.ToolHarnesses.FileSystem;
// Just add the ToolHarness - uses current directory with safe defaults
var agent = new AgentBuilder()
.WithToolHarness<FileSystemToolHarness>() // ← That's it!
.Build();
// Default context:
// - workspaceRoot: Current directory
// - enableSearch: true
// - allowOutsideWorkspace: false (secure!)
// - maxFileSize: 10 MB
Option 2: Custom Context (Full Control)
using HPD.Agent.ToolHarnesses.FileSystem;
// 1. Create a custom context
var context = new FileSystemContext(
workspaceRoot: "/path/to/your/project",
allowOutsideWorkspace: false, // Security: keep operations in workspace
respectGitIgnore: true, // Honor .gitignore patterns
respectGeminiIgnore: true, // Honor .geminiignore patterns
maxFileSize: 10_000_000, // 10 MB max per file
enableSearch: true // Enable glob/grep operations
);
// 2. Create ToolHarness instance with context
var fileSystemToolHarness = new FileSystemToolHarness(context);
// 3. Register with AgentBuilder
var agent = new AgentBuilder()
.WithTool(fileSystemToolHarness, context) // ← Pass instance + context
.Build();
Option 3: Using ToolHarnessManager Directly
var context = new FileSystemContext("/workspace");
var ToolHarnessManager = new ToolHarnessManager();
// Register and create functions
ToolHarnessManager.RegisterToolHarness<FileSystemToolHarness>();
var functions = ToolHarnessManager.CreateAllFunctions(context);
// Add to your AI client
chatClient.Tools = functions;
3. Use with Your Agent
// The AI can now call these functions automatically:
var response = await chatClient.CompleteAsync("Read the contents of README.md");
// → AI calls ReadFile("/path/to/your/project/README.md")
var response = await chatClient.CompleteAsync("Find all TypeScript files in src/");
// → AI calls FindFiles("src/**/*.ts")
var response = await chatClient.CompleteAsync("Search for 'TODO' comments in the codebase");
// → AI calls SearchContent("TODO", filePattern: "*.cs")
📖 Available Functions
ReadFile
Read file contents with optional pagination.
// Read entire file
await ReadFile("/absolute/path/to/file.txt");
// Read specific line range (for large files)
await ReadFile("/absolute/path/to/large.log", offset: 100, limit: 50);
Parameters:
absolutePath(required) - Absolute path to the fileoffset(optional) - Starting line number (0-based)limit(optional) - Maximum number of lines to read
Features:
- Automatic encoding detection
- File size validation
- Binary file detection
- Line range support for large files
WriteFile
Create or overwrite files. Requires permission approval.
await WriteFile("/absolute/path/to/file.txt", "Hello, World!");
Parameters:
filePath(required) - Absolute path to the filecontent(required) - Content to write
Features:
- Automatic directory creation
- UTF-8 encoding by default
- Workspace validation
- Permission system integration
ListDirectory
Browse directory contents.
// List current directory
await ListDirectory("/path/to/directory");
// List recursively
await ListDirectory("/path/to/directory", recursive: true);
Parameters:
directoryPath(required) - Absolute path to directoryrecursive(optional) - Include subdirectories
Output:
--- Directory: /path/to/directory ---
[DIR] subfolder/
[FILE] README.md (1.2 KB)
[FILE] package.json (456 B)
Total: 1 directories, 2 files
EditFile
Smart file editing with diff preview. Requires permission approval.
await EditFile(
filePath: "/path/to/file.cs",
oldString: "public class OldName",
newString: "public class NewName"
);
Parameters:
filePath(required) - Absolute path to the fileoldString(required) - Exact text to find (must be unique)newString(required) - Replacement text
Features:
- Uniqueness validation (prevents ambiguous edits)
- Diff preview using DiffPlex
- Workspace validation
- Permission system integration
Output:
✓ File edited successfully: /path/to/file.cs
Changed 1 lines
--- Diff ---
namespace MyApp
{
- public class OldName
+ public class NewName
{
// ...
FindFiles
Find files using glob patterns. Only available when EnableSearch = true.
// Find all C# files
await FindFiles("**/*.cs");
// Find in specific directory
await FindFiles("*.json", searchPath: "config/");
// Complex patterns
await FindFiles("src/**/*.{ts,tsx}");
Parameters:
pattern(required) - Glob pattern (**/*.ext,dir/**/*)searchPath(optional) - Directory to search in
Supported Patterns:
*.cs- All .cs files in current directory**/*.cs- All .cs files recursivelysrc/**/*.json- All .json files under src/*.{ts,tsx}- All .ts and .tsx files
Output:
--- Found 15 files matching '**/*.cs' ---
1. src/Program.cs (2.3 KB, modified 1h ago)
2. src/Models/User.cs (1.8 KB, modified 2d ago)
3. tests/UnitTests.cs (4.1 KB, modified 1w ago)
...
SearchContent
Search for regex patterns in files (grep). Only available when EnableSearch = true.
// Simple text search
await SearchContent("TODO");
// Regex search
await SearchContent(@"class\s+\w+Controller");
// With file filter
await SearchContent("import", filePattern: "*.ts");
// Case-sensitive
await SearchContent("ERROR", caseSensitive: true);
Parameters:
pattern(required) - Regular expression patternsearchPath(optional) - Directory to searchfilePattern(optional) - Glob pattern to filter filescaseSensitive(optional) - Case-sensitive matching
Output:
--- Found 12 matches for 'TODO' ---
File filter: *.cs
File: src/Program.cs
Line 45: // TODO: Implement authentication
Line 102: // TODO: Add error handling
File: src/Services/EmailService.cs
Line 23: // TODO: Use async/await
...
Configuration
FileSystemContext Options
public class FileSystemContext
{
public string WorkspaceRoot { get; } // Required: Base directory
public bool AllowOutsideWorkspace { get; } // Default: false (recommended)
public bool RespectGitIgnore { get; } // Default: true
public bool RespectGeminiIgnore { get; } // Default: true
public long MaxFileSize { get; } // Default: 10 MB
public bool EnableSearch { get; } // Default: true
}
Conditional Functions
Some functions are conditionally available based on context:
FindFilesandSearchContent- Only available whenEnableSearch = true
This is achieved through the [ConditionalFunction] attribute:
[AIFunction<FileSystemContext>]
[ConditionalFunction("EnableSearch")]
public Task<string> FindFiles(...) { }
🛡️ Security & Permissions
Workspace Isolation
All operations are validated against the workspace root:
// Allowed: /workspace/src/file.txt
// Blocked: /etc/passwd
// Blocked: ../../../etc/passwd
Permission System
Write operations require explicit user approval via [RequiresPermission]:
[AIFunction]
[RequiresPermission] // User must approve before execution
public async Task<string> WriteFile(...) { }
File Size Limits
Prevents reading massive files that could crash the agent:
var context = new FileSystemContext(
workspaceRoot: "/workspace",
maxFileSize: 5_000_000 // 5 MB max
);
🔍 Under the Hood
Libraries Used
| Feature | Library | Purpose |
|---|---|---|
| Glob matching | DotNet.Glob |
File pattern matching (**/*.cs) |
| Diff generation | DiffPlex |
Show changes in EditFile |
| Encoding detection | Ude.NetStandard |
Auto-detect file charset |
| .gitignore parsing | MAB.DotIgnore |
Respect ignore patterns |
| Source generation | HPD-Agent.SourceGenerator | Compile-time code generation |
AOT Compatibility
This ToolHarness is fully AOT-compatible:
- No reflection at runtime
- All metadata generated at compile-time
- Manual JSON parsing for parameters
📚 Examples
Example 1: Code Search & Replace
// 1. Find all files with old API usage
var files = await FindFiles("**/*.cs");
// 2. Search for old pattern
var matches = await SearchContent("OldApiClient", filePattern: "*.cs");
// 3. Edit each file
await EditFile(
"/workspace/src/Service.cs",
oldString: "var client = new OldApiClient();",
newString: "var client = new NewApiClient();"
);
Example 2: Documentation Generator
// 1. Find all source files
var sourceFiles = await FindFiles("src/**/*.cs");
// 2. Read each file
var content = await ReadFile("/workspace/src/Program.cs");
// 3. Generate docs and save
await WriteFile(
"/workspace/docs/API.md",
generatedDocumentation
);
Example 3: Log Analysis
// 1. Find log files
var logs = await FindFiles("logs/**/*.log");
// 2. Search for errors
var errors = await SearchContent(
pattern: "ERROR|FATAL",
searchPath: "logs/",
filePattern: "*.log"
);
// 3. Read specific time range from large log
var recentLogs = await ReadFile(
"/workspace/logs/app.log",
offset: 10000, // Skip first 10k lines
limit: 1000 // Read next 1k lines
);
🤝 Contributing
This ToolHarness is part of the HPD-Agent ToolHarness ecosystem. Contributions are welcome!
📄 License
FSL-1.1-ALv2 License - See LICENSE file for details
🔗 Related
- HPD-Agent Core
- HPD-Agent Source Generator
- Gemini CLI - Inspiration for this ToolHarness
Built with ❤️ for the HPD-Agent community
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CliWrap (>= 3.10.5)
- DiffPlex (>= 1.9.0)
- HPD-Agent.Framework (>= 0.9.2)
- JsonSchema.Net.Generation (>= 7.4.1)
- MAB.DotIgnore (>= 3.0.2)
- Microsoft.Extensions.AI (>= 10.11.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.11.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 10.0.13)
- Ude.NetStandard (>= 1.2.0)
-
net8.0
- CliWrap (>= 3.10.5)
- DiffPlex (>= 1.9.0)
- HPD-Agent.Framework (>= 0.9.2)
- JsonSchema.Net.Generation (>= 7.4.1)
- MAB.DotIgnore (>= 3.0.2)
- Microsoft.Extensions.AI (>= 10.11.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.11.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 10.0.13)
- System.Net.Http (>= 4.3.4)
- System.Text.RegularExpressions (>= 4.3.1)
- Ude.NetStandard (>= 1.2.0)
-
net9.0
- CliWrap (>= 3.10.5)
- DiffPlex (>= 1.9.0)
- HPD-Agent.Framework (>= 0.9.2)
- JsonSchema.Net.Generation (>= 7.4.1)
- MAB.DotIgnore (>= 3.0.2)
- Microsoft.Extensions.AI (>= 10.11.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.11.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 10.0.13)
- System.Net.Http (>= 4.3.4)
- System.Text.RegularExpressions (>= 4.3.1)
- Ude.NetStandard (>= 1.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.