(input any, toolUseData *uctypes.UIMessageDataToolUse)
| 229 | } |
| 230 | |
| 231 | func readTextFileCallback(input any, toolUseData *uctypes.UIMessageDataToolUse) (any, error) { |
| 232 | const ReadLimit = 1024 * 1024 * 1024 |
| 233 | |
| 234 | params, err := parseReadTextFileInput(input) |
| 235 | if err != nil { |
| 236 | return nil, err |
| 237 | } |
| 238 | |
| 239 | expandedPath, err := wavebase.ExpandHomeDir(params.Filename) |
| 240 | if err != nil { |
| 241 | return nil, fmt.Errorf("failed to expand path: %w", err) |
| 242 | } |
| 243 | |
| 244 | if !filepath.IsAbs(expandedPath) { |
| 245 | return nil, fmt.Errorf("path must be absolute, got relative path: %s", params.Filename) |
| 246 | } |
| 247 | |
| 248 | if blocked, reason := isBlockedFile(expandedPath); blocked { |
| 249 | return nil, fmt.Errorf("access denied: potentially sensitive file: %s", reason) |
| 250 | } |
| 251 | |
| 252 | fileInfo, err := os.Stat(expandedPath) |
| 253 | if err != nil { |
| 254 | return nil, fmt.Errorf("failed to stat file: %w", err) |
| 255 | } |
| 256 | |
| 257 | if fileInfo.IsDir() { |
| 258 | return nil, fmt.Errorf("path is a directory, cannot be read with the read_text_file tool. use the read_dir tool if available to read directories") |
| 259 | } |
| 260 | |
| 261 | file, err := os.Open(expandedPath) |
| 262 | if err != nil { |
| 263 | return nil, fmt.Errorf("failed to open file: %w", err) |
| 264 | } |
| 265 | defer file.Close() |
| 266 | |
| 267 | totalSize := fileInfo.Size() |
| 268 | modTime := fileInfo.ModTime() |
| 269 | |
| 270 | initialBuf := make([]byte, min(8192, int(totalSize))) |
| 271 | n, err := file.Read(initialBuf) |
| 272 | if err != nil && err != io.EOF { |
| 273 | return nil, fmt.Errorf("failed to read file: %w", err) |
| 274 | } |
| 275 | initialBuf = initialBuf[:n] |
| 276 | |
| 277 | if utilfn.IsBinaryContent(initialBuf) { |
| 278 | return nil, fmt.Errorf("file appears to be binary content") |
| 279 | } |
| 280 | |
| 281 | origin := *params.Origin |
| 282 | offset := *params.Offset |
| 283 | count := *params.Count |
| 284 | maxBytes := *params.MaxBytes |
| 285 | |
| 286 | var lines []string |
| 287 | var stopReason string |
| 288 |
nothing calls this directly
no test coverage detected