package tools import ( "fmt" "os" "strings" "git.mlow.ca/mlow/lmcli/pkg/lmcli/model" toolutil "git.mlow.ca/mlow/lmcli/pkg/lmcli/tools/util" ) const READ_FILE_DESCRIPTION = `Read the contents of a text file relative to the current working directory. Each line of the returned content is prefixed with its line number and a tab (\t). Example result: { "message": "success", "result": "1\tthe contents\n2\tof the file\n" }` var ReadFileTool = model.Tool{ Name: "read_file", Description: READ_FILE_DESCRIPTION, Parameters: []model.ToolParameter{ { Name: "path", Type: "string", Description: "Path to a file within the current working directory to read.", Required: true, }, }, Impl: func(tool *model.Tool, args map[string]interface{}) (string, error) { tmp, ok := args["path"] if !ok { return "", fmt.Errorf("Path parameter to read_file was not included.") } path, ok := tmp.(string) if !ok { return "", fmt.Errorf("Invalid path in function arguments: %v", tmp) } result := readFile(path) ret, err := result.ToJson() if err != nil { return "", fmt.Errorf("Could not serialize result: %v", err) } return ret, nil }, } func readFile(path string) model.CallResult { ok, reason := toolutil.IsPathWithinCWD(path) if !ok { return model.CallResult{Message: reason} } data, err := os.ReadFile(path) if err != nil { return model.CallResult{Message: fmt.Sprintf("Could not read path: %s", err.Error())} } lines := strings.Split(string(data), "\n") content := strings.Builder{} for i, line := range lines { content.WriteString(fmt.Sprintf("%d\t%s\n", i+1, line)) } return model.CallResult{ Result: content.String(), } }