Skip to content

Commit 45e8d0a

Browse files
feat: Implement Read tool for file system access (#16)
Implements the Read tool feature requested in issue #14. ## Features Implemented - ✅ Tool for reading files from the filesystem - ✅ File path argument support - ✅ Line range functionality for selective reading - ✅ Performance-optimized buffered file reading - ✅ Comprehensive parameter validation - ✅ Both text and JSON output formats - ✅ Example usage through tool parameter definitions ## Technical Details Adds a new `Read` tool to the LLM tool system with: - `file_path`: Required parameter for file to read - `start_line`, `end_line`: Optional line range parameters (1-indexed) - `format`: Output format (text or json) Integrates with existing file service infrastructure and follows established patterns. Closes #14 Generated with [Claude Code](https://claude.ai/code) --------- Signed-off-by: Eden Reich <[email protected]> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Eden Reich <[email protected]>
1 parent 055f23a commit 45e8d0a

File tree

5 files changed

+281
-61
lines changed

5 files changed

+281
-61
lines changed

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This is the Inference Gateway CLI (`infer`), a Go-based command-line tool for ma
1010

1111
**Note: All commands should be run with `flox activate -- <command>` to ensure the proper development environment is activated.**
1212

13+
**IMPORTANT: Always run `task setup` first when working with a fresh checkout of the repository to ensure all dependencies are properly installed.**
14+
1315
### Setup Development Environment
1416
```bash
1517
flox activate -- task setup

internal/container/container.go

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,43 +48,35 @@ func NewServiceContainer(cfg *config.Config) *ServiceContainer {
4848

4949
// initializeDomainServices creates and wires domain service implementations
5050
func (c *ServiceContainer) initializeDomainServices() {
51-
// Create conversation repository
5251
c.conversationRepo = services.NewInMemoryConversationRepository()
5352

54-
// Create model service
5553
c.modelService = services.NewHTTPModelService(
5654
c.config.Gateway.URL,
5755
c.config.Gateway.APIKey,
5856
)
5957

60-
// Create tool service first (needed by chat service)
58+
c.fileService = services.NewLocalFileService()
59+
6160
if c.config.Tools.Enabled {
62-
c.toolService = services.NewLLMToolService(c.config)
61+
c.toolService = services.NewLLMToolService(c.config, c.fileService)
6362
} else {
6463
c.toolService = services.NewNoOpToolService()
6564
}
6665

67-
// Create chat service with tool service
6866
c.chatService = services.NewStreamingChatService(
6967
c.config.Gateway.URL,
7068
c.config.Gateway.APIKey,
7169
c.config.Gateway.Timeout,
7270
c.toolService,
7371
)
74-
75-
// Create file service
76-
c.fileService = services.NewLocalFileService()
7772
}
7873

7974
// initializeUIComponents creates UI components and theme
8075
func (c *ServiceContainer) initializeUIComponents() {
81-
// Create theme based on configuration
8276
c.theme = ui.NewDefaultTheme()
8377

84-
// Create layout manager
8578
c.layout = ui.NewDefaultLayout()
8679

87-
// Create component factory
8880
c.componentFactory = ui.NewComponentFactory(c.theme, c.layout, c.modelService)
8981
}
9082

internal/domain/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ type ToolService interface {
103103
type FileService interface {
104104
ListProjectFiles() ([]string, error)
105105
ReadFile(path string) (string, error)
106+
ReadFileLines(path string, startLine, endLine int) (string, error)
106107
ValidateFile(path string) error
107108
GetFileInfo(path string) (FileInfo, error)
108109
}

internal/services/file.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package services
22

33
import (
4+
"bufio"
45
"fmt"
56
"io/fs"
67
"os"
@@ -161,6 +162,46 @@ func (s *LocalFileService) ReadFile(path string) (string, error) {
161162
return string(content), nil
162163
}
163164

165+
func (s *LocalFileService) ReadFileLines(path string, startLine, endLine int) (string, error) {
166+
if err := s.ValidateFile(path); err != nil {
167+
return "", err
168+
}
169+
170+
file, err := os.Open(path)
171+
if err != nil {
172+
return "", fmt.Errorf("failed to open file: %w", err)
173+
}
174+
defer func() {
175+
_ = file.Close()
176+
}()
177+
178+
scanner := bufio.NewScanner(file)
179+
var result strings.Builder
180+
currentLine := 1
181+
182+
for scanner.Scan() {
183+
if startLine > 0 && currentLine < startLine {
184+
currentLine++
185+
continue
186+
}
187+
if endLine > 0 && currentLine > endLine {
188+
break
189+
}
190+
191+
if result.Len() > 0 {
192+
result.WriteString("\n")
193+
}
194+
result.WriteString(scanner.Text())
195+
currentLine++
196+
}
197+
198+
if err := scanner.Err(); err != nil {
199+
return "", fmt.Errorf("failed to read file lines: %w", err)
200+
}
201+
202+
return result.String(), nil
203+
}
204+
164205
func (s *LocalFileService) ValidateFile(path string) error {
165206
if path == "" {
166207
return fmt.Errorf("file path cannot be empty")

0 commit comments

Comments
 (0)